BufferedReader 和 FileReader read() 性能 - 大文本文件

BufferedReader & FileReader read() Performance - Large Text File

我正在使用以下两段代码来读取一个大文件。

这使用 FileReader

File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);

int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    System.out.print((char) ch);
}
long end = System.currentTimeMillis();

下面使用 BufferedReader:

File file = new File("/Users/Desktop/shakes.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));

int ch;
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    System.out.print((char) ch);
}
long end = System.currentTimeMillis();

查看 BufferedReader 的文档:

It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.

鉴于此文档和 BufferedReader 的默认缓冲区大小 8192 class,使用 BufferedReader 读取文件的总时间不应该更快吗?目前,这两段代码 运行 在我的机器上耗时约 3000 毫秒。但是,如果我在 BufferedReader 中使用 'readLine',性能会大大提高(~200 毫秒)。

想念我缺少的东西吗?是不是期望即使使用 'read()' 方法,BufferedReader 也应该提供比从 FileReader 读取更好的性能?

使用 BufferedReader 确实比只使用 FileReader 更快。

我在我的机器上执行了您的代码,使用以下文本文件 https://norvig.com/big.txt (6MB)。

  • 初步结果显示时间大致相同。每个大约 17 秒。
  • 但是,这是因为 System.out.print() 是瓶颈(在循环内)。没有 print,使用 BufferedReader 结果快 4 倍。 200 毫秒与 50 毫秒。 (对比之前的17s)

换句话说,基准测试时不要使用 System.out.print()

例子

使用 StringBuilder.

的改进基准可能如下所示
File file = new File("/Users/Desktop/shakes.txt");
FileReader reader = new FileReader(file);

int ch;
StringBuilder sb = new StringBuilder();
long start = System.currentTimeMillis();
while ((ch = reader.read()) != -1) {
    //System.out.print((char) ch);
    sb.append((char) ch);
}
long end = System.currentTimeMillis();

System.out.println(sb);

以上代码提供相同的输出,但执行速度更快。它将准确显示使用 BufferedReader.

时的速度差异

Thoughts on something that I'm missing?

BufferedReader 中一次读取文件一个字符应该比 FileReader 更快。 (数量级!)所以我怀疑问题出在你的基准测试中。

  1. 您的基准测试同时测量读取文件和将文件写入标准输出。所以基本上,您的性能数据会因 写入 文件的开销而失真。如果你的输出被写入 "console",那么这些开销包括在屏幕上绘制字符的开销......和滚动。

  2. 您的基准测试没有考虑虚拟机启动开销。

  3. 您的基准测试(显然)没有采用文件缓存的效果。 (第一次读取文件时,它将从磁盘读取。如果您稍后再次读取它,您可能从缓存在内存中的文件副本中读取系统。那样会更快。)