我正在编写一个为数千个连接提供服务的高吞吐量服务器。假设我有 400 个字节要通过套接字发送。假设我用两种方式来做:
- 调用 Socket.Send() 40 次,每次发送 10 个字节。
- 调用 Socket.Send() 一次,发送 400 个字节。
这两种方式在速度、CPU负载等方面有很大区别吗?
最佳答案
如果Socket.NoDelay
保留为false
,那么它很少会产生任何影响 - 大多数时候,你只是要在本地缓冲 - 尽管P/Invoke 开销比绝对必要的多一点(由于通过套接字层进行大量调用)。请注意,在您关心的任何地方,Socket.NoDelay
通常应设置为 true
。
如果Socket.NoDelay
为true
,那么如果一切都最大限度地工作,那么您可能引入额外的使用 40 次发送 10 字节进行数据包分段,这在使用 1 次发送 400 字节时可以避免。然而,在许多情况下,操作系统/硬件堆栈中的各种抽象和层意味着许多 10 字节 block 可能最终会共享数据包。不过,在最佳情况下,这仍然比 1 个数据包多得多。
另请注意,这始终是一种权衡:数据包碎片会降低总体吞吐量,但如果其他 390 字节需要花费较长的时间,那么尽早发送第一个字节可能会减少感知的延迟。可测量(但可能很小)的构建时间。
在大多数情况下:这不太可能成为瓶颈。如果您可以避免数据包碎片而不导致延迟,那么这可能是可取的。如果是我,我可能会更关心高效的缓冲区管理,以最大限度地提高可扩展性,同时避免由于 GC 造成的暂停;像新的“管道”IO API 这样的工具确实可以帮助解决这个问题,并且 Kestrel 可用于托管基于“管道”的 TCP 服务器,其代码比您编写的代码要少您自己的套接字监听器 - 然后它会为您处理所有缓冲区管理。
关于C# 套接字 : is multiple sending less efficient than a single send?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69629408/