将大文件发送到多个客户端时的性能改进

时间:2014-10-23 10:51:20

标签: java sockets operating-system

我想将文件发送到至少100个客户端。一个文件是225MB。我做了一些测试,我甚至无法实现80-90%的可用带宽用于发送文件。

将文件发送给一个客户端时:8秒

对于2个客户:45-50秒(这是一个显着增加)

对于50个客户,它会持续增加30分钟。

网络带宽为1Gbps。这意味着我可以达到超过100MB / s的速度。

以下是与此相关的代码部分:

            totalSize = (int) file.length();
            response.setContentType("application/octet-stream");
            response.setContentLength(totalSize);
            response.setHeader("Content-Disposition", "attachment; fileName=\"" + fileName + "."+extension+"\"");

            is = new FileInputStream(file);
            OutputStream os = nresponse.getOutputStream();
            int byteRate = DmConstants.BYTE_RATE;

            byte[] buff = new byte[DmConstants.BYTE_RATE];              
            int a = -1;         
            while((a = is.read(buff)) != -1) 
            {
                // a is the number of bytes ACTUALLY read, so 
                // when we write, that's the number of bytes to write
                os.write(buff,0,a);     
            }
            os.flush();
            os.close();
            is.close();

BYTE_RATE是1MB的缓冲区大小。如何提高性能?

复制文件时,我可以获得125MB / s的速度,看起来不错。 我猜多次读/写操作需要花费很多时间(sBYTE_RATEyscall)。 有什么方法可以减少吗?

1 个答案:

答案 0 :(得分:0)

以下列出了可用于提高性能的技术:

  1. 内存映射您要加载的文件;这是一种清漆使用的技术,它减少了从磁盘加载数据所需的OS上下文切换次数,并且可以非常有效地进行CPU预取。它还意味着您不必一遍又一遍地重新加载相同的数据,并且您不必立即关闭该文件,因为操作系统将非常有效地为您处理分页。
  2. 避免在程序和操作系统中复制数据结构之间的字节。可以将NIO字节缓冲区重新分配给已经内存映射到文件的字节,从而使字节到网络适配器的速度比其他方式快得多。
  3. 研究调整操作系统的网络设置/驱动程序。
  4. 向多个客户端广播文件,而不是一遍又一遍地重新发送同一文件,这需要您做更多的工作以确保数据正确到达,但在现代网络硬件上,数据包丢失非常低(直到网络饱和并且数据包丢失从悬崖上掉下来 - 这听起来比实际情况更糟糕,让这种平衡很好,值得付出努力)。这里的优点是您可以扩展客户端数量,例如7秒内1个文件到1个客户端或7个到100个客户端;它完全一样。网络将通过同时将数据包传送到多台计算机来处理文件的分发。
  5. 如果速度真的非常重要,那么有专门的网卡/驱动程序支持绕过OS内核并将网络缓冲区直接映射到用户地址空间;我之所以提到这一点主要是为了完整性,因为我不知道有任何人在低延迟空间之外积极使用这种技术。
相关问题