LWN:替换 congestion_wait()!

kernel-4.9内存回收核心流程 以32位系统为例 内存分配流程调用流程: alloc_pages() -->alloc_pages_node() -->__alloc_pages_node() -->__alloc_pages() -->__alloc_pages_nodemask() -->get_page_from_freelist() 在get_pa... 阅读详情

关注了就能看到更多这么棒的文章哦~

Replacing congestion_wait()

By Jonathan Corbet
October 25, 2021
DeepL assisted translation
https://lwn.net/Articles/873672/

内存管理在很多方面都是在追求平衡。例如,内核必须要对当前用户对内存的需求以及预期未来的需求之间进行一下权衡。内核还必须权衡是否要为其他用途而回收内存,因为这可能涉及到需要将数据写入永久存储(permanent storage),以及底层的存储设备进行数据写入时的速度等等。多年来,内存管理子系统一直把存储设备操作的拥塞作为一个信号,告诉它自己应该要放慢回收速度了。不幸的是,这个机制从一开始就有点问题,在很长一段时间内其实并没有效果。Mel Gorman 现在正试图提供一个 patch set 来解决这个问题,不过这样一来内核就不应该再等待拥塞出现了。

The congestion_wait() surprise

当内存变得紧张时,内存管理子系统必须得回收当前正在使用的 page 用于其他用途。这反过来又先需要把所有被修改过的 page 的内容写出去。如果要写入这个 page 内容的块设备已经被繁重的写入任务所占用了,那么这里就算让 I/O 请求堆积得更高,也没有什么效果了。早在黑暗和遥远的时代, Git 出现之前(2002 年),Andrew Morton 就提议为块设备增加一个拥塞追踪(congestion-tracking)机制:如果某个设备已经拥塞住了,那么内存管理子系统就会暂时不再发起新的 I/O 请求(并控制(也就是放慢)那些在申请更多内存的进程的运行),直到拥塞缓解。这一机制在 2002 年 9 月的 2.5.39 开发版内核中就位了。

在那以后的几年里,拥塞等待机制以各种方式演进。即将发布的 5.15 内核中仍然包含有一个叫做 congestion_wait() 的函数,它可以暂停当前的 task,直到拥挤的设备变得不那么拥挤(也就是通过 clear_bdi_congested() 调用来通知这个状态)或者出现 timeout 从而结束。或者,至少这曾是它想象中的行为。

碰巧,clear_bdi_congested() 的主要调用位置是一个叫做 blk_clear_congested() 的函数,该函数在 2018 年的 5.0 内核版本中被移除了。从那时起,除了少数文件系统(Ceph、FUSE 和 NFS)之外,没有任何东西调用 clear_bdi_congested() 了,这意味着对 congestion_wait()的调用几乎总是会坐等到 timeout 结束,这并不是开发者的本意。

又过了一年(来到了 2019 年 9 月),内存管理开发人员才搞清楚这一点,这时,block 子系统维护者 Jens Axboe 让大家知道:

拥堵已经不存在了。在我看来,这个机制一直是无效的,因为它天生就是有 race condition 的。我们在传统的做法中使用过去的 batch 批处理机制来发出 signal,而这只在一些设备上有效。

Norton 在他的原始提案中实际上已经注意到了拥塞机制的 race condition 问题。某个 task 可以检查设备并看到它此时没有拥塞,但在该任务排进队列一直到其 I/O 请求得到之前,情况可能会发生变化。随着存储设备所支持的命令队列长度的增加,拥塞检测也越来越难做到准确了。所以块设备的开发者决定在 2018 年摆脱这个概念。不幸的是,当时没有人告诉内存管理开发人员这件事,从而导致了 Michal Hocko 在事情被报出来之后当时的很不愉快的抱怨。

这是一个不好的例子,就像是一只手不知道另一只手在做什么。多年来,这个问题导致内存管理性能受损。但是,内核开发人员往往不会光坐在那里指责和抱怨,相反,他们开始思考如何解决这个问题。他们一定想得很周到,因为这个过程花费了两年时间,才有 patch 出现。

