ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Ruff 真实世界基准语料解析:crates/ruff_benchmark/resources 的 vendored 文件、内嵌机制与基准用法

Ruff 真实世界基准语料解析:crates/ruff_benchmark/resources 的 vendored 文件、内嵌机制与基准用法 Ruff 真实世界基准语料解析crates/ruff_benchmark/resources 的 vendored 文件、内嵌机制与基准用法【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff本篇文章围绕 Ruff 仓库中 crates/ruff_benchmark/resources/README.md 展开系统讲解 Ruff 如何用真实开源项目中的代码文件而非合成测试样例来驱动 lexer、parser、formatter、linter 与类型检查的微基准测试。读完你将领会这些语料文件从哪来、为何要锁定到具体 commit、如何通过include_str!在编译期被静态嵌入以及如何用cargo bench -p ruff_benchmark亲自运行与对比基线。为什么 Ruff 要用“真实世界代码”做基准Ruff 以“extremely fast”著称性能优化与回归防护高度依赖基准测试。Ruff 的基准策略分两层微基准micro-benchmarks由ruff_benchmarkcrate 承载在单个文件级别分别压测 linter、formatter、lexer、parser 以及类型检查ty等模块项目级基准real-world project benchmarks克隆并固定真实 Python 项目 commit做端到端类型检查与墙钟时间测量。resources目录服务的是第一层。其配套文档开宗明义地解释了动机本目录从真实项目中 vendor 了一些文件目的是用真实世界的代码来压测 Ruff 的性能而不是用合成基准。这一点至关重要合成测试样例往往无法代表真实代码中常见的缩进形态、超长表达式、Unicode 字符串、复杂类型注解与实际噪声因而容易高估或低估真实吞吐量。把现实仓库里的高价值文件直接做成语料能让“每字节处理速度”等指标更可信。resources 目录的内容与来源实际目录crates/ruff_benchmark/resources/中除 README.md 外还包含以下文件README 中列出的为前 6 项目录里另有一个 README 未列出的typeis_narrowing.py将在下文说明语料仓库相对路径上游来源项目用途特征resources/numpy/globals.pyNumPy小文件约 3 KB密集的模块级__getattr__/__dir__等惯用法resources/numpy/ctypeslib.pyNumPy中等偏大文件约 17 KBresources/pypinyin.pypython-pinyinUnicode/多语言字符串密集resources/pydantic/types.pyPydantic大文件约 26 KB类型注解复杂resources/large/dataset.pymikeio测试文件 test_dataset.py超大文件约 42 KBstress 大文件吞吐resources/tomllib/init.pyCPython 标准库 tomllib3.124 个文件的“模块级”语料配合 ty 类型检查基准resources/tomllib/_parser.py同上递归下降解析器的成熟实现resources/tomllib/_re.py同上正则驱动辅助模块resources/tomllib/_types.py同上类型定义resources/typeis_narrowing.pyty 回归用例对应一个 ty issueTypeIs收窄场景的大字面量联合每个文件都在 README 中附带了指向上游仓库某一个具体 commit的链接这一点保证了可复现性上游代码一旦演进Ruff 的基准结果不会因外部改动而无故漂移这正是真实项目基准领域“pin commit”的通行做法与 crates/ruff_benchmark/src/real_world_projects.rs 中固定 commit 克隆真实项目的思路一致。需要说明由于本仓库展示的 resources/README.md 为只读快照其中tomllib一条标注了(3.12)指其取自 Python 3.12 的标准库 tomllib 模块个别新增语料如typeis_narrowing.py可能尚未同步进该 README 的清单实际以目录内容为准。许可与版权约定README 明确说明这些文件保留其原始许可证请以资源内嵌链接对应的上游许可证为准例如 resources/tomllib/init.py 文件头就保留了SPDX-License-Identifier: MIT、SPDX-FileCopyrightText: 2021 Taneli Hukkinen及 “Licensed to PSF under a Contributor Agreement” 的原始署名与 MIT 声明。把文件放进resources目录是为了允许离线运行基准并简化构建但版权归属仍归上游作者引用与再分发需遵守各源文件自身许可。语料如何在编译期被“静态内嵌”TestFile 与 include_str!Ruff 把语料文件作为构建期常量嵌入二进制而不在运行时读取文件系统这是它能“离线”运行基准的关键。在 crates/ruff_benchmark/src/lib.rs 中定义了统一的TestFile载体#[derive(Debug, Clone)] pub struct TestFile { name: static str, code: static str, } impl TestFile { pub const fn new(name: static str, code: static str) - Self { ... } pub fn code(self) - str { self.code } pub fn name(self) - str { self.name } pub fn path(self) - PathBuf { ... } // 拼接出 resources/name 的源路径 }随后用include_str!在编译期把每个语料文件的内容烘焙进静态变量pub static NUMPY_GLOBALS: TestFile TestFile::new( numpy/globals.py, include_str!(../resources/numpy/globals.py), ); pub static UNICODE_PYPINYIN: TestFile TestFile::new( unicode/pypinyin.py, include_str!(../resources/pypinyin.py), ); pub static PYDANTIC_TYPES: TestFile TestFile::new( pydantic/types.py, include_str!(../resources/pydantic/types.py), ); pub static NUMPY_CTYPESLIB: TestFile TestFile::new( numpy/ctypeslib.py, include_str!(../resources/numpy/ctypeslib.py), ); pub static LARGE_DATASET: TestFile TestFile::new( large/dataset.py, include_str!(../resources/large/dataset.py), );由此带来的工程收益零运行时 IO基准测量完全排除磁盘读取干扰专注纯 CPU 处理路径离线可跑语料已随 crate 分发无需在基准机上重新 clone 上游仓库单一事实来源TestFile.name还承担了仿真路径的角色例如 formatter 基准会用PyFormatOptions::from_extension(Path::new(case.name()))根据文件名推断.py格式选项。消费这些语料的微基准lexer / parser / formatter / linter / tyTestFile语料被多个 bench 共享它们的共同形态是create_test_cases()返回同一组文件再对每个文件注册一个 Criterion benchmark id。每个 bench 文件在编译期通过 crate features 开关见 crates/ruff_benchmark/Cargo.toml 中ruff_instrumented、ty_instrumented、module_resolution、ty_walltime、codspeed等特性独立启用避免一次性编译全部依赖从而加快 CI。lexer 基准crates/ruff_benchmark/benches/lexer.rs 对每个文件调用lexer::lex(case.code(), Mode::Module)并持续拉取 token 直至EndOfFile遇到Unknown则 panic“输入必须是合法 Python”。它通过Throughput::Bytes(case.code().len() as u64)声明吞吐量使 Criterion 能报告 MB/s 量级的词法吞吐。parser 基准crates/ruff_benchmark/benches/parser.rs 使用同一组文件做完整语法解析parser bench 入口同样引用NUMPY_GLOBALS/UNICODE_PYPINYIN/PYDANTIC_TYPES/NUMPY_CTYPESLIB/LARGE_DATASET衡量 parse 到 CST/AST 的成本。formatter 基准crates/ruff_benchmark/benches/formatter.rs 的每次迭代是完整的格式化流水线先用ruff_python_parser::parse解析再用TriviaRanges::from(parsed.tokens())构造 trivia 区间继而调用format_module_ast(parsed, trivia_ranges, case.code(), options)生成格式文档最后formatted.print()输出字符串。注意其PyFormatOptions通过文件扩展名推断且显式启用PreviewMode::Enabled——因此它压测的是开启 preview 模式的格式化路径。linter 基准crates/ruff_benchmark/benches/linter.rs 是三套 lint 配置的组合linter/default-rulesLinterSettings::default()、linter/all-rulesRuleSelector::All关闭 preview与linter/all-with-preview-rules开启 preview。all-rules/preview 两组都通过disable_io_rules关闭两个基于 shebang/可执行位的 IO 规则注释明确说明是为了消除基准抖动来源。每次迭代内部先parse_module预解析出parsed再以b.iter_batchedParseSource::Precomputed(parsed)复用语法树只测量lint_only(...)的纯 lint 成本并断言parsed.has_valid_syntax()。ty类型检查基准与 tomllib在 crates/ruff_benchmark/benches/ty.rs 中TOMLLIB_FILES用include_str!一次性内嵌 tomllib 的全部 4 个源文件随后setup_tomllib_case()把 4 个文件写入内存文件系统以ProjectMetadata::discover建库并 override 为 Python 3.12 环境最后db.set_check_mode(CheckMode::OpenFiles)打开全部文件。它支持两类典型场景ty_check_file[cold]每次迭代都重建FileCase并做整库冷启动检查ty_check_file[incremental]先在_re.py末尾追加一行注释触发变更事件ChangeEvent::ChangedChangedKind::FileContent再通过db.apply_changes与db.check()测增量路径。两次场景都会调用assert_diagnostics将诊断规约成(DiagnosticId, 文件, 区间, headline, Severity)的元组与EXPECTED_TOMLLIB_DIAGNOSTICS目前为空数组比对确保“测的确实是正确结果”而非仅仅“跑得快”。同一 bench 文件中还有大量ty_micro[...]回归基准大枚举比较、超大元组切片、TypeIs/TypeGuard收窄、递归 protocol 等部分用例的代码形态即来自真实 issue与resources/typeis_narrowing.py一脉相承。从“文件级”到“项目级”real_world_projects 的补充层次resources解决的是单文件微基准而项目级基准由 crates/ruff_benchmark/src/real_world_projects.rs 支撑两者互补。其RealWorldProject结构体携带完整配置字段pub struct RealWorldProjecta { pub name: a str, // 项目名用作缓存目录名 pub repository: a str, // 公开 git 仓库地址 pub commit: a str, // 固定 commit hash防止结果漂移 pub paths: a [a str], // 要 type check 的路径 pub dependencies: a [a str], // 需要由 uv 安装的依赖 pub max_dep_date: a str, // uv 的 --exclude-newer 上限日期 pub python_version: SupportedPythonVersion, }setup 流程与资源目录“离线优先”的设计形成互补在target/benchmark_cache/项目名中git clone --filterblob:none --no-checkout不下载大对象、不立刻检出再git fetch origin commit后精确 checkout 固定 commit已存在则只 fetch 更新用uv venv --python 版本 --allow-existing建虚拟环境并以uv pip install --exclude-newer max_dep_date安装依赖结果缓存在.venv跨次复用保证依赖可复现可选地通过InstalledProject::copy_to_memory_fs把整个项目树递归复制进ruff_db的MemoryFileSystem把 IO 噪声从基准中抹掉之后再由ProjectDatabase消费该快照执行基准。这个模块还用模块级常量TY_ECOSYSTEM_PIN: str 2026-06-17T06:46:32Z统一固定 ty 生态基准的依赖时间窗。也就是说resources之于微基准相当于real_world_projects之于端到端基准——前者依赖编译期内嵌、天然离线后者面向完整项目、自动在 target 下搭建可复现环境。如何运行这些基准以 crates/ruff_benchmark/README.md 与 CONTRIBUTING.md 中 “Microbenchmarks” 一节的说明为准推荐按以下方式使用# 1. 在“基线”上运行一次并保存例如在 main 分支 cargo bench -p ruff_benchmark -- --save-baselinemain # 2. 在改动分支上与基线对比 cargo bench -p ruff_benchmark -- --baselinemain # 3. 只运行词法基准crate 内 benchmark 过滤器 cargo bench -p ruff_benchmark lexer -- --baselinemain仓库内部还定义了便捷别名cargo benchmark等价于cargo bench -p ruff_benchmark --bench linter --bench formatter --即默认只跑 linter 与 formatter 两组文件级微基准。若干实用技巧源自 CONTRIBUTING.md “Benchmarks” 章节用--save-baselinename保存基线用--baselinename对比Criterion 会自动报告相对基线的“improved/regressed”用cargo bench -p ruff_benchmark filter按名字过滤例如lexer、formatter--quiet输出更精简--quick迭代更少、出结果更快但噪声更大需要统计对比多组结果时可分别--save-baselinemain与--save-baselinepr后用critcmp生成可视化对比正式跑基准前保持 CPU 空闲、关闭后台任务并切换性能模式避免短时基准被调度噪声污染微基准按文件粒度的Throughput::Bytes(...)设定吞吐目标报告可解释为每字节耗时或 MB/s。由于ruff_benchmark是纯 dev 用途的 cratepublish false见其 Cargo.toml这些命令只需在仓库内执行不涉及安装或对外发布在 PR 上Ruff 还会通过 CI 跑这些微基准用于性能回归把关。小结crates/ruff_benchmark/resources内嵌了来自 NumPy、python-pinyin、Pydantic、mikeio、CPython tomllib 等真实项目的代码README 记录每个语料的来源与对应 commit所有语料通过include_str!在编译期进入二进制crates/ruff_benchmark/src/lib.rs换来离线运行与零 IO 噪声同一组语料被 lexer、parser、formatter、linter 四个 bench 复用而 tomllib 语料与typeis_narrowing.py则服务于 ty 类型检查的冷启动/增量/收窄回归基准若要覆盖“整个真实项目”的维度可参考 crates/ruff_benchmark/src/real_world_projects.rs 的项目级克隆-固定-建 venv-入内存文件系统的完整流程运行与对比方式收敛为cargo bench -p ruff_benchmark加--save-baseline/--baseline/过滤器参数详细操作指引见 CONTRIBUTING.md。一言以蔽之这些被 vendor 的真实代码文件是 Ruff 微基准与类型检查基准的“现实训练集”理解其来源、内嵌方式与消费链是深入 Ruff 性能工程的第一个入口。【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表