【发布时间】:2017-05-10 12:03:07
【问题描述】:
我需要一次读取一个字符的文件,我正在使用来自BufferedReader 的read() 方法。 *
我发现read() 比readLine() 慢大约 10 倍。这是预期的吗?还是我做错了什么?
这是 Java 7 的基准测试。输入的测试文件有大约 500 万行和 2.54 亿个字符(~242 MB)**:
read() 方法读取所有字符大约需要 7000 毫秒:
@Test
public void testRead() throws IOException, UnindexableFastaFileException{
BufferedReader fa= new BufferedReader(new FileReader(new File("chr1.fa")));
long t0= System.currentTimeMillis();
int c;
while( (c = fa.read()) != -1 ){
//
}
long t1= System.currentTimeMillis();
System.err.println(t1-t0); // ~ 7000 ms
}
readLine() 方法仅需约 700 毫秒:
@Test
public void testReadLine() throws IOException{
BufferedReader fa= new BufferedReader(new FileReader(new File("chr1.fa")));
String line;
long t0= System.currentTimeMillis();
while( (line = fa.readLine()) != null ){
//
}
long t1= System.currentTimeMillis();
System.err.println(t1-t0); // ~ 700 ms
}
* 实际用途:我需要知道每一行的长度,包括换行符(\n 或\r\n)以及剥离后的行长。我还需要知道一行是否以> 字符开头。对于给定的文件,这仅在程序开始时执行一次。由于 BufferedReader.readLine() 没有返回 EOL 字符,因此我使用 read() 方法。如果有更好的方法,请说。
** gzip 压缩文件在这里http://hgdownload.cse.ucsc.edu/goldenpath/hg19/chromosomes/chr1.fa.gz。对于那些可能想知道的人,我正在编写一个类来索引 fasta 文件。
【问题讨论】:
-
请阅读如何编写准确的 Java 基准测试。
-
@Louis Wasserman 诚然,我并不太关心我的基准测试是否准确。 JUnit 和
currentTimeMillis()并不理想,但我认为在一个相当大的文件上 8-10 倍的时间差足以提出这个问题。 -
@dariober 你最好使用
public int read(char[] cbuf, int off, int len) throws IOException而不是直接使用bufferdreader 的read函数。最终,您的目标是在文件中找到行尾。虽然我自己没有测试过,但是控制在你手中的缓冲区可能会给你带来更好的结果。 -
快速检查后:测试可能(!)不仅有缺陷,我认为它完全有缺陷。尝试在
read测试之前运行readLine测试,看看时间是否不同。这可能只是与 HDD 缓存或 JIT 有关(对我来说,旧的慢速 HDD 在第一次运行时的时间差是 1:7,但在后续运行中大约是 1:2。所以事实上,请尝试运行 @987654340 @ 并告诉我们结果...) -
@Marco13 尝试在读取测试之前运行 readLine 测试:我在 Eclipse 中执行此操作,我尝试了几次关闭 Eclipse 并重新打开它(是这足以清除缓存和所有内容?)。我也使用
nanoTime()而不是currentTimeInMillis()。我发现即使我先运行 readLine,结果也几乎相同。 (比如 readLine() 与 read() 的 1:6)。我正在使用带 SSD 的 Mac 笔记本电脑。
标签: java bufferedreader benchmarking