Moving beyond congestion

Gorman 的 patch set 一开始就指出,"即使拥塞控制这个功能有效,也不能说这是一个好主意"。有许多情况会拖慢 reclaim process (内存回收进程)。其中一种情况是有太多的 page 在进行 writeback,导致底层设备处理不过来。这种情况可能可以被一个(正常工作的)congestion-wait 机制来解决,但其他问题不会被同样解决了。因此,这个 patch set 删除了所有的 congestion_wait() 调用,并采用了一系列启发式的方法来取代它们。

  • 在内存管理子系统中,有一些地方的需要对 reclaim 进行限流(throttle)。例如,如果 kswapd 线程发现目前正在写回的 page 已被标记为需要立即回收,这表明这些 page 在写入后备存储之前已经是在 LRU 中走完了一轮了。当这种情况发生时,进行 reclaim 的 task 将会被限流(throttle)一段时间。但并不是在等待那个已经不再存在了的 "congestion is done" 的 signal,而是会暂停 reclaim 直到当前 NUMA node 上的 page 已经有足够多的被写出去了为止。

    请注意,一些线程(尤其是内核线程和 I/O worker)在这种情况下不会被节流,可能会需要它们继续工作来清理积压(backlog)。

  • 许多内存管理操作,如 compaction 和 page migration,需要对后续将要操作的 page 给 "隔离(isolate)" 开。在这种情况下,隔离是指从那些 LRU list 中将此 page 删除。reclaim process 也需要到在写出去之前隔离 page。如果许多 task 最终会进行 direct reclaim,那么可以会有大量 page 被隔离,从而需要一些时间才能完全完成 reclaim 操作。如果内核对 page 进行隔离操作的处理速度比起 page 被回收的速度要快,那么这完全没有必要,其实是一种浪费。

    如果被隔离的 page 数量过多的话,内核本身已经会对 reclaim 进行节流,但这种节流操作实际上是在等待(或试图等待)拥塞结束。戈尔曼指出。"这没有意义,过度的并行化处理本身与 writeback 或拥塞无关"。新的代码改为了使用一个 wait queue,供那些在进行 reclaim 时因隔离太多 page 而被限流的 task 来使用。当隔离 page 的数量下降或发生 timeout 时,就会唤醒这些 wait queue。

  • 有时,进行执行 reclaim 操作的线程可能会发现它的工作基本上没有什么进展:扫描了很多 page,但成功回收的 page 很少。这可能是由于它在扫描 page 存在太多引用,或者其他一些因素。有了这个 patch,那些在 reclaim 方面进展不好的线程将被节流,一直等到系统中的某个地方取得进展。具体来说,内核将一直等待,直到运行中的回收线程成功完成至少 12%的 page 的扫描,然后才会唤醒那些没有进展的线程。这应该会减少浪费在无效回收这个工作上的时间。

  • 如果由于内存太少而导致写出 dirty page 的时候失败了,那么 writeback 工作也会被限流。在这种情况下,只有等到一些 page 被成功写回之后(或者像平常一样发生超时),才会取消限流。

大多数情况下 timeout 时间被设置为十分之一秒。不过,等待那些被隔离的 page 数量下降的 timeout 是五十分之一秒,原因是这种情况应该会很快发生变化。设置这些 itmeout 的 patch 指出,这些数值是 "凭空产生的",但在有人找到更好的值之前,可以先开始使用。作为朝这个不断改进的方向迈出的第一步,在 benchmark 测试结果显示 no-progress 这类 timeout 太容易超时之后,就将它改为了 0.5 秒。

这组 patch set 提供了一组详尽的 benchmark 测试结果。作为测试的一部分,Gorman 增加了一个新的 "stutterp " test,期望能展示 reclaim 问题。结果差别很大,但总体上是积极的。例如,一项测试显示系统的 CPU 时间减少了 89%。戈尔曼总结说:

