LWN:最近在关注的kernel改动!
关注了就能看到更多这么棒的文章哦~
Kernel topics on the radar
By Jonathan Corbet
August 2, 2021
DeepL assisted translation
https://lwn.net/Articles/864603/
内核开发社区非常繁忙,每天都有成千上万的电子邮件飞来飞去,每个时刻都有许多不同的开发任务在进行中。这些工作中大部分最终都会引出 LWN 的相关文章,但我们没有办法涵盖所有的工作,甚至没有办法涵盖全部那些有趣的工作。下面是我们的第一次尝试,希望也可以成为后续我们定期的专题:快速过一下目前编者正在跟踪的那些工作,不过不确定它们后续会不会变成一篇完整文章的主题。第一组的主题包括 memory folios 、task isolation 、以及谷歌的 lightweight threading framework。
Memory folios
三月份的时候已经在 LWN 介绍过了 memory folios 。Matthew Wilcox 的这组 patch 增加了 "foio" 的概念,即其确保了不会成为一个 compound page 中的 tail page。也就是 folio page 可以保证要么是一个独立的(singleton)page ,要么是一个 compound page 的开头部分,它也创建了一个 API 来给内存管理功能新定义了一些有用的 structure,节省了一些内存空间,并且稍微提高一些场景下的性能表现。
虽然内存管理社区仍然没有完全接受这个概念(一些开发者认为这个改动很大但好处却很小),但看起来这组 patch 似乎越来越可能在不久的将来被合并进来。或者,至少会开始走 merge 流程。人们不会一下子合入所有 138 个 patch(这是最后一次统计的数字)的内存管理 patch set。在 7 月中旬的时候 Wilcox 提出了他的计划,也就是在 5.15 中合并前 89 个 patch ,而其余的 patch 将在接下来的两个开发周期内得到合入。目前似乎没有人对这个时间表提出异议。
不过在 7 月下旬,Wilcox 偶然发现了一篇他命中注定会读到的 Phoronix benchmarking 的文章,该文章显示在内核中应用了 folio 补丁后,PostgreSQL 的性能提高了 80%。他说这个结果是 "看起来很令人鼓舞(plausibly real)",并且提出是不是应该加速合并这些 folio 相关的 patch。但其他开发者的反应则是表示怀疑。PostgreSQL 的开发者 Andres Freund 研究了一下这个结果是如何出现的,并得出结论说这个测试 "归根结底并没有测量出什么特别有趣的结果"。他自己的测试得到了 7% 的提高,不过(正如他所指出的)这仍然是一个不错的改进了。
最终来看,支持 folio 的力量似乎越来越强,而 merge 过程很可能仍将在 5.15 的时候开始。
Retrying task isolation
去年,开发社区曾经讨论过 task-isolation mode,也就是允许那些对 latency 很敏感的应用程序在没有内核干扰的情况下得以在 CPU 上运行。这项工作最终没有被 merge,但人们显然仍然对这种模式很感兴趣,从 Marcelo Tosatti 的 patch set 就可以看出这一点。它采取了一种更简单的方法来解决这个问题,至少起初的时候是这样的。
这个 patch 着重关注的是,哪怕 CPU 在 "nohz" 模式下运行时不会有定期的 clock tick,也仍然会产生内核中断,因此会引出麻烦。具体而言,他正在研究 "vmstat" 代码,这部分代码是为内存管理子系统执行清理工作的。其中一些工作是在一个单独的线程中完成的(通过一个工作队列来运行),当 CPU 运行在 nohz 模式下时,该线程通常会被禁用。不过,有些情况会导致这个线程在 nohz CPU 上被重新 reschedule 得以运行,从而导致原来的应用程序无法再独占该处理器。
Tosatti 的 patch set 增加了一组新的 prctl() 命令来解决这个问题。PR_ISOL_SET 这个命令会设置 "isolation parameters",这个参数可以是 PR_ISOL_MODE_NONE 或 PR_ISOL_MODE_NORMAL。后者要求内核避免发生中断。但这些参数一直要等到 task 真正进入了 isolation 模式才会开始生效,这是通过 PR_ISOL_ENTER 命令来完成的。内核看到需要进入 isolation 模式的时候,就会立即执行之前推迟的所有 vmstat 工作,这样内核就不会在以后不方便清理的时候再做这个工作了。在 isolation mode 中,任何一次系统调用结束的时候都会触发这个 deferred-work 要完成的 cleanup 动作。因为这些系统调用很可能总会触发一些 delayed work,这样在应用程序代码运行时情况不会被弄得更加混乱。
这个改动的意图明显是希望使这类功能更加普遍适用,也就是保证任何一个 delayed work 都要得以立即执行。这导致其他人(包括 Nicolás Sáenz)的质疑,认为这种采用单一的 mode 来控制那些各种不同的内核操作是不对的。他说,将各种行为分割开来,后续就可以将一些决策动作转移到用户空间。经过反反复复的讨论,Tosatti 同意修改接口,让用户空间可以明确控制每个可能会用到的 isolation 功能。实现该 API 的一个 patch set 已于 7 月 30 日发布出来,它增加了一个新的操作(PR_ISOL_FEAT),用于查询 isolation 模式激活时可以被静默掉的那些 action。
顺便说一下:我们社区的新成员可能不知道,20 年前,Tosatti 被人们称为神奇企鹅马塞洛(Marcelo the Wonder Penguin)。
User-managed concurrency groups
今年 5 月的时候,Peter Oskolkov 发布了一组 patch 实现了名为 "user-managed concurrency group" (UMCG) 的机制。这个工作显然是被称为 "Google Fibers" 的 scheduling framework 的一个实现,这自然是可以想象到的最不符合 Google 风格的名字(反讽一下)。这组 patch 起初没有解释清楚它究竟希望实现什么功能,但随着时间的推移,大家越来越清楚这个情况了。
UMCG,旨在成为一个轻量级的、由用户空间控制的 M:N 线程机制。经过人们的一些催促后发布了一个文档,描述了其核心理念。一个用户空间的进程可以设置一个或多个并发组(concurrency group)来管理它的工作。在每个组中,都会有一个或多个 "server" 线程。他的计划似乎是让应用程序针对每个可用的 CPU 都设置一个 server 线程。同时还会有不确定数量的 "worker" 线程,用来执行应用程序需要完成的工作。在任一时刻,每个 server 线程都可以执行一个 worker。用户空间可以随时控制哪些 worker 线程得以运行,具体的方法就是将它们 attach 到 server 上。各种事件(比如 worker 被阻塞在 I/O 上了)的通知处理可以让 server 线程保持忙碌。
在 8 月 1 日版本的 patch set 中,定义了两个系统调用来管理这个机制。调用 umcg_ctl() 就会把一个线程注册为 UMCG task,可以是 server mode,也可以是 worker mode。它还可以进行 unregistration 动作。umcg_wait() 则是主要的调度机制。例如,worker 线程可以用这个 API 来暂停执行。但 server 线程也可以使用 umcg_wait() 来唤醒一个特定的 worker 线程,或者强制从一个 worker 线程切换到另一个 worker 线程。只要 worker 线程继续运行,该调用通常就会一直保持阻塞状态。一旦 umcg_wait() 返回,server 线程就可以选择一个新的 worker 来执行了。
至少看起来是这么回事。几乎没有关于这些系统调用真正会如何被使用的文档,也根本没有示例代码。这组 patch 的最新版本终于包括了一些对系统调用的介绍,此前的版本中完全没有。也许正是这个原因,这项工作到目前为止收到的 review 相对较少。Oskolkov 似乎更专注于内核内的功能的具体实现,但 review 人员会希望能先对用户空间要用的 API 进行较长时间的仔细研究,因为如果这个 API 被合入的话就必须永远都得到支持。UMCG 看起来很有趣,而且可能会很有用,但是这种对 core-kernel 部分的改动,最起码来说也是很难得到 merge 的。到目前为止,由于缺乏对其用法的详细介绍,要想 merge 这组 patch 就会更加困难。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~