什么更快:多个“发送”或使用缓冲?

Posted

技术标签:

【中文标题】什么更快:多个“发送”或使用缓冲?【英文标题】:What is faster: multiple `send`s or using buffering? 【发布时间】:2011-02-07 23:18:27 【问题描述】:

我正在使用 C/Python 中的套接字,我想知道将标头从 Python 字典发送到客户端套接字的最有效方法是什么。

我的想法:

    对每个标题使用send 调用。 优点:不需要内存分配。 缺点:很多send 调用——可能容易出错;错误管理应该相当复杂 使用缓冲区。 优点一个 send 调用,错误检查更容易。 缺点:需要缓冲区 :-) malloc/realloc 应该相当慢,并且使用(太大)缓冲区来避免 realloc 调用会浪费内存。

对我有什么建议吗?谢谢:-)

【问题讨论】:

另请注意,根据您的平台和网络配置,发送大量小数据包有时会导致数据包计时问题,从而降低性能。 【参考方案1】:

除非您要发送真正大量 的数据,否则最好使用一个缓冲区。如果您使用几何级数来增加缓冲区大小,分配的数量将成为一个摊销常数,分配缓冲区的时间通常会随之而来。

【讨论】:

你会推荐哪个几何级数? 在这种情况下,它只是意味着当缓冲区已满并且您需要扩展它时,将其大小乘以某个因子,而不是仅仅添加某个固定数量。 1.5 倍似乎效果很好。【参考方案2】:

send() 调用意味着到内核(直接处理硬件的操作系统部分)的往返。它的单位成本约为几百个时钟周期。除非您尝试调用 send() 数百万次,否则这是无害的。

通常,缓冲是指在收集到“足够的数据”时只偶尔调用一次send()。 “足够”并不意味着“整个消息”,而是类似于“足够的字节使得内核往返的单位成本相形见绌”。根据经验,8-kB 缓冲区(8192 字节)通常被认为是好的。

无论如何,对于所有与性能相关的问题,没有什么比实际衡量更重要了。试试吧。大多数时候,没有任何实际的性能问题值得担心。

【讨论】:

【参考方案3】:

由于 TCP 拥塞控制的工作方式,一次发送所有数据的效率更高。 TCP 维护一个窗口,它允许有多少数据“在空中”(已发送但尚未确认)。 TCP 测量返回的确认,以确定它可以“在空中”拥有多少数据而不会导致拥塞(即丢包)。如果应用程序没有足够的数据来填充窗口,TCP 就无法进行准确的测量,因此它会保守地缩小窗口。

如果您只有几个小的标头,并且您对send 的调用是快速连续的,那么操作系统通常会为您缓冲数据并在一个数据包中发送所有数据。在这种情况下,TCP 拥塞控制并不是真正的问题。但是,对send 的每次调用都涉及从用户模式到内核模式的上下文切换,这会产生 CPU 开销。换句话说,您最好还是在应用程序中进行缓冲。

在(至少)一种情况下,您最好不使用缓冲:当您的缓冲区比上下文切换开销慢时。如果你在 Python 中编写一个复杂的缓冲区,那很可能就是这种情况。用 CPython 编写的缓冲区将比内核中经过精细优化的缓冲区慢很多。缓冲很可能会花费您超过它所购买的费用。

如有疑问,请测量。

但请注意:过早优化是万恶之源。这里的效率差异很小。如果您尚未确定这是您的应用程序的瓶颈,请选择让您的生活更轻松的任何方法。以后随时可以更改。

【讨论】:

以上是关于什么更快:多个“发送”或使用缓冲?的主要内容,如果未能解决你的问题,请参考以下文章

当两个或多个进程(应用程序)等待将数据放入同一个缓冲区时,是不是保证顺序?

面试经验4-27

JAVA NIO Scatter/Gather(矢量IO)

什么是Scatter/Gather?

缓冲文件(用于更快的磁盘访问)

Go:缓冲通道总和更快?