5

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

我的想法:

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

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

4

3 回答 3

3

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

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

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

如有疑问,请测量。

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

于 2010-04-14T16:13:34.463 回答
0

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

于 2010-04-14T15:12:23.757 回答
0

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

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

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

于 2010-04-14T15:15:36.357 回答