我正在对用 Java 编写的应用程序进行一些基准测试。实验很重要,结果不受页面缓存的影响(我用的是linux)
因此,避免页面缓存的最佳方法是在打开文件时使用 O_DIRECT。因此,我更改了 jre 源代码中的相应代码。
我的方法非常适用于通过(例如写作)的所有事情FileOutputStream
,但它不适用于FileInputStream
(例如阅读)。
将 O_DIRECT 添加到 的 open-call 时FileInputStream
,JVM 无法加载任何类:
Error: Could not find or load main class perf.TestDirectIO
这个错误不是类路径问题,因为我可以通过使用“未破解”的 JVM 来修复它。
所以打开文件似乎有问题。
对于有关如何解决此问题的任何建议,我感到非常高兴。
如果有人想做类似的事情,我已经在我的博客中记录了整个 hack。
作为参考,这些是我对 JVM 代码所做的更改:
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
}
此更改有效
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));
}
我还更改了热点 jre 以确保内存对齐(这是 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);