【发布时间】:2011-09-15 20:26:15
【问题描述】:
要从 python 中的套接字读取数据,请调用 socket.recv,它具有以下签名:
socket.recv(bufsize[, flags])
python docs for socket.recv 模糊状态:
注意:为了与硬件和网络现实进行最佳匹配, bufsize 应该是比较小的 2 的幂,例如 4096。
问题:“与硬件和网络现实最匹配”是什么意思?将 bufsize 设置为非二次方的实际影响是什么?
我已经看到 many other recommendations 使其读取为 2 的幂。我也很清楚将数组长度作为 2 的幂通常有用的原因(位移/屏蔽长度、最佳 FFT 数组大小等的操作),但这些取决于应用程序。我只是没有看到socket.recv 的一般原因。当然不是python文档中的specific recommendation。我也没有在 underlying python code 中看到任何二次幂优化以使其成为特定于 python 的推荐
例如...如果您有一个确切知道传入数据包长度的协议,显然最好只读取“最多”您正在处理的数据包所需的内容,否则您可能会吃掉下一个数据包,那会很烦人。如果我当前正在处理的数据包只有 42 个字节待处理,我只会将 bufsize 设置为 42。
我错过了什么?当我必须选择任意缓冲区/数组大小时,我通常(总是?)将长度设为 2 的幂,以防万一。这只是多年养成的习惯。 python 文档也只是习惯的受害者吗?
这不是 python 独有的,但由于我专门引用了 python 文档,所以我会这样标记它。
更新:我刚刚在我的系统上检查了内核级别的缓冲区大小(或者至少我认为我做了...我做了cat /proc/sys/net/core/rmem_default),它是 124928。不是两个的幂。 rmem_max 是 131071,显然也不是 2 的幂。
在进一步研究这一点时,我真的看不出两个推荐的力量有什么好处。我准备把它称为虚假推荐......
我还添加了tcp 和C 标签,因为它们也很相关。
【问题讨论】:
-
我最好的猜测是,出于内存管理的原因,一些操作系统级别的网络堆栈可能更喜欢维护 2 次幂大小的缓冲区,但这似乎是一个毫无意义的历史产物。也许这个笔记的主旨是缓冲区大小应该是 4KB 而不是 4MB 或 4GB,2 的幂只是迷信。
-
我的猜测是,非 2 的幂大小唯一可能的真正后果是某些较低级别的代码可能会分配一个缓冲区,其大小无论如何都是 2 的下一个幂,并且如果缓冲区不会被使用,则为后一部分。除非您的 RAM 严重不足,否则这不是问题...
-
查看this SO question 上的答案。它也处理
recv(),答案可能有助于更全面地理解。它不会回答问题,但会提供更多见解。 -
很可能唯一可能重要的数字是:高速缓存行大小(通常为 64 字节,但始终为 2 的幂)和页面大小(通常为 4096 字节,但始终为 2 的幂)。只要您是其中更相关的倍数,您可能就是理想的。
-
还要注意,由于缓存关联的怪异,最好不要使用 2 的幂。