Files
STM32F4-Base/docs/门禁说明/mem-budget.md
T
wandering1 c0d7bb9c8e docs(门禁): mem-budget 第 6 节补一条盲区——同码凭证按 git 索引生成,多人同树时必红
今天道G 报出 `check_size_gate.py --local` 单跑 exit 1(代码指纹与体积测量指纹不一致),我复核后确认这不是
预算问题、也不是谁改坏了台账,而是**该凭证的定义在多人同树下必然不成立**:代码指纹取的是 **git 索引里的
blob**,而此刻工作区里有别的任务在飞、尚未入索引的改动 ⇒ 两边算出来的东西本来就不是同一份内容。

写进 §6 的三点判据:
· 它**只挂在 `scripts/ci_local.py` 的 L0c,不在这 51 条 pre-commit 钩子内** ⇒ 红它不等于提交
会被拦,别在
  提交被拦的清单里找它;
· 报错若同时列出「未入索引的文件」而那些文件正被别的任务改 ⇒ 等它们入库后统一 `@build` →
  `ram_baseline.py --update` 补凭证;**绝不为把它调绿去 `git add` 别人在飞的改动**(这条比前两条更要紧,
  今天就这样发生过一次:别人已 staged 的文件会被我的 add 顺手卷进我这一笔);
· 本节写作时凭证**仍是红的**(回填发生在通讯卡入库之后)——我只写成因与判据,**不预告还没发生的结果**,
  这正是 `pre-commit使用说明.md` §2.5 那条「注释陈述事实不陈述意图」在同一天的第二次应用。

自查:`check_doc_links --all` exit 0(198 篇)、本篇 `--sections-strict` 通过、noBOM
 / LF / U+FFFD=0 / 结尾
换行齐;`id-check` 未受影响(本笔零编号)。本笔零代码,且此刻两条道正在写 `Drivers/BSP/UI/` 与
`App/algo/`,故只提这一只文档文件。
2026-10-27 09:47:23 +08:00

6.9 KiB
Raw Blame History

mem-budget — RAM 总量红线(RW_IRAM1 / RW_CCM 超 92% 即拦)

一句话:它是总量刹车,不是预算规划器。它只管两件事:任一静态区域别超 92%,以及 台账里的水位数字别和 .map 漂移。

  • 配置:entry: python scripts/ram_baseline.py --gate、pass_filenames: false、 files: 覆盖 App/、Drivers/BSP/、Src/、Inc/、Lib/lv_conf.h 等会影响占用面。
  • 背景:登记簿条目「缩堆迁 CCM 后半(暂缓)」的前半;三件套里的机械部分(阈值门禁 + 趋势台账 + 台账受管区)。

1. 它在查什么

  1. 解析 .map,算 RW_IRAM1、RW_CCM 的占用率;任一 > 92.0% → FAIL,并附 Top-10 RW+ZI 对象表(直接告诉你是谁吃掉的);
  2. 顺带核对 docs/内存管理/RAM预算台账.md 的受管区(MEM_BUDGET:BEGIN/END)是否与 .map 一致——防台账漂移,与 mem-numbers 同一思路;
  3. .map 不存在 → 自适应跳过(这台机器没做 Keil 构建)。

配套的两个入口(不在提交门禁里,属于日常):

  • --update:每次 @build 后往 scripts/ram_baseline.tsv 追一行趋势;
  • --trend:打印趋势并高亮 RW+ZI 较上一行增长 > 1 KB 的对象——把"ZI 增量超 1 KB 必须解释" 这条纪律机械化;
  • --write:同步台账受管区(区域水位 + 子系统配额对照)。

子系统配额(规划值,改配额要先在台账变更记录里登记,再改脚本 QUOTAS): 网络 12 KB / 存储 12 KB / UI 16 KB / RTOS 堆 56 KB / 应用 8 KB。

2. 为什么要它

  • 本仓 RAM 是真红线:RW_CCM 常年 87.9%(FreeRTOS 堆迁 CCM 之后),离 92% 只差几个百分点; 链接期才发现塞不下,代价是回退一大片改动。
  • 实跑当前值:RW_IRAM1 57.4% / RW_CCM 87.9%(阈值 92%)。
  • 趋势台账让"谁什么时候吃掉了这 3 KB"可查,不必靠记忆。

3. 触发面 / 看不见什么

  • 只看 RW_IRAM1 与 RW_CCM 两个静态区域;不看:栈运行时水位、FreeRTOS 堆运行时余量、 堆碎片、MicroLIB 的 512 B C 堆(那条纪律是"自研代码禁用 malloc/free",2026-10-23 起由 coding-standard 的 CODE-RULE-20 机器拦截(见 coding-standard.md §1/§7),不再只靠评审)。
  • .map 缺失即跳过 → 无构建的机器(含远端 CI)这一门不产生信息。

4. 报错怎么读