最起码,限流看起来是有效的,wakeup event 会减少最坏情况下的 stall (卡住情况)。timeout 值可能还有一些调整空间,但这些工作很可能是徒劳的,因为最坏的情况跟 workload、内存大小和存储速度息息相关。希望进一步改善这组 patch 的话,更好的方法是根据 task 进行 allocation 分配的速率来确定其优先级,但这种做法可能会引入非常昂贵的开销。

这些 patch 到目前为止已经经历了五轮修改,发生了各种变化。很难想象这项工作最终会有什么原因被 mainline 拒绝。毕竟当前 kernel 中的代码显然是无法使用的。但是这种核心的内存管理代码的改动总是很难得到 merge 的。现在世界上的 workload 种类那么多,当改为使用这种启发式方法进行处理之后,肯定有一些情况下的性能会下降。因此,虽然这样的改动看起来会被接受,但人们永远不知道在合入之前会出现多少次 timeout。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

7f9775321e960669e89fa5500de05edc.png

Linux IO并发拥塞控制机制分析-3 如下面的代码,inode,bdi相关的读或写方向的拥塞判断都是通过wb_congested函数,而wb_congested函数判断是否拥塞就是根据“Linux IO并发拥塞控制机制分析-2”中提到的函数blk_set_congested是否设置了拥塞标志(读或写方向)。 inode(文件)的拥塞判断 举例1如下,在进行预读操作时,如果判断当前读方向处于拥塞,则推迟(Defer)... 阅读详情

相关推荐

perf_event 事件类型与分类

Linux 性能检测/调优之Perf_Event_He11o_Liu的专栏-优快云博客

SHELLCODE_8BIT的博客 1543

Linux缓存写回机制

Linux缓存写回机制

u010217401的专栏 2646

LIS3DHTR三轴加速度计Arduino驱动与嵌入式集成指南

加速度计是嵌入式系统中实现运动感知、姿态解算和振动分析的核心传感器。其工作原理基于MEMS微机械结构在惯性力作用下的电容变化,经片内ADC转换为数字信号;I²C接口因其硬件资源占用少、布线简洁,成为低功耗物联网节点的主流通信方式。技术价值体现在高分辨率(12位)、多量程(±2g~±16g)与低功耗(待机电流仅2µA)的平衡,支撑电池供电设备长期运行。典型应用场景包括可穿戴设备的姿态识别、工业预测性维护中的振动监测,以及智能硬件的敲击/跌落检测。本文围绕LIS3DHTR芯片及其Grove模块,详解Arduin

weixin_42584758的博客 594

2011-8-1 21:13:48

2011-8-1 21:13:48 struct percpu_data {  void *ptrs[NR_CPUS]; }; #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long

725

Synopsys 逻辑综合之 ICG

文章摘要: ICG(集成时钟门控单元)是一种用于降低时钟功耗的专用逻辑单元,通过控制时钟信号的传播实现节能。其核心原理是在寄存器前插入门控逻辑(如gclk=clk&en),但需避免直接使用AND门以防止毛刺,转而采用带锁存器的专用ICG单元。在RTL设计中,符合条件(如稳定使能信号)的if(en)结构可被综合工具(如DesignCompiler)自动识别并替换为ICG。使用时需配置时序检查(如PrimeTime分析使能路径、门控时钟延迟),并注意避免组合逻辑使能、多级门控等误区。ICG是芯片低功耗设

Serven的博客 4348

海康线扫相机平场矫正教程

1、白纸准备确保视野中有一张平整且无折痕的白纸,使其完全铺满相机的整个视野。2、行高设置将行高参数设定为 2048。3、灰度值控制相机端图像的灰度值应维持在 120 - 160 这个区间内。同时,最亮像素点与最暗像素点的灰度值差值不得超过 4 倍。在调整灰度值时,尽量开启增益功能。4、 图像模糊处理为减少白纸对平场矫正的影响,需将相机端获取的图像进行模糊化处理。具体操作是对镜头进行虚焦,使整体图像变得模糊。

T 2746

Perf -- Linux下的性能分析工具

原文 http://blog.youkuaiyun.com/bluebeach/article/details/5912062

Hello World! 2770

华为OD机试 - 跳房子I(Java 双机位A卷 100分)

