我有一个大小5GB的文件,我想通过块读,说2MB。 使用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
花费相当大量的CPU时间:
由于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;
}
RESULT = 1179852225
在一个循环中捉迷藏这需要平均1179852225毫微秒,这几乎两倍更有效率。
问题:什么是与临界段内的常规文件读取实际问题?