RAM 预算门禁 FAIL:RW_CCM 占用 92.3% > 92%(阈值 92%)
   Top-10 RW+ZI 对象 …
  • 单独跑:& '.venv\Scripts\python.exe' scripts/ram_baseline.py --gate(只读); --trend -n 12 看趋势。--gate 不修改任何东西,要同步台账用 --write。

  • 报 FAIL 的正确动作是回去减(缩缓冲/挪区段/减日志调用点),不是抬阈值。

  • 两类软提醒不拦提交:tsv 末行落后于 .map(忘了跑 --update)、.map 早于最新源码(忘了 @build)。

  • 退出码:0 = 通过或跳过 / 1 = 超阈值或台账漂移 / 2 = 解析失败(.map 读不出结构,不等于"没问题")。

  • .map 解析口径复用 scripts/ram_report.py,两个脚本不会各说各话。

  • 为什么需要(背景):2026-09 体系评审提出的"超阈值即失败 + Top-10 附表"此前没有任何机械检查 ——mem-numbers 只核数字对不对,不判是否超限。

5. 好处

  • 总量红线机械化,红线以下谁都能放心加东西;
  • Top-10 归属表把"超了"变成"某某对象吃了多少",省掉一次手工 .map 考古;
  • 趋势 + >1 KB 高亮让"增量必须有解释"变成可查记录,而不是口头承诺。

6. 限制与盲区

  1. 92% 是拍的管理阈值,不是安全余量计算(脚本里 THRESHOLD_PCT = 92.0)。它不回答 "还剩多少才够下一个任务/缓冲"——那是 docs/内存管理/RAM预算台账.md 的配额表与人的事。
  2. 静态视角:栈峰值、堆低水位、碎片一概看不见(运行时水位要靠串口 [STACK] 与 stack_report.py)。
  3. 只看两个区:Flash(ER_IROM1)不在本门阈值内,它由 mem-numbers 报数、无人卡阈值。
  4. .map 缺失即"通过"式跳过 → 在没有 Keil 构建的环境里绿,不代表有余量。远端缺口已于 2026-10-25 关闭:scripts/check_size_gate.py --ci 用同码凭证按同一常数复核红线(runner 无需 Keil),--gate 无 .map 的 SKIP 文案也已改为明说「SKIP 不等于 PASS」;口径正文 = 该脚本 docstring。
  5. 配额对照是"目标态 vs 现状",现状超配(例如 UI)会被如实展示但不拦提交——它是台账,不是红线。
  6. 阈值/配额改动没有双人复核机制,改 QUOTAS 或 THRESHOLD_PCT 只靠提交说明约束。
  7. 并行分支约定(Lead 裁决 2026-10-12):分支不跑 --write,台账由主干统一回填;分支上 本门与 mem-numbers 可能因受管快照与 .map 漂移而红,那不代表预算超标(处置见 §7 的 mem-numbers 篇)。
  8. 同码凭证在「多人同树」下必然不成立(2026-10-27 实测):check_size_gate.py --local 的代码指纹取 git 索引里的 blob,所以「工作区有别人在飞、尚未入索引的改动」时指纹一定对不上,报「这份源码没有被 真实链接测量过」——这不是预算问题,也不拦提交(该脚本只挂在 scripts/ci_local.py 的 L0c,不在 51 条 pre-commit 钩子内)。判据:报错里若同时列出「未入索引的文件」且那些文件正被别的任务改,就等它们入库后 统一 @build → ram_baseline.py --update 补凭证,别为了把它调绿去 git add 别人在飞的改动。本条写作时 (2026-10-27 09:4x)凭证仍是红的:App/protocol/iec104/iec104_comm.{c,h} 正被通讯道改、未入索引; 回填动作发生在该卡入库之后,届时以 --update 的实际输出为准,本节不预告结果。

7. 豁免与基线

  • 没有基线、没有 --no-verify 之外的合法豁免:超了就减。
  • docs/内存管理/RAM预算台账.md 的受管区是事实展示区,不是豁免登记表;别在那里"解释一下"就算过关。

8. 改这个门禁本身

  • 抬阈值前必须在台账里写清"为什么 92% 变松了",否则等于把刹车线往后画;
  • 新增区域(例如再开一个自定义段)要同时改解析器与台账口径,否则新区域完全不在监控内;
  • --update 的 tsv 是趋势事实源,改列格式会让 --trend 的历史对比失效。

9. 变更记录

日期 变更
2026-10-27 §6 补第 8 条:同码凭证按 git 索引 blob 生成,工作区有在飞改动时 --local 必红;该检查只在 ci_local 的 L0c,不是 pre-commit 钩子,不拦提交(成因由道G 报出、Lead 复核)
2026-10-23 首篇逐项文档(实跑:RW_IRAM1 57.4% / RW_CCM 87.9%,阈值 92%)