套接字和文件推荐的缓冲区大小

5

Linux内核程序员,请问对于套接字或文件的write(2)系统调用,从性能角度考虑,合理的缓冲区大小是多少?很明显,它应该是某个页面大小的倍数,但是是哪个呢?这是否重要?什么样的大小算是“太小”或“太大”?


发送队列默认容量是128KB,除非你想使用setsockopt来进行调整,否则请确保传输的数据不超过此容量。 - Damon
1
@Damon:我不确定“任何东西”是正确答案。缓冲区肯定应该对齐。 - Cartesius00
默认设置适用于大多数人大多数情况(可以合理地假设编写网络堆栈的人不是完全的白痴)。除非您经常需要发送大量数据(真的很大),并且对延迟有一些严格的限制,否则通常没有理由费心。任何“合理”的大小都会被简单地复制到发送缓冲区并发送,无论其大小如何。如果不是全部适合,write将写入少于您请求的数量(返回该数量)。在任何情况下,它都能正常工作。 - Damon
缓冲区对齐在编程中非常重要(或者说可能很重要),例如,如果您直接将数据vmsplice / splice到网络卡,则允许内核重新映射页面并将DMA从页面传输到网络。write无论如何都会进行复制,所以...没有人关心。 - Damon
@Damon:是的,它可以工作,我完全同意。但那不是答案。此外,我也问了关于普通文件的问题。 - Cartesius00
1
对于普通文件也是一样的。write会复制,没有对齐或大小限制。如果write无法处理你传入的几TB数据,它将返回它能够写出的字节数,并且你需要再次调用write,减去已经写出的字节数。 - Damon
1个回答

7

取决于您与同行之间的延迟时间有多长,假设您拥有100MBps的连接速度和50ms的延迟时间,则可以进行计算:

100MBps * 0.050 sec / 8 = 0.625MB = 625KB

但是Linux 2.6的默认窗口大小大约为110KB,这将限制您的传输速率约为2.2MBps(110KB / 0.050)。 因此,要解决这个问题,您可以使用 setsockopt

int ret, sock, buf_size;
sock = socket(AF_INET, SOCK_STREAM, 0);
buf_size = 625*1024;
ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buf_size, sizeof(buf_size));
ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&buf_size, sizeof(buf_size));

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