I'm doing some benchmarks of an application written in Java. It is very important for the experiments that the results are not influenced by the page cache (I'm using linux)
So the best way to avoid the page cache is using O_DIRECT whenever a file is opened. I therefore changed the respective code in the sourcecode of the jre.
My approach works perfectly for everything that goes through the FileOutputStream
(e.g. writing), but it does not work for FileInputStream
(e.g. reading).
When adding O_DIRECT to the open-call of FileInputStream
, the JVM is unable to load any classes:
Error: Could not find or load main class perf.TestDirectIO
This error is not a classpath issue, since I can fix it just by using a "unhacked" JVM.
So there seems to be an issue with opening files.
I'm very happy about any advice on how to fix the issue.
If anyone ever wants to do something similar, I've documented the whole hack in my blog.
As a reference, these are the changes on the JVM code I did so:
jdk/src/share/native/java/io/FileInputStream.c
:
@@ -58,7 +60,8 @@
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) {
- fileOpen(env, this, path, fis_fd, O_RDONLY);
+ fileOpen(env, this, path, fis_fd, O_RDONLY | O_DIRECT); // this is the change that causes all the problems
}
This change works:
jdk/src/solaris/native/java/io/FileOutputStream_md.c
:
@@ -55,8 +55,10 @@
JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this,
jstring path, jboolean append) {
fileOpen(env, this, path, fos_fd,
- O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC));
+ O_WRONLY | O_DIRECT | O_CREAT | (append ? O_APPEND : O_TRUNC));
}
I also changed the hotspot jre to ensure that the memory is aligned (thats a requirement for O_DIRECT)
hotspot/src/share/vm/runtime/os.cpp
:
+# include <mm_malloc.h>
...
- u_char* ptr = (u_char*)::malloc(size + space_before + space_after);
+ u_char* ptr = (u_char*)::_mm_malloc(size + space_before + space_after,512);