Rich 性能基准测试指南:Airspeed Velocity 基准套件的设计、运行与结果发布流程
【免费下载链接】richRich is a Python library for rich text and beautiful formatting in the terminal.项目地址: https://gitcode.com/gh_mirrors/ri/rich
Rich 官方在 benchmarks/ 目录下维护了一套基于 Airspeed Velocity(asv)的性能基准测试体系,用于持续监控各核心渲染路径(文本换行、表格、Pretty 输出、颜色降级、Segment 切分等)的性能随版本演化的趋势。读完本文,你将了解该基准体系如何组织测试套件与测试素材、如何阅读 asv 配置文件 中的每个关键项、如何用asv run/asv publish等命令运行并产出基准结果,以及如何按官方流程更新对外的基准仪表盘。
基准测试体系概述
benchmarks/README.md 开宗明义:该目录“contains benchmarks, for monitoring the performance of Rich over time”——即基准测试的首要目标不是给出一个绝对分数,而是建立一条可追溯的性能曲线,让任何一次重构或优化都能被量化地观察。整套体系由三部分构成:
- 基准定义:benchmarks/benchmarks.py 中的各测试套件(Suite),配合 benchmarks/snippets.py 中的测试素材;
- 运行环境配置:仓库根目录的 asv.conf.json,声明 Python 版本、虚拟环境类型、结果与 HTML 输出目录等;
- 结果与发布:
benchmarks/results/下的 JSON 结果文件,以及经asv publish生成的静态站点(benchmarks/html/)与对外仪表盘。
README 中还提醒:完整命令选项应以asv run --help的输出为准,下文只覆盖常用操作。
asv 配置文件逐项解读
asv.conf.json 是与官方文档 关联配置 中../asv.conf.json相对链接指向的同一文件(位于仓库根目录),其关键配置项如下:
| 配置项 | 值 | 作用 |
|---|---|---|
version | 1 | asv 配置文件格式版本 |
project | rich | 被基准测试的项目名,也用于卸载命令 |
repo | . | 以当前仓库根目录作为 DVCS 仓库根 |
dvcs | git | 版本控制方式,asv 依赖它遍历 commit |
branches | ["master"] | 默认跟踪的分支 |
environment_type | virtualenv | 为每个 commit 创建隔离的 virtualenv 环境 |
pythons | ["3.10"] | 固定使用 Python 3.10,保证跨 commit 对比口径一致 |
matrix | {"setuptools": ["59.2.0"]} | 矩阵变量,锁定 setuptools 版本,排除环境差异对结果的干扰 |
install_timeout | 180 | 项目安装超时 180 秒 |
html_dir | ./benchmarks/html | asv publish生成静态站点的输出目录 |
results_dir | ./benchmarks/results | JSON 结果文件存放目录 |
env_dir | ./benchmarks/env | 各 commit 对应的虚拟环境缓存目录 |
构建与安装链条同样值得关注:build_command依次执行pip install poetry、python setup.py build、python -mpip wheel --no-deps --no-index -w {build_cache_dir} {build_dir},先构建 wheel 再安装;install_command为in-dir={env_dir} python -mpip install {wheel_file},uninstall_command则用return-code=any容忍卸载失败。这一设计意味着每个被测试的 commit 都是“干净安装”的最新构建产物,性能对比排除了陈旧依赖的干扰。
基准测试套件设计
benchmarks/benchmarks.py 共定义了 8 个测试套件,全部输出重定向到StringIO()的Console,并统一开启color_system="truecolor"、legacy_windows=False,以固定渲染路径:
- TextSuite(benchmarks.py#L14-L61):针对
rich.text.Text的核心操作,包括wrap(宽 12、overflow="fold"的窄终端换行)、with_indent_guides、fit、split、divide、align、render。每个操作都提供两组输入:普通英文素材(LOREM_IPSUM)与“Unicode 重”素材(UNICODE_HEAVY_TEXT,含大量日文宽字符、链接与 Markdown 标记,见 snippets.py),用于验证单元格宽度计算在宽字符、混合文本下的开销。 - TextHotCacheSuite(benchmarks.py#L64-L72):连续 20 次对 Unicode 重文本执行
wrap,测量缓存命中后的热路径性能,与 TextSuite 的冷路径形成对照。 - SyntaxWrappingSuite(benchmarks.py#L75-L94):对
Syntax(code=snippets.PYTHON_SNIPPET, lexer="python", word_wrap=True)分别在宽 20(重度换行)、60(中度换行)、100(基本不换行)三档终端宽度下打印,覆盖语法高亮 + 换行的典型压力场景。 - TableSuite(benchmarks.py#L97-L126):以 “Star Wars Movies” 示例表(含 markup 样式单元格)分别打印在宽 100(无换行)与宽 30(重度换行)的 Console 中。
- PrettySuite(benchmarks.py#L129-L145):对嵌套字典
PYTHON_DICT打印默认Pretty、indent_guides=True、justify="center"三种形态。 - StyleSuite(benchmarks.py#L148-L166):
Style.parse解析 ANSI 名色、hex 色、混合复杂样式(dim bold reverse #00ee00 on rgb(123,12,50)),以及样式相加style1 + style2。 - ColorSuite 与 ColorSuiteCached(benchmarks.py#L169-L204):将
#0d1da0解析出的真彩色分别降级到EIGHT_BIT/STANDARD/WINDOWS三档颜色系统。Cached 版本在setup中先各执行一次降级“预热缓存”,专门测量缓存命中路径。 - SegmentSuite(benchmarks.py#L207-L218):对 10 个
Segment组成的行调用Segment.divide(line, [5, 10, 20, 50, 108, 110, 118]),测量布局系统在按切割点切分渲染行时的开销。
测试素材的选取与 Rich 的实际负载高度对应:snippets.py 中的PYTHON_SNIPPET是带类型注解与长 docstring 的真实布局算法代码(用于 Syntax 换行),UNICODE_HEAVY_TEXT是包含日文宽字符、URL、emoji 的 README 式文本(用于单元格宽度计算的压力测试),MARKUP则是 20 行带粗体/斜体/下划线/链接的 markup 拼接而成(用于 render 测试)。
源码印证:基准为何盯住这些热路径
结合当前仓库源码,可以看出基准套件挑选的正是 Rich 渲染管线中被反复调用的热点:
- 颜色降级的缓存:
Color.downgrade在 rich/color.py#L512-L513 上标注了@lru_cache(maxsize=1024),降级逻辑会按 HLS 饱和度判断灰度、映射到 256 色立方体。ColorSuite与ColorSuiteCached的成对设计,恰好分别度量该函数“未命中/命中 lru_cache”两种状态,是典型的缓存收益验证手法。 - Segment 切分:
Segment.divide(rich/segment.py#L629-L632)是 classmethod,按cuts位置把 segment 流切分为若干行;实现中绑定cached_cell_len做单元格长度计算、用局部变量缓存list.append/clear等方法引用以降低开销。SegmentSuite与TableSuite的“窄终端重度换行”用例正压测这段逻辑。 - 文本 wrap/fold:
TextSuite中wrap(console, 12, overflow="fold")的极窄宽度是最坏情况——几乎每个词都要重新断行,能放大cells.py宽度表查询的成本;而TextHotCacheSuite的 20 次循环则用于观察这些查找表进入 CPU/函数缓存后的稳态表现。
运行基准测试
按 benchmarks/README.md 的指引,常用操作有三类:
# 1. 对 master 分支运行基准(跟踪 branches 配置中的分支) asv run # 2. 只测当前分支最新一个 commit(HEAD^! 表示以 HEAD 为起点的单 commit 历史) asv run HEAD^! # 3. 生成可浏览的静态结果网站,HTML 输出到 benchmarks/html asv publish结合 asv.conf.json 的配置可以预期其行为:asv run会沿 git 历史逐个 commit 创建benchmarks/env/下的虚拟环境(Python 3.10、setuptools 59.2.0),构建并安装该 commit 的 wheel 后执行 benchmarks/benchmarks.py 中全部time_*方法;耗时较长(官方说明“take several minutes”级别),且每个 commit 独立计时。查看完整选项建议直接运行asv run --help。
结果文件的组织方式
asv run的结果落在results_dir即benchmarks/results/,当前仓库已收录一台机器的历史数据,目录结构如下:
benchmarks/results/ ├── benchmarks.json # 基准元数据:名称、代码哈希、计时类型(seconds)、版本指纹 └── darrenburns-2022-mbp/ # 以机器名为子目录 ├── machine.json # 机器指纹 └── <commit-hash>-virtualenv-py3.10[-setuptools59.2.0].json # 每个 commit 一份结果其中 machine.json 记录了采集机指纹:Apple M1 Pro(arm64,10 核,16GB 内存,Darwin 21.2.0),这让读者在引用结果时能明确硬件前提。benchmarks.json 则为每个基准项记录type: "time"、unit: "seconds"及代码version指纹(源码哈希)——当基准代码本身变化时,asv 会据此区分新旧口径,避免把测试改动误读为性能变化。结果文件名的后缀virtualenv-py3.10与-setuptools59.2.0正对应配置文件中的environment_type与matrix,体现了“环境指纹进入文件名”的追溯设计。
更新基准仪表盘网站的完整流程
README 给出了 7 步发布流程,这里按原文顺序完整继承并补充说明:
- 登记 tag:确认要纳入对比的发布 tag 都已写入仓库根目录的 asvhashfile。该文件目前从
v10.0.0起逐行列出了后续各版本 tag; - 对 tag 运行基准:执行
asv run HASHFILE:asvhashfile,asv 会读取文件中的每个 tag 作为 commit 起点分别运行,耗时数分钟; - 本地生成 HTML:执行
asv publish,产出位于benchmarks/html的静态站点; - 本地预览:执行
asv preview启动本地 webserver,打开其给出的 URL,人工检查仪表盘内容是否正常; - 检出 rich-benchmarks 仓库:单独检出官方用于托管仪表盘的
rich-benchmarks仓库并进入其目录(建议与rich检出在同一文件系统层级,方便相对拷贝); - 拷贝 HTML:把上一步生成的 HTML 复制到该仓库根目录,例如
cp -r ../rich/benchmarks/html/* .; - 自动发布:当这些 HTML 合并进
rich-benchmarks的main分支后,其 GitHub Action 会自动更新对外仪表盘,无需额外部署操作。
适用前提与限制
- 基准固定于Python 3.10 + setuptools 59.2.0的 virtualenv 环境(见 asv.conf.json),因此结果反映的是该口径下的相对趋势,不宜直接外推到其他解释器版本;
- 已有结果文件来自 Apple M1 Pro 单机(见 machine.json),跨机器对比时需留意 asv 的机器隔离机制;
asv run HEAD^!适合开发者自测最新 commit,但只有跑完全部 tag 并asv publish后才能用于更新公开仪表盘;- 若需扩展基准,参照 benchmarks/benchmarks.py 的既有模式即可:
setup中构造固定Console与素材,time_*方法只调用被测 API,冷/热路径成对设计,素材统一取自 benchmarks/snippets.py。
【免费下载链接】richRich is a Python library for rich text and beautiful formatting in the terminal.项目地址: https://gitcode.com/gh_mirrors/ri/rich
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考