gpt4 book ai didi

java - 为什么使用 FilterOutputStream 拦截 FileInputStream 到 FileOutputStream 的传输要慢几个数量级?

转载 作者:行者123 更新时间:2023-11-30 08:37:08 25 4
gpt4 key购买 nike

上下文

我正在尝试在数据传输期间获得反馈。会出现不同的情况,但我正在处理的特定情况是 FileInputStream 到 FileOutputStream 的复制。

实际的流复制循环是用 org.apache.commons.io.IOUtils 完成的。

请注意,我是一名经验丰富的开发人员,但我是一名 Java 新手。我不太了解 JVM 的优化。

问题

我将 FileOutputStream 包装在 java.io.FilterOutputStream 中以拦截传输并按如下方式计数:

FileInputStream input = new FileInputStream(new File("path"));
FileOutputStream output = new FileOutputStream(new File("path2"));
FilterOutputStream filterOutput = new FilterOutputStream(output);
IOUtils.copyLarge(input, filterOutput, new byte[32 * 1024]);

现在,当我这样做时,删除了实际的“做某事”(在上面的示例中,删除了我使用基本 FilterOutputStream 的实现,以免影响测试),复制一个 450Mb 的文件从 5-10 秒急剧下降(没有 FilterOutputStream 包装)大约 8 分钟。

几个事实

  • 在 windows x64 8 核机器上测量
  • 从本地 LAN 复制到我机器的 SSD
  • 一个核心 100% 忙,直到操作结束
  • 网络和磁盘几乎不忙 (1-2%)
  • 我测试过在我的文件流周围使用不同缓冲区大小的缓冲输入/输出流,但没有使用它们。
  • 我改变了实际的数据缓冲区大小。
  • 以上两种变化均未证明对有无之间的数量级差异有任何有意义的影响FilterOutputStream 包装。

问题

为什么会出现这种情况?有什么办法可以解决这个问题吗?

我猜测 JVM 能够检测文件复制的标准模式并将其直接委托(delegate)给操作系统。对我来说,它会在缓冲流中执行此操作,但无法通过 FilterOutputStream 间接的写入方法来执行此操作,这对我来说似乎有点奇怪。

现在我看到的唯一解决方法是在复制循环中直接实现一个监听器而不是管道输出流,但是因为这需要重新实现循环而不是使用 Apache utils,并添加并向下传递该监听器几层API,我正在寻找信息,然后再走这条路。

最佳答案

FilterOutputStream将通过以下方法逐字节复制:

public void write(byte[] b, int off, int len) throws IOException

Writes len bytes from the specified byte array starting at offset off to this output stream. The write method of FilterOutputStream calls the write method of one argument on each byte to output.

Note that this method does not call the write method of its underlying input stream with the same arguments. Subclasses of FilterOutputStream should provide a more efficient implementation of this method.

关于java - 为什么使用 FilterOutputStream 拦截 FileInputStream 到 FileOutputStream 的传输要慢几个数量级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37446021/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com