可行的两步组合有 [1, 2] (索引和 0+3=3)、[1, 2] (索引和 0+4=4)、[4, 2] (索引和 1+3=4)、[4, 2] (索引和 1+4=5)、[5, 2] (索引和 2+3=5)、[5, 2] (索引和 2+4=6)。此样例有多种组合满足两回合跳到最后,譬如[-1,9], [2,6],其中[-1,9]的索引和为0+3=3, [2,6]的索引和为1+4=5, 所以索引和最小的步数组合为[-1,9].[3, 2] 和 [1, 4] 都满足和等于 5,且索引和均为 3。

学Java,找哪吒 4508

Home 欢迎加盟 关于我们 热门文章 搜索技术博客-淘宝关注技术 关注搜索 关注淘宝 graph database 性能优化 搜索引擎 前端技术 数据挖掘 导购搜索 搜索动态 分布式技术 其他 28

Iowait的成因、对系统影响及对策 子嘉 什么是iowait? 顾名思义,就是系统因为io导致的进程wait。再深一点讲就是:这时候系统在做io,导致没有进程在干活,cpu在执行idle进程空转,所以说iowait的产生要满足两个条件,一是进程在等io,二是等io时没有进程可运行。 Iowait是如何计算的? 先说说用户如何看到iow

mailerlee的专栏 1156

2026华为OD面试题084:贪心的商人

商人经营一家店铺,有 `number` 种商品。由于仓库限制,每件商品的最大持有数量是 `item[index]`。 每种商品每天有一个价格 `item_price[item_index][day]`。通过对商品买进和卖出获取利润,请给出商人在 `days` 天内能获取到的最大利润。 注:同一件商品可以反复买进和卖出。 输入描述: - 第一行输入商品数量 `number` - 第二行输入商人售货天数 `days` - 第三行输入 `number` 个整数,表示每件商品的最大持有数量 `item[in

琅嬛福地 273

dolphinscheduler-3.4.0

dolphinscheduler集群部署

docsz的博客 660

Linux so helper,Linux 通用块层之拥塞控制

为什么需要拥塞控制前面已经介绍了 Linux 操作系统通用块层中作为数据流动的关键因素 BIO,从软件的角度来讲,只要代码执行得够快,理论上就可以不停的下发数据让后端去执行。当然,都知道这是不可能的,首先局限于底层的硬件限制,磁盘速率一般也不超过 300MB/s,换成 SSD 的话会更快一下但是也不可能无限,另外一方面,代码执行总是需要消耗 CPU 时间,假设底层硬件能力为无穷大,但是通用块层自身...

weixin_28754365的博客 241

C#实战大华智能安防系统:从SDK封装到视频流与智能报警的全链路落地

本文将介绍C#集成大华SDK开发安防系统的实战经验,重点解决多路视频预览卡顿和报警延迟问题。文章通过三层架构设计(SDK封装层、业务服务层、应用层)实现解耦,详细分析线程安全封装、高效解码显示和智能事件联动等核心技术。针对16路摄像头同时预览时CPU占用率过高的问题,提出使用子码流拉流与异步解码的优化方案,并总结8个常见开发陷阱的解决方案。文中还提供了大华智能安防系统的完整架构图,展示从设备层到应用层的交互流程,特别强调业务服务层中视频流服务和智能报警服务的核心功能设计。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 429

Iowait的成因、对系统影响及对策

什么是iowait?顾名思义,就是系统因为io导致的进程wait。再深一点讲就是:这时候系统在做io,导致没有进程在干活,cpu在执行idle进程空转,所以说iowait的产生要满足两个条件,一是进程在等io,二是等io时没有进程可运行。 Iowait是如何计算的?先说说用户如何看到iowait吧我们通常用vmstat就能看到iowat,图中的wa就是(标红)这个数据是vmstat经过计算文件/...

weixin_34341229的博客 1214

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

块设备I/O调度程序

1.5.5 块设备I/O调度程序<br />我们建立请求队列建的目录是,当向请求队列增加一条新的请求,即产生一个request数据结构时,通用块层会调用I/O调度程序来确定该新request将在请求队列中的确切位置。I/O调度程序试图通过扇区将请求队列排序。如果顺序地从链表中提取要处理的请求,那么就会明显减少磁头寻道的次数,因为磁头是按照直线的方式从内磁道移向外磁道(反之亦然),而不是随意地从一个磁道跳跃到另一个磁道。<br /> <br />这就是著名的电梯算法,回想一下,电梯算法处理来自不同层的上下请求

云(存储),松(耦合) 9344

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

congestion源码解读

基于ATS6.1.1代码研究 变量和函数解释 t_state 中与拥塞控制相关的参数 // congestion control CongestionEntry *pCongestionEntry; StateMachineAction_t congest_saved_next_action; //下一状态保存,有 HttpTransact::STATE_MACHINE_ACTI

lx_shudong的专栏 896

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

解决Linux TIME_WAIT过多造成的问题

1、 time_wait的作用: TIME_WAIT状态存在的理由: 1)可靠地实现TCP全双工连接的终止 在进行关闭连接四次挥手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN, 因此客户端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出co...

zhangjunli的博客 15万+

writeback机制源码分析

  writeback相关数据结构   与writeback相关的数据结构主要有: 1,backing_dev_info,该数据结构描述了backing_dev的所有信息,通常块设备的request queue中会包含backing_dev对象。 2,bdi_writeback,该数据结构封装了writeback的内核线程以及需要操作的inode队列。 3,wb_writeback_w...

weixin_33810006的博客 298

linux 内核tcp拥塞处理(一)

这次我们来分析tcp的拥塞控制,我们要知道协议栈都是很保守的,也就是说只要有一个段被判断丢失,它就会认为发生了拥塞.而现在还有另一种,也就是路由器来通知我们发生了拥塞,这里ip头还会有一个ECN的位(准确的说是两位),来表示已经发送拥塞,不过这里要注意首先收到ECN的是接受方,可是真正需要被通知的却是发送方,因此当接受方收到ECN之后,用下一个ack来通知发送方有拥塞发生了,然后发送方才会做出响应...

但行好事 莫问前程 447

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 395

从一段视频到可漫游的 4D 有声场景:思路拆解与最小复现手记

只需一段手机视频,你就能生成可"走进去"的 4D 有声场景:转头时狗叫声方向随之变化,走近时声音更清晰。本文拆解 Video-to-4DAVScene 的核心思路,手把手带你用几十行 Python 搭出最小管线,把视频中的运动物体变成带空间位置的声源,并附上三个真实踩坑的排障经验,代码可直接跑。🎧

helloagent的博客 232

Python+Agent入门笔记(二):列表推导式、模块和异常,这些写 Agent 前得会

接上一篇《Python+Agent入门笔记(一)》。基础语法跑通之后,这篇聊几块日常写脚本绕不开的东西。还是按 JS/Go 开发者的视角写,尽量记录我实际卡过的地方。

qq_41241612的博客 430

【每天一个 Python 小案例30】Python 基础知识综合小项目:我的工具盒

作为系列收官,本篇把前 29 篇的知识点合成一个能直接用的命令行工具"我的工具盒":计算器(用 ast 解析表达式,不碰 eval)、单位换算与温度转换(一张换算表 + 特例分支)、记账与分类统计(Decimal + JSON 持久化)、以及用"字典当命令表"把菜单和业务逻辑解耦的主循环。文中对比了 eval 的安全隐患与 ast 白名单的做法,解释了 lambda 闭包在字典里的写法与晚绑定陷阱,并在最后给出整个系列的知识地图,把变量、数据结构、控制流、函数、类、异常、文件、标准库八块内容对应到具体篇目。

xinjiyaya的博客 418

详解Python条件语句

在 Python 中,if...else 是一种条件语句,可以根据给定的条件执行不同的操作。这个语句通常用于控制程序的流程。

2601_96798737的博客 205
上一篇: LWN:让GPU的工作也依赖进程优先级!
下一篇: LWN:Android墙纸用作身份识别!
LinuxNews搬运工
博客等级 码龄7年 438粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值