Заставить JVM выполнять все операции ввода-вывода без кэширования страниц (например, O_DIRECT)
Я делаю некоторые тесты приложения, написанного на Java. Для экспериментов очень важно, чтобы на результаты не влиял кеш страниц (я использую linux)
Поэтому лучший способ избежать кеша страниц - использовать O_DIRECT при каждом открытии файла. Поэтому я изменил соответствующий код в исходном коде JRE.
Мой подход прекрасно работает для всего, что проходит черезFileOutputStream
(например, запись), но это не работает дляFileInputStream
(например, чтение).
При добавлении O_DIRECT к открытому вызовуFileInputStream
, JVM не может загрузить какие-либо классы:
Error: Could not find or load main class perf.TestDirectIO
Эта ошибка не является проблемой classpath, так как я могу исправить ее, просто используя «не взломанную» JVM.
Так что, похоже, проблема с открытием файлов.
Я очень рад любому совету о том, как решить проблему.
Если кто-то захочет сделать что-то подобное, язадокументировал весь взлом в моем блоге.
Для справки: это изменения в коде 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);