java - 在将大文件发送到多个客户端的同时提高性能

标签 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)。
有什么办法可以减少吗?

最佳答案

以下是可用于提高性能的技术列表:

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

    相关文章:

    java - 数据表中生成的标记

    java - 在未附加到 Activity 的 Fragment 中调用 Activity 方法

    c - 套接字读取速度非常慢的原因可能是什么?

    Java 代理 - 无法正确交换来自 HTTP GET/POST 请求的数据

    android - 执行 os 命令 python 后获取打印值

    java - Lombok @With 将克隆上的继承字段设置为 null。我如何让它复制工作?

    java - “wsimport”未被识别为内部或外部命令

    c - C 中的套接字,带有 select() 方法的非阻塞 send() 和 receive()

    python mkdir用子文件夹制作文件夹?

    assembly - 操作系统中的加载程序如何工作?