用法与调试
前五部分讲 loom 内部怎么工作,这一部分站在使用者一侧:代码怎么接、模型怎么写、失败了怎么查。每条建议都落回前面某一章的机制,并配本机实测。
flowchart LR a["cfg(loom) 切换层:被测代码换成 loom 类型"] --> b["写模型:loom::model(|| ...)"] b --> c["RUSTFLAGS="--cfg loom" cargo test --release,LOOM_MAX_PREEMPTIONS=2 或 3"] c -->|失败| d["LOOM_CHECKPOINT_FILE + INTERVAL=1 存下失败那一轮"] d --> e["LOOM_LOG=trace + LOOM_LOCATION 只重放那一轮"] c -->|通过| f["反向验证:改错一处应失败"]
三章:
- cfg(loom) 切换层:文档推荐的
mod sync写法;API 差别清单(原子不能const构造的编译错误原文);tokio、bytes 的cfg(all(test, loom))、crossbeam 的crossbeam_loom、concurrent-queue 等裸cfg(loom)三种写法,以及下游开--cfg loom时它们各自会不会被换掉;check-cfg声明与警告原文。 - 写一个好模型:线程数与操作数的交错数表;把常数调小;自旋要
yield_now;确定性;断言与结果收集;反向验证;skip_branch;抢占上限取 2 或 3;release 与 debug 的速度(E20)。 - checkpoint、日志与位置:checkpoint 只在整 interval 轮写(E3),文档三步法与代码的出入和一个能用的流程;残留文件的副作用;没开 feature 的行为(E3 反向);
LOOM_LOG的级别与输出捕获;LOOM_LOCATION只看是否存在。
环境变量速查
全部在 Builder::new 里读(model.rs:76-114),值解析失败直接 panic。字段与默认值的完整对照见 model 与 Builder。
| 变量 | 作用 | 本部分相关的要点 |
|---|---|---|
LOOM_MAX_PREEMPTIONS | 抢占上限 | 文档建议 2 或 3 |
LOOM_MAX_BRANCHES | 一轮的分支数上限,默认 1000 | 自旋不 yield_now 会撞上 |
LOOM_MAX_PERMUTATIONS、LOOM_MAX_DURATION | 提前结束 | 只在整 interval 轮检查 |
LOOM_CHECKPOINT_FILE、LOOM_CHECKPOINT_INTERVAL | 存取路径,默认每 20 000 轮 | 需要 checkpoint feature;文件存在就从那里开始 |
LOOM_LOG | EnvFilter 过滤串 | 只在 loom::model 里生效 |
LOOM_LOCATION | 记录调用位置 | 只看是否存在 |
本部分的实验
| # | 目录 | 看什么 | 章 |
|---|---|---|---|
| — | exp-loom/cfg-check/ | 不声明 check-cfg 时的警告原文;static 里 AtomicUsize::new 在 --cfg loom 下的编译错误 | cfg(loom) 切换层 |
| E2 | exp-loom/survey/tests/bound.rs | 线程数 × 操作数 × 抢占上限的交错数 | 写一个好模型 |
| E11 | exp-loom/survey/tests/misc.rs | 自旋锁不 yield 撞分支上限,yield 后通过 | 写一个好模型 |
| E17 | exp-loom/survey/tests/extra.rs | skip_branch 与 stop_exploring 的效果 | 写一个好模型 |
| E20 | exp-loom/speed/ | release 与 debug 的每秒交错数 | 写一个好模型 |
| E3 | exp-loom/survey/tests/checkpoint2.rs、exp-loom/no-checkpoint/ | 早失败与晚失败的 checkpoint 文件;INTERVAL=1 的精确重放与耗时;不开 feature | checkpoint、日志与位置 |
| — | exp-loom/usage/ | 切换 flags 时的重编;残留 checkpoint 文件;LOOM_LOG 的输出与捕获 | checkpoint、日志与位置 |
💬 关联讨论
发起讨论加载中...