你有没有试过优化一个系统,但发现它不会比一些看似随意的点更快?这看起来是不是看起来像是某种东西达成了协议,即使它被卸载并在设备之间有一个超快的网络连接,它也永远不会在不到X毫秒的时间内将结果送到哪里?
这件事发生在几年前我的一些朋友身上。他们已经运行某个软件的一个版本很长时间了,而且它是从上游派生出来的。显然,它已经在效率、正确性和所有这些好东西方面获得了一系列本地修复。尽管如此,它还是设法错过了一大堆好处,所以公司最终又回到了开源版本。
在这样做的时候,他们注意到没有请求会在40毫秒内完成,即使他们以前在相同的条件下在旧版本的代码上也是如此。这个神奇的数字不断出现:这里是40毫秒,那里是40毫秒。不管他们做了什么,它都不会消失。
我真希望我当时在那里,找出是什么促使他们转危为安,寻求解决方案。唉,这一细节缺失了。但是,我们知道他们发现了什么:上游(开源)版本忘记了处理Nagle算法。
是啊。您是否曾经查看过TCP代码,并注意到有几个对setsockopt()的调用,其中一个是TCP_NODELAY?这就是为什么。当该算法在Linux上启用时,TCP会尝试将一堆微小的发送压缩成较少的较大的发送,以避免因开销而消耗大量的网络带宽。不幸的是,为了实际收集这些数据,在将少量数据刷新到网络之前,需要一定的延迟和超时。
在本例中,超时时间为40ms,这明显高于他们习惯使用其服务时看到的超时时间。在尽可能快地保持运行的名义下,他们给它打了补丁,然后事情就恢复到了以前的性能水平。
这个故事中有一个有趣的东西:一些参与其中的人制作了T恤,上面显示了他们的服务在修复前后的延迟图。
像这样的东西正好证明了这项工作的很大一部分只是记住了一堆奇怪的数据点,并且知道什么时候把这个故事和那个问题联系起来。
顺便说一句,如果这类事情对您很重要,那么您希望在Linux机器上使用的手册页是TCP(7)。这里有“很多”小旋钮,它们可能会影响您,这取决于您使用网络的方式。不过要小心,不要因为东西存在就开始调优。沿着这条路走下去也是疯狂的。