Java的FilterOutputStream会带来性能惩罚

3

我有一段代码,它将输出流分成两个目的地。它们都会写入文件,但第二个目的地会经过一个过滤器。我试图弄清楚为什么简单地包装一个FilterOutputStream而不重写任何方法会导致巨大的性能损失。

我创建了一个大小为358兆字节的文件:

dd if=/dev/zero of=dummyfile.txt count=700000 bs=512

使用以下代码检测它:

private OutputStream getFilteredStream(OutputStream out1, OutputStream out2) {
    return new TeeOutputStream(out1, new FilterOutputStream(out2));
}
private OutputStream getDestination(String name) {
    return new BufferedOutputStream(new FileOutputStream(new File(name)));
}
...
InputStream in = new FileInputStream(new File("dummyfile.txt"));
OutputStream out = getFilteredStream(getDestination("dest1"), getDestination("dest2"));
long start = System.currentTimeMillis();
IOUtils.copy(in, out);
out.flush();
long end = System.currentTimeMillis();
System.err.println(((end - start) / 1000.0) + " seconds");
// close the files

结果是:
1.672 seconds

如果我移除FilterOutputStream...

private OutputStream getFilteredStream(OutputStream out1, OutputStream out2) {
    return new TeeOutputStream(out1, out2);
}

重新运行后,结果如下:

0.797 seconds

我使用FilterOutputStream时,预计会有性能损失,但我不希望损失翻倍,尤其是在没有覆盖任何方法的情况下。我查看了FilterOutputStream的源代码,但没有发现会导致如此巨大损失的原因。
请问有人能够解释一下可能会导致这个问题的原因吗?

使用分析器查看发生了什么。 - Kayaman
在管道中添加一个普通的FilterOutputStream,而不对其进行任何实际过滤的子类化,有什么意义呢? - Andreas
没有意义,我只是想演示一下我所看到的问题。 - user1428945
1个回答

6
默认实现在FilterOutputStream中禁用块处理并逐个字节地通过write(int b)方法发送所有字节,因此速度较慢。
这是文档中所述:

请注意,此方法不使用相同的参数调用其底层输入流的写入方法。FilterOutputStream的子类应该提供更有效的实现方式


实际上,在覆盖write(byte b[], int off, int len)方法之后,性能恢复正常。 - user1428945

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接