Linux 5.9内核回归源于页面锁定公平性的最新进展

2020-09-14 13:00:00

我们依赖您的支持:本网站主要由广告支持。广告使这个网站在过去的16年里得以维持。我们尽最大努力确保只显示干净、相关的广告,当检测到任何令人讨厌的广告时,我们会尽快将其删除。如果您想浏览没有广告的网站,同时仍然支持我们的工作,请考虑我们的无广告Phoronix溢价。你也可以考虑通过贝宝支付小费。上周,我们报道了从Linux5.0到5.9的基准测试之后的Linux5.9内核回归,最新开发的内核急剧下降。内核回归与Linux5.9内核周期开始时Linus Torvalds引入的代码一分为二。不幸的是,这不是一个微不足道的问题,一个仍在分析中的问题正在想出一个适当的解决方案。因此,简短的故事是,这是一个正在进行的工作,而这篇文章有一些额外的洞察力和基准在过去几天的过程中完成。

对于那些为Apache httpd/nginx/Hackbench等发现的Linux5.9内核回归感到好奇的人来说,它仍在评估中。莱纳斯·托瓦尔兹知道发生了什么,但他仍在试图找出解决问题的最佳方法,以解决性能急剧下降的问题,同时也试图解决他最初写补丁的动机。

正如前一篇文章中指出的,该问题源于此补丁重写了WAIT_ON_PAGE_BIT_COMMON()逻辑。虽然他正在考虑恢复它,他希望工作在一种新的混合模式,以解决旧的和新的用例。

在这些跨系统的不同测试用例中观察到的一些影响的示例。

以下是托瓦尔兹最初是如何在平分报告之后发给Phoronix的一封电子邮件中,用所有有趣的技术细节来总结这个问题的:

让我们假设某个页面被某个用户锁定(原因并不重要-可能是IO,也可能只是针对任何数量的IO。我需要锁定此页面以保证状态保持一致),并且有许多其他进程进入并希望锁定它。

我们所做的(以及我们在提交之前所做的)是将它们排在散列页面等待队列中,并且在页面结构中设置一个标志来说明";这个页面有服务员";。

我们把东西按顺序排好队,这样年纪最大的服务员就排在第一位。这是关于公平的,但你稍后会明白为什么这一部分并不重要。

无论如何,这件事并没有因为您将性能回归一分为二而从根本上进行更改-是的,队列中的提交更改,但不是以任何重要的方式,更改是随之而来的重大更改,即唤醒时发生的更改。

所以最大的区别在于唤醒行为。在此之前和之后,基本触发器都是相同的:持有页面锁的进程执行一个";unlock_page()&34;,在它解锁时,还会检查我们是否有已设置的等待器位,然后继续处理该等待列表。

这里是最大的不同之处。我们*过去*只是唤醒等待名单上的东西,仅此而已。我们有各种各样的反羊群行为,所以我们只会唤醒*一个*独占的服务员进程(即某人正在做锁页()),这样我们就不会让所有的服务员突然醒来,但基本上我们就这样做了。哦,我们现在已经发布了页面,所以叫醒那些服务员吧。

这听起来很明显,但实际上有一个相当不明显的效果。特别值得一提的是,页面现在已经解锁,服务员已经被叫醒,但他们并不一定在“运行”。它们已经可以运行了,但特别是在负载下,这些服务员可能需要一段时间才能真正获得任何CPU时间。

同时,所有不在等待队列中(特别是原始页面锁定器)且可运行的进程都可以自由进入并再次锁定该页面。

这实际上真的很高效-让第一个可能的储物柜进来并获得锁,对吞吐量有好处-但这是极其不公平的。因为等待了很长时间而被唤醒的可怜的进程实际上根本没有获得锁,而恰恰相反--当它最终开始运行时,现在页面又被其他人锁定了,这些人进来了,根本不用等待它。

更糟糕的是,原来的服务员现在看到该页面再次被锁定,所以猜猜它要做什么?右:它只是将自己添加到等待队列的末尾,所以现在它必须重新等待,加上所有的老服务员现在都在它的前面。双重不公平。

这就是老一套的行为。这就是为什么你最终让看门狗着火了,因为在重负和运气不好的情况下,上述情况可能会持续发生好几次,所以老服务员可能会等上几十秒。

但是它是高效的。只要第一个进程处于解锁状态,我们就会将页面锁定给出现的第一个进程。因此,旧的行为可能非常不公平,但它也最大限度地释放了页面锁定,从而最大化了吞吐量(它甚至可能最小化_Average_Delay,因为所有幸运的人都非常快地获得了页面锁定)。这只会造成真正可怕的最大延迟,因为这太不公平了。

新的模型都是相似的,直到觉醒发生。在这一点上,我们不是仅仅唤醒等待页锁的进程,而是将页锁交给该进程,并告诉它,您重新获得了页锁,您已经获得了页锁,甚至在它实际运行CPU之前就已经获得了页锁。

在我解锁页面和我把锁交给服务员之间仍然有一个非常小的窗口,但现在已经是两个周期了,所以不公平不会真的发生(如果它发生在蓝月亮上,也不是什么大问题-如果它真的很幸运的话,它将会是一个进程获得锁的轮流)。(如果它真的很幸运,那么它也不是什么大不了的事情。)(如果它真的很幸运,那么它将是一个进程,它会得到锁的轮流。这可能会发生几次。

因此,现在你基本上可以忽略极小的不公平机会,而且它不会因为重新排队或重复而变得更加复杂。

在许多情况下,您实际上会看到性能的提高,因为对于只将一个锁转移给一个服务员的情况,直接转移锁的新模型不仅公平,而且效率也略高一些。

那个令人讨厌的不公平案例可能会导致不幸过程的巨大延迟峰值,以及可怕的不公平,但它会帮助所有进来并幸运的储物柜。也许他们把页面锁上了,然后几乎立即再次解锁,也许他们就不会伤害原来的服务员了。

这就是我怀疑正在发生的事情,我希望我能从你们的个人资料中看到:找到一些常见的案例,快速获得锁并立即释放它,这在过去得到了巨大的帮助,因为我们过去使用的是根本不公平的锁定模式。

然后我希望我可以修复它来做一些不同的事情,并以这种方式修复性能回归。

因为我怀疑你一分为二的承诺正像预期的那样起作用,只是旧的不公平真的对表现有好处。我们以前已经看到过这种情况--特别是在锁争用的情况下,不公平的行为通常对平均性能非常有利,即使在最糟糕的延迟情况下也会非常非常糟糕。