У меня есть файл размером 5 ГБ, который я хочу прочитать кусками, скажем, 2 МБ.Использование java.io.InputStream
работает нормально.Таким образом, я измерил эту вещь следующим образом:
static final byte[] buffer = new byte[2 * 1024 * 1024];
public static void main(String args[]) throws IOException {
while(true){
InputStream is = new FileInputStream("/tmp/log_test.log");
long bytesRead = 0;
int readCurrent;
long start = System.nanoTime();
while((readCurrent = is.read(buffer)) > 0){
bytesRead += readCurrent;
}
long end = System.nanoTime();
System.out.println(
"Bytes read = " + bytesRead + ". Time elapsed = " + (end - start)
);
}
}
RESULT = 2121714428
Видно, что в среднем требуется 2121714428 нанометров.Это связано с тем, что реализация (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf);
данных считывает в malloc
ed или выделенный в стек буфер, как показано здесь .Так что memcpy
занимает довольно большое количество процессорного времени:
Поскольку спецификация JNI определяет, что
Внутри критическойрегион, собственный код не должен вызывать другие функции JNI или любой системный вызов, который может вызвать блокировку текущего потока и ожидание другого потока Java.(Например, текущий поток не должен вызывать чтение для потока, записываемого другим потоком Java.)
Я не вижу проблем с чтением из обычногофайл в критическом разделе.Чтение из обычного файла блокируется только на короткое время и не зависит от какого-либо потока Java.Примерно так:
static final byte[] buffer = new byte[2 * 1024 * 1024];
public static void main(String args[]) throws IOException {
while (true) {
int fd = open("/tmp/log_test.log");
long bytesRead = 0;
int readCurrent;
long start = System.nanoTime();
while ((readCurrent = read(fd, buffer)) > 0) {
bytesRead += readCurrent;
}
long end = System.nanoTime();
System.out.println("Bytes read = " + bytesRead + ". Time elapsed = " + (end - start));
}
}
private static native int open(String path);
private static native int read(int fd, byte[] buf);
Функции JNI:
JNIEXPORT jint JNICALL Java_com_test_Main_open
(JNIEnv *env, jclass jc, jstring path){
const char *native_path = (*env)->GetStringUTFChars(env, path, NULL);
int fd = open(native_path, O_RDONLY);
(*env)->ReleaseStringUTFChars(env, path, native_path);
return fd;
}
JNIEXPORT jint JNICALL Java_com_test_Main_read
(JNIEnv *env, jclass jc, jint fd, jbyteArray arr){
size_t java_array_size = (size_t) (*env)->GetArrayLength(env, arr);
void *buf = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
ssize_t bytes_read = read(fd, buf, java_array_size);
(*env)->ReleasePrimitiveArrayCritical(env, arr, buf, 0);
return (jint) bytes_read;
}
РЕЗУЛЬТАТ = 1179852225
Выполнение этого в цикле занимает в среднем 1179852225 нано, что почти вдвое эффективнее,
Вопрос: В чем проблема с чтением из обычного файла в критическом разделе?