news 2026/9/4 11:01:41

zram 状态指标详解:mm_stat 的 9 列、io_stat 的 3 列与一套完整排障路径

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
zram 状态指标详解:mm_stat 的 9 列、io_stat 的 3 列与一套完整排障路径

zram 状态指标详解:mm_stat 的 9 列、io_stat 的 3 列与一套完整排障路径

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

线上某台 32G 内存的服务器,可用内存掉到 4% 以下,swap 开始工作后应用 P99 延迟从 80ms 爬到 600ms。这台机器的 swap 挂在 zram 上,理论上不走磁盘,为什么还会这么卡?登录机器后cat /sys/block/zram0/mm_stat一看:压缩后的数据量只比原始数据量小 8%,mem_used_max一路逼近 disksize,io_stat里的failed_writes还在持续增长。接下来这段内容,就照着内核里 zram 真正记录、导出这些数字的代码,把每个字段拆开讲,再给出对应异常下的排查顺序。

一个 4KB 页进入 zram 之后发生了什么

zram 本质是一个 RAM 块设备:页被"写"进来的时候不占原来的 4KB 槽位,而是压缩后塞进一个按对象大小分档的内存池(zsmalloc);读回来时再解压。它并不是无脑压缩,页内容会先走三条分支:

压缩器以"后端"形式挂载,每种算法一个文件,见 drivers/block/zram/ 下的backend_lz4.cbackend_zstd.c等;池分配逻辑在 mm/zsmalloc.c。写路径zram_bvec_write、读路径zram_bvec_read都在 drivers/block/zram/zram_drv.c 里,排障时对照这两个函数看计数从哪来最直观。

mm_stat 的 9 列与 io_stat 的 3 列逐列拆开

用户空间能读到的核心状态就在/sys/block/zramX/下两个文件。mm_stat的 9 列顺序固定,由mm_stat_show()按序 emit,字段定义可对照 Documentation/ABI/testing/sysfs-block-zram:

列序字段含义合理取值 / 经验阈值
1orig_data_size当前存入的原始数据量(未压缩口径)≤ disksize
2compr_data_size压缩后实际占用的数据量越小说明压缩越有效
3mem_used_total内存池真实占用(含元数据)这是 zram 真正吃的 RAM
4mem_limit人为设定的占用上限,0=不限按需设定
5mem_used_max历史峰值占用逼近 disksize 要警惕
6same_pages全零页数量占比高=压缩器没白干
7pages_compacted碎片整理移动过的对象数持续上涨=池在碎片化
8huge_pages当前多页槽位数量反映大对象占比
9huge_pages_since累计产生的多页槽位只增不减,看增量

io_stat只报块层不统计的部分,3 列依次为 failed_reads、failed_writes、notify_free——后两个是内存池吃紧时池向系统发的"释放通知",它们非零就说明 zram 已经在和分配失败搏斗。读写次数则走通用块层接口,/sys/block/zramX/stat的第 1、5 列即读、写次数。

注意一个常被误读的点:压缩率不是某个现成 sysfs 字段,要自己算:

# 第1列=orig,第2列=compr,第6/8列按每页4KB折算,输出真实压缩比 awk '{r=$1/($2+$6*4096+$8*4096); printf "orig=%.1fM compr=%.1fM ratio=%.2f\n", $1/1048576, $2/1048576, r}' < /sys/block/zram0/mm_stat

这个比值长期低于 1.1,基本等于 zram 白开——页还在占 RAM,却多付了压缩 CPU。

观测:从一条 awk 到 Prometheus 面板

手工巡检一行就够:

# 一眼看全:压缩比、池占用、失败计数 paste <(awk '{print $1/($2+$6*4096+$8*4096)}' /sys/block/zram0/mm_stat) <(cat /sys/block/zram0/io_stat)

脚本化采集把同一套 awk 塞进 cron,5 分钟一次落盘,顺带做阈值判断:

#!/bin/bash # 采集 zram 关键指标,压缩比低于 1.1 输出告警到 stderr LOG=/var/log/zram_metrics.log awk -v t="$(date +%F_%T)" '{ r = $1 / ($2 + $6 * 4096 + $8 * 4096) print t, $1, $2, $5, r, $7 >> "'"$LOG"'" if (r < 1.1) print "zram0 ratio " r " < 1.1" > "/dev/stderr" }' /sys/block/zram0/mm_stat

接入 Prometheus最省事的路线是 node_exporter 的 textfile collector,把指标渲染成 exposition 格式,Grafana 里放三张图:压缩比趋势(低于 1.1 画参考线)、mem_used_total 与 disksize 对比(80% 告警)、failed_writes 增量(非零即红色面板)。采集片段:

# 供 node_exporter textfile_collector 抓取 { awk '{printf "zram_compression_ratio %.4f\n", $1/($2+$6*4096+$8*4096)}' /sys/block/zram0/mm_stat awk '{printf "zram_orig_bytes %.0f\nzram_mem_used_bytes %.0f\n", $1, $3}' /sys/block/zram0/mm_stat awk '{printf "zram_failed_writes_total %.0f\n", $2}' /sys/block/zram0/io_stat } > /var/lib/node_exporter/textfile_collector/zram.prom

三类高频异常:比值太低、池子打满、换入偏慢

压缩比趴在 1.1 以下。先确认数据本身的可压缩性:如果 workload 主要是已压缩/加密内容(对象缓存、加密块),低比值是必然,此时调算法收益有限,正确动作是缩disksize(服务器建议物理内存的 25%~50%,嵌入式可放到 100%~200%)甚至弃用 zram。若数据其实可压缩,则换更激进的算法,并用 5.19+ 引入的二次压缩把存量页再压一遍:

# 主算法换成 zstd;再让空闲页用次级算法重压缩,降低存量平均大小 echo zstd > /sys/block/zram0/comp_algorithm echo idle_pages > /sys/block/zram0/recompress

mem_used_max 逼近 disksize、failed_writes 上涨。这是池子装不下或碎片化后的典型形态,对应io_stat里 notify_free 也会跟着涨。处置分三步:先看pages_compacted是否持续上涨(碎片信号),是则触发一次整理;再检查有没有设mem_limit兜底;最后如果开了后备盘,让不可压缩页走 writeback 腾池:

# 触发 zsmalloc 碎片整理;写回空闲页到后备盘;重置峰值计数便于观察新趋势 echo 1 > /sys/block/zram0/compact echo 1 > /sys/block/zram0/writeback echo 0 > /sys/block/zram0/mem_used_max

换入延迟高但 zram 本身"健康"。这时重点怀疑页其实不在 RAM 里:看后备盘计数文件bd_stat(bd_count、bd_reads、bd_writes),如果 bd_reads 明显增长,说明大量页被 writeback 到了盘上,读回走的是磁盘路径,zram 的快就没了。对策是收紧 writeback 触发(调小writeback_limit、必要时writeback_limit_enable置 0),或把后备盘换成更快的介质。

一个判断收尾

zram 的全部状态可以浓缩成四个视角:压缩器有没有用(压缩比)、池子占了多少(mem_used_total / mem_used_max)、碎片化程度(pages_compacted)、失败与回写(io_stat 与 bd_stat)。日常盯住这四组,90% 的异常都能对号入座。想继续深入,读 Documentation/admin-guide/blockdev/zram.rst 里的完整配置流程,再从 drivers/block/zram/zram_drv.c 的zram_bvec_write顺着计数变量的每个atomic64_inc走一遍,比任何指标手册都清楚。留给读者一个问题:如果换成以不可压缩数据为主的 workload,zram 的账还划得来吗?

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 9:35:58

paperclipai实战:用Python打造AI文件自动整理与归档工具

之前在业务迭代中接触到一个叫paperclipai / paperclip的项目命名&#xff0c;起初以为只是某个回形针图标的开源库&#xff0c;真正动手后发现&#xff1a;paperclip这个词在软件工程里本身就承担着好几层含义&#xff0c;从文件上传组件到轻量 AI 工具&#xff0c;甚至还能演…

作者头像 李华
网站建设 2026/8/31 19:46:25

单片机事件监测器设计:从硬件消抖到软件状态机的嵌入式实战

1. 项目缘起与核心价值 最近在准备蓝桥杯电子类单片机组的比赛&#xff0c;发现很多同学在应对“事件监测器”这类综合性模块题目时&#xff0c;常常感到无从下手。这类题目往往不会直接告诉你“请用定时器中断实现一个秒表”&#xff0c;而是会用一个更抽象、更贴近实际应用场…

作者头像 李华
网站建设 2026/8/31 21:50:26

4步跑通Dify工作流引擎:零基础上手,把知识问答流程搭起来

4步跑通Dify工作流引擎&#xff1a;零基础上手&#xff0c;把知识问答流程搭起来 【免费下载链接】dify Build Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move…

作者头像 李华