FileInputStream
使用此本机方法读取用户提供的缓冲区中的字节。正如我们在实现中看到的那样,用户空间缓冲区确实分配了长度为max(BUF_SIZE, supplied buffer length)
的缓冲区。然后将该缓冲区传递给CCD_ 3。我无法找到这个方法的实现,但我很确定这是标准的C缓冲读取。为什么说FileInputStream
没有缓冲?BufferedReader
使用了什么额外的缓冲?
编辑:比较100M文件读取时间的基准及其结果:
Benchmark Mode Cnt Score Error Units
StreamIOBenchmark.bisMultiBytes avgt 30 27.640 ± 1.117 ms/op
StreamIOBenchmark.bisSingleBytes avgt 30 400.552 ± 26.921 ms/op
StreamIOBenchmark.fisMultiBytes avgt 30 25.231 ± 1.459 ms/op
StreamIOBenchmark.fisSingleBytes avgt 30 97991.213 ± 5620.685 ms/op
真正的区别是在读取单个字节时,因为FIS将为每个字节进行新的系统调用。然而,当一次读取8k字节时,FIS(fisMultiBytes
)和BIS(bisMultiBytes
)的性能非常相似。
FileInputStream
真的没有缓冲吗?
是。真正地
我无法找到这个方法的实现,但我很确定这是标准的C缓冲读取。
不是。本机代码不使用C缓冲I/O。它正在执行对临时缓冲区的read(2)
调用。然后,它将数据从临时缓冲器复制到呼叫者提供的CCD_ 10。
在我正在查看的Java 11u代码中,临时缓冲区是一个较小的堆栈上缓冲区,或者是一个较大的本地堆缓冲区,在native
调用期间为malloc
'd和free
'd。
OpenJDK Java 11u代码库中的相对路径名是./src/java.base/share/native/libjava/io_util.c
。查找readBytes
方法。(这是通过./src/java.base/share/native/libjava/FileInputStream.c
中的本地入口点方法调用的)
io_utils.c
中的IO_Read
是一个别名为handleRead
的宏,它封装了read(2)
调用。
更新
我刚刚注意到您已经找到了指向io_util.c
的Java 8u版本的链接。它的行为方式与我上面描述的11u代码相同。所以,也许你只是看错了你找到的C代码?
为什么说
FileInputStream
没有缓冲?
它是"据说是";因为它确实没有缓冲。
BufferedReader
使用了什么额外的缓冲?
您可以通过查看BufferedReader
的(Java)源代码来了解这一点。
提示:与其对JVM本机代码实现的工作方式做出(错误的)假设,不如下载并阅读OpenJDK源代码。任何有足够磁盘空间(1.2GB)的人都可以下载。