FileChannel.transferTo(假设为零拷贝)没有给出任何性能提升

时间:2018-06-11 19:24:04

标签: sendfile zero-copy

我正在开发一个REST API,它有一个端点可以下载一个可能是>的文件。 2 GB大小。我已经读过,如果操作系统支持,那么Java FileChannel.transferTo(...)将使用零拷贝。在我的MacBook Pro OS 10.11.6上进行开发期间,我的服务器在localhost上运行。

我将以下两种将文件写入响应流的方法进行了比较:

  1. 使用FileChannel
  2. 将固定数量的字节从WritableByteChannel复制到transferTo
  3. FileInputStream读取固定数量的字节到字节数组(大小为4096)并在循环中写入OutputStream
  4. 使用这两种方法,5.2GB文件所需的时间在20到23秒之间。我尝试transferTo将单个传输中的固定字节数设置为以下值:4KB(即4 * 1024),1MB和50MB。在所有3个案例中,写作所用的时间都在相同的范围内。

    从进入while循环之前到退出while循环之前测量所花费的时间,其中从文件中读取字节。这一切都在服务器端。网络跳跃时间没有考虑到这一点。

    关于原因可能是什么的任何想法?我确信MacOS 10.11.6应该支持零拷贝(即sendfile系统调用)。

    编辑 (6/18/2018)

    我在2015年发现了以下博文,称MacOS X上的sendfile已被破坏。难道这个问题仍然存在吗?

    https://blog.phusion.nl/2015/06/04/the-brokenness-of-the-sendfile-system-call/

1 个答案:

答案 0 :(得分:1)

您所引用的(高)传输速率很可能接近或限制SATA设备可以执行的操作。如果我的猜测是正确的,那么您将不会在运行测试的时间中看到性能的提高-但是在测试过程中,CPU负载可能会发生变化。假设您有一台相对强大的计算机,则您的CPU和内存足够快。任何方法(无论是否为零拷贝)都可以相同的速度工作-这就是磁盘的速度。但是,零拷贝将减少CPU负载,也不会从内存中获取不必要的带宽。因此,您应该测试不同的方法,然后看看哪种方法最终使用最少的CPU并为您的应用程序选择该方法。