操作系统(Linux / BSD)将10GB缓冲区分成许多数据包并发送/使用它们,还是一次发送?
如果不可能一次发送10GB缓冲区的域套接字,那么单个数据包的实际大小限制是多少?
约束:
>该程序将在Linux 2.6.32和FreeBSD 9上运行
>要发送的缓冲区的大小范围从3字节到最大10GB.
解决方法
> wmem_max套接字发送缓冲区最大大小的内核设置,它确定可以使用setsockopt(SO_SNDBUF)设置的发送缓冲区的最大大小.当前设置可以从/ proc / sys / net / core / wmem_max中读取,并且可以使用sysctl net.core.wmem_max = VALUE设置(将设置添加到/etc/sysctl.conf,以使更改在重新启动之间持续).请注意,此设置适用于所有套接字和套接字协议,而不仅仅适用于Unix套接字.
>如果多个数据包被发送到Unix套接字(使用SOCK_DATAGRAM),则可以在不阻塞的情况下发送的最大数据量取决于套接字发送缓冲区的大小(见上文)和最大数量的未读数据包Unix套接字(内核参数net.unix.max_dgram_qlen).
>最后,一个数据包(SOCK_DATAGRAM)需要连续的内存(根据What is the max size of AF_UNIX datagram message that can be sent in linux?).内核中有多少连续内存将取决于许多因素(例如系统上的I / O负载等).
因此,为了最大程度地提高应用程序的性能,您需要一个大的套接字缓冲区大小(以最小化由于套接字写入系统调用的用户/内核空间上下文切换)和一个大型的Unix套接字队列(尽可能多地解耦生产者和消费者).但是,套接字发送缓冲区大小和队列长度的乘积不能太大,导致内核用完连续的内存区域(导致写入失败).
实际数字将取决于您的系统配置和使用情况.您将需要通过测试确定限制…开始说,在256Kb的wmem_max和max_dgram_qlen在32,并保持加倍wmem_max直到你注意到事情开始中断.您将需要调整max_dgram_qlen以在一定程度上平衡生产者和消费者的活动(尽管生产者比消费者快得多或慢得多),队列大小不会有太大的影响).
请注意,您的制作人必须通过调用setsockopt(SO_SNDBUF)将套接字发送缓冲区大小专门设置为wmem_max字节,并且必须将数据分割为wmem_max字节块(消费者将不得不重新组合它们).
最好的猜测:实际的限制是围绕wmem_max〜8Mb和unix_dgram_qlen〜32.