套接字接收缓冲区大小

4
我的问题是关于在Linux上使用Python进行套接字编程,但由于Python的socket模块只是对系统调用(recv、recvfrom等)的包装器,因此它与Python没有太大关系。
因此,根据docs,当我们调用recv方法时,
“为了与硬件和网络实际情况最佳匹配,bufsize的值应该是相对较小的2的幂,例如4096”
这是什么意思?
“与硬件和网络实际情况最佳匹配”
我最关心的是性能。
如果我将自定义缓冲区(稍后在我的代码中用作数据容器,如果有必要,它只是一个内存视图)传递给socket.recv_into方法,而缓冲区大小不是2的幂次方,那么它会成为我的网络软件瓶颈吗?

这只需要一行清晰简短的代码。

但我的缓冲区大小可能是17或51或其他值,所以我在思考,是否应该实现一些内部类似环形缓冲区的东西,其大小“好”(比如4096),并使用它以这样的“好”大小分块读取数据从套接字中,并将其写入那里,然后复制到我的缓冲区中?

从性能的角度来看,这样做有意义吗?

还是我的当前方案(当我以“不好”的大小读取数据时,它不符合“2的幂”规则)是可以的?

换句话说:如果我们以1023的大小而不是1024的大小分块从套接字中读取数据,这会影响性能吗?


1
如果这真的让你很烦恼,你可以在套接字上创建一个BufferedReader。它将确保以合理的块进行读取,同时允许您读取所需的数量。 - spectras
此外,查看这个问题,了解完整的历史记录,包括谁写下了这些话。 :) - Russ
1个回答

9
为了更好地匹配硬件和网络实际情况,bufsize的值应该是2的相对较小次幂,例如4096。您应该考虑以太网数据包的最大大小(~1500字节)和TCP数据包的最大大小(~64K)。你真的想要一个比第一个缓冲区(所以1024可能行不通)更大的缓冲区,而且你可能不需要比后者更多。因此,选择2K、4K、8K、16K、32K或64K。他们也暗示内核使用大小为2的幂的缓冲区(由于TCP最大数据包大小可能为64K),你需要花费一些功夫来匹配它,这样在读取时就不会有小/中等剩余(模数您的数据包大小)。例如:假设您正在使用1023字节的缓冲区,并且由于发送了大量数据,因此TCP数据包已达到64K。你将有64个1023字节的迭代和一个浪费的64字节额外迭代。

5
另外,将1kb分成64个系统调用的成本要比1个系统调用的64kb高。系统调用涉及到更改许多内部处理器状态,这需要时间。这就是为什么我们要进行缓冲的原因:进行一次系统调用并在用户空间中将其分成块可以避免系统调用的开销。 - spectras

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