我不明白为什么tcp_adv_win_scale
和 tcp_app_win
变量在 Linux 中共存。信息来自TCP(7)说:
为了tcp_adv_win_scale
:
tcp_adv_win_scale
(整数;默认值:2;自 Linux 2.4 起)
将缓冲开销计算为
bytes/2^tcp_adv_win_scale
, 如果tcp_adv_win_scale
大于0;或者bytes-bytes/2^(-tcp_adv_win_scale)
, 如果tcp_adv_win_scale
小于或等于零。套接字接收缓冲区空间在应用程序和内核之间共享。 TCP维护部分缓冲区作为TCP窗口,这是通告给另一端的接收窗口的大小。其余空间用作“应用程序”缓冲区,用于将网络与调度和应用程序延迟隔离。这
tcp_adv_win_scale
默认值 2 意味着用于应用程序缓冲区的空间是总空间的四分之一。
对于tcp_app_win
:
tcp_app_win
(整数;默认值:31;自 Linux 2.4 起)此变量定义为缓冲开销保留 TCP 窗口的字节数。
最多为 (
window/2^tcp_app_win
, mss) 窗口中的字节保留给应用程序缓冲区。值 0 表示没有保留任何金额。
所以我不确定tcp_app_win
到底改变了什么。在我看来,这两个变量都可以用来调整 TCP 应用程序缓冲区,因此不需要一起更改它们。我说得对吗?
答案1
我找到了这个信息,其中谈到了tcp_adv_win_scale
。该页面的标题是:TCP性能调优——如何调优linux。
摘抄
TCP 性能受到延迟和窗口大小(以及开销,这会减少有效窗口大小)的限制,具体取决于 window_size/RTT(这是在任何给定时刻可以通过链路“传输”的数据量)。
要获得可能的实际传输速度,您必须将结果窗口除以延迟(以秒为单位):
开销为:window/2^tcp_adv_win_scale(tcp_adv_win_scale默认为2)
因此,对于 Linux 接收窗口 (tcp_rmem) 的默认参数:87380 - (87380 / 2^2) = 65536。
给定跨大西洋链路(150 ms RTT),最大性能最终为:65536/0.150 = 436906 字节/秒或约 400 kbyte/秒,这在今天确实很慢。
随着默认大小的增加:(873800 - 873800/2^2)/0.150 = 4369000 字节/秒,或大约 4Mbytes/秒,这对于现代网络来说是合理的。请注意,这是默认设置,如果发送方配置了更大的窗口大小,它会很高兴地扩展到 10 倍(8738000*0.75/0.150 = ~40Mbytes/s),这对于现代网络来说非常好。
2.6.17 及更高版本具有相当好的默认值,并且如果对方支持的话,实际上可以将窗口大小调整到允许的最大值。因此,从那时起,本指南的大部分内容就不再需要了。不过,为了获得良好的长途吞吐量,可能需要增加最大值。
我能够理解这一点,但不太理解这两个变量之间的关系(如果有的话)。
我只是勉强理解这试图解释什么。从本质上讲,这个参数听起来像是用于缩放缓冲空间量的参数,用于 TCP 和应用程序。
经过更多搜索,我发现这些解释更有意义。该页面的标题是:Ipsysctl 教程 1.0.4 - 第 3 章 IPv4 变量引用。
摘抄
3.3.2. tcp_adv_win_scale
该变量用于告诉内核应将多少套接字缓冲区空间用于 TCP 窗口大小,以及为应用程序缓冲区保存多少空间。如果 tcp_adv_win_scale 为负数,则使用以下公式计算窗口缩放的缓冲区开销:
其中 bytes 是窗口中的字节数。如果 tcp_adv_win_scale 值为正,则使用以下公式计算缓冲区开销:
tcp_adv_win_scale 变量采用整数值,默认设置为 2。这反过来意味着应用程序缓冲区是 tcp_rmem 变量中指定的总缓冲区空间的 1/4。
3.3.3. tcp_app_win
该变量告诉内核在传输特定 TCP 窗口的 TCP 套接字内存缓冲区中为特定 TCP 窗口保留多少字节。该值用于指定要保留多少缓冲区空间的计算,该计算看起来为下列:
从上面的计算中您可能会了解到,该值越大,特定窗口的缓冲区空间就越小。此计算的唯一例外是 0,它告诉内核不为该特定连接保留空间。该变量的默认值为 31,通常应该是一个不错的值。除非您知道自己在做什么,否则请勿更改此值。
根据这些解释,听起来第一个参数tcp_adv_win_scale
是控制套接字缓冲区空间的分割,即如何划分 TCP 窗口使用与应用程序缓冲区。
而第二个参数tcp_app_win
指定为描述中提到的应用程序缓冲区保留的字节数tcp_adv_win_scale
。
答案2
以下是我从内核源代码中得到的发现:
- tcp_adv_win_scale 用于宏include/net/tcp.h 中的 tcp_win_from_space。该宏用于net/ipv4/tcp_input.c 中的函数 tcp_grow_window。
似乎它仅用于已建立的连接,而不用于连接。
此参数的默认值为 1,这会导致应用程序使用 50% 的 rcv 缓冲区。 - tcp_app_win 用于net/ipv4/tcp_input.c 中的函数 tcp_init_buffer_space。
似乎它仅用于连接而不用于已建立的连接。
此参数的默认值为 31,这会导致应用程序使用 0.0% 的 rcv 缓冲区。
我想说的逻辑不是为新连接中的应用程序保留缓冲区并在接收数据时增加它。
这样理论上初始 rwnd 可以被广告为与整个缓冲区一样大。发送方将发送那么多数据。接收器缓冲区将填满,接收器将根据 tcp_adv_win_scale 缩小 win 并增加缓冲区的应用部分。
所以,正如中提到的@slm答案 - 似乎没有理由接触 tcp_app_win。