为什么要在 FreeBSD 中更改 net.inet.tcp.tcbhashsize?

sh-*_*eta 8 freebsd performance-tuning sysctl

在几乎每个 FreeBSD 网络调优文档中,我都能找到:

# /boot/loader.conf
net.inet.tcp.tcbhashsize=4096
Run Code Online (Sandbox Code Playgroud)

这通常与一些无用的语句配对,例如“TCP 控制块哈希表调整”或“将此设置为合理的值”。man 4 tcp也没有多大帮助:

tcbhashsize         Size of the TCP control-block hash table (read-only).
                    This may be tuned using the kernel option TCBHASHSIZE
                    or by setting net.inet.tcp.tcbhashsize in the
                    loader(8).
Run Code Online (Sandbox Code Playgroud)

我能找到的唯一涉及这个神秘事物的文档是优化 FreeBSD IP 和 TCP 堆栈中传输层下的协议控制块查找小节,但它的描述更多地是关于使用它的潜在瓶颈。这似乎与将新的 TCP 段与它们的侦听套接字匹配有关,但我不确定如何。

TCP 控制块究竟是做什么用的?为什么要将其哈希大小设置为 4096 或任何其他特定数字?

Sav*_*btz 3

这更像是计算机科学问题。特别是如果您想深入研究哈希表大 O表示法。

答案是:
如果您在服务器上处理许多 TCP 会话,您确实希望在 O(1) 时间内查找连接的 tcp 参数,而不是 O(n) 时间。FreeBSD 使用链接来解决哈希表冲突。因此,如果有很多连接,就会有很多冲突,因此您需要进行复杂度为 O(n) 的线性链查找,而不是 O(1) 哈希表查找。

您提到的参数 -tcbhashsize基本上是哈希表中的存储桶数量。
在我们的服务器上,它设置为相当高的值,例如16384甚至更高。通过该设置,我们每台服务器处理大约 60,000 个连接。

当前 x86_64 上的哈希表中的每个条目本身使用 252 字节 ( tcp_inpcb) + 688 字节 ( tcpcb) 的内核内存(自 7.2+ IIRC 起,amd64 中的 kmem 大小为 512G)。可以通过查看vmstat -z

关于 TCP 控制块的结构,您可以阅读 FreeBSD 源代码:tcp_var.h或阅读TCP/IP Illustrated, Volume 2: The Implements by Gary R. Wright, W. Richard Stevens