十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

herdr 内 libghostty-vt 基准测试指南:用 ghostty-gen 与 ghostty-bench 做可复现的终端性能对比

herdr 内 libghostty-vt 基准测试指南:用 ghostty-gen 与 ghostty-bench 做可复现的终端性能对比 herdr 内 libghostty-vt 基准测试指南用 ghostty-gen 与 ghostty-bench 做可复现的终端性能对比【免费下载链接】herdrthe runtime your coding agents live on项目地址: https://gitcode.com/GitHub_Trending/her/herdr本指南围绕 herdr 仓库 vendored 的 libghostty-vt 终端引擎中的基准测试工具链展开核心是理解ghostty-gen合成输入数据生成器与ghostty-bench基准测量器的分工、构建方式、运行参数与分支性能对比方法。读完本文你将能够搭建一套“先生成固定语料、后用 hyperfine 对比多个构建产物”的可复现基准流程避免把生成开销混入测量、误用 debug 构建、并行跑基准等常见陷阱从而得到可用于代码改动评估的可信数据。这套工具的权威说明文件是 benchmark 目录的 AGENTS.md它与 仓库根目录的 AGENTS.md整体开发命令约定互补是 libghostty-vt 组件内性能测量相关改动例如终端解析、屏幕克隆、压缩的守则。基准测试工具的两个角色libghostty-vt 的基准测试把“制造输入”和“测量执行”严格拆成两个独立可执行文件避免混淆被测对象工具职责源码入口ghostty-gen生成合成输入数据字节流、转义序列等写向 stdoutsrc/main_gen.zig →synthetic/main.zigghostty-bench消费已存在的输入数据文件并执行基准测量src/main_bench.zig →benchmark/main.zig两个二进制在同一份构建脚本中定义。查看 GhosttyBench.zig 可以看到ghostty-gen的根模块是src/main_gen.zig构建注释写明“数据生成需要跑一段时间我们总是希望它够快”ghostty-bench的根模块是src/main_bench.zig注释同样强调“基准测试总是在 release 模式下”二者的.optimize字段都被直接写死为.ReleaseFast链接 libc。也就是说这两个工具本身在源码层面就永远不会以 debug 模式构建——真正需要-DoptimizeReleaseFast保证的是被测终端引擎代码整体处于 release 优化状态原因见下文“构建”一节。两个 CLI 的可选子命令ghostty-bench不是单一测试而是一个按子命令分派的基准框架。benchmark/cli.zig 定义了Action枚举子命令列表与Action.Struct()的编译期映射每个 action 对应目录下一个“命名可预测”的模块文件模块需提供OptionsCLI 参数结构、create从参数构造实例、benchmark返回一个Benchmark三样东西基准子命令对应模块测量对象terminal-streamTerminalStream.zig从输入到终端状态更新的完整链路样式、光标、擦除、模式等最接近真实 IO 线程的工作terminal-parserTerminalParser.zig更隔离的 VT 转义序列解析测量osc-parserOscParser.zigOSC操作系统控制序列解析apc-parserApcParser.zigAPC 序列解析page-compressionPageCompression.zig页大小原始字节的 LZ4 块压缩 / 解压吞吐有意与终端页的所有权与生命周期解耦scrollback-compressionScrollbackCompression.zig滚动回压入侧的压缩相关路径codepoint-widthCodepointWidth.zigUnicode 码点显示宽度计算grapheme-breakGraphemeBreak.zig字素簇切分screen-cloneScreenClone.zig屏幕克隆相关路径hyperlink-mapHyperlinkMap.zig超链接映射维护is-symbolIsSymbol.zig符号判定相关函数上述表中子命令的调用形式直接来自 PageCompression.zig 头部示例如ghostty-bench page-compression --modereport --data/tmp/pages.raw。ghostty-gen侧同样有 synthetic/cli.zig 维护的生成器子命令集合ascii、kitty、osc、utf8其分派逻辑与 benchmark CLI 共用同一套cli.action检测机制。构建基准二进制构建命令来自 benchmark AGENTS.md 原文# 基础构建 zig build -Demit-bench -DoptimizeReleaseFast # macOS跳过 macOS App bundle加快编译 zig build -Demit-bench -DoptimizeReleaseFast -Demit-macos-appfalse注意三点必须显式传-DoptimizeReleaseFast。虽然ghostty-gen/ghostty-bench两个可执行文件在 GhosttyBench.zig 里被固定为.ReleaseFast但被测的终端库代码与整体项目其它目标的优化级别仍受全局-Doptimize控制如果整体落在 debug 优化下跑出来的结果会非常慢完全不代表真实性能。这也是文档反复强调该参数的原因。产物位置。两个工具安装到标准zig-out/bin/下zig-out/bin/ghostty-gen与zig-out/bin/ghostty-bench文档中分支对比流程也直接引用zig-out/bin/ghostty-bench这一路径。修改点若集中在终端引擎本身仓库根 AGENTS.md 还提供了更快迭代的测试入口zig build test-lib-vt -Dtest-filterfilter见 libghostty-vt 开发指南与基准构建互补。基准测试工作流先有数据再谈测量benchmark AGENTS.md 用“Workflow”一节给出几条铁律全部围绕一个目标测量只能反映被测代码的差异不能混入别的成本。生成与测量必须分离计时比较时先用ghostty-gen生成数据文件稍后再用ghostty-bench测量它不要直接把ghostty-gen管道直连ghostty-bench。一旦ghostty-gen ... | ghostty-bench ...生成成本随机数产生、UTF-8 组装、缓冲写入等就会被计进基准耗时导致分支间的比较充满噪声你无法判断差异来自被测改动还是来自生成器的不稳定。从实现看两套 CLI 也确实按这种“分离”设计ghostty-gen的输出固定走 stdoutsynthetic/cli.zig 写入std.stdout并在结束 flush而ghostty-bench的输入来自文件或 stdin见下文--data两者之间只通过“文件”这一介质相连而不是管道。输入语料的三条可复现纪律比较不同修订时复用完全相同的生成文件。若每次比较都重新生成字节分布的任何抖动都会混入结果同一份文件才能把差异收敛到被测代码上。生成器支持固定种子时优先使用确定性输入fixed seed。这点与源码相印证ghostty-gen主入口默认以std.time.nanoTimestamp()这类时间值做种子synthetic/cli.zig默认情况并不确定因此只有支持--seed的生成器子命令才能产出逐字节可复现的语料。例如 Utf8 生成器 就暴露了--seed未设置时才回退到时间种子。固定种子的好处是任何人包括你切换分支后都能用同一参数重新生成“相同”的文件。大型生成语料放在仓库之外除非这次改动确实要求把测试数据签入仓库。基准语料动辄数十 MB见下文的 64 MiB 读入上限塞进 git 会让仓库迅速膨胀也会让“复用同一文件”变得困难。文档的建议是把语料放在/tmp等仓库外路径比较分支时反复指向它。使用 ghostty-gen 生成输入语料生成器沿用与ghostty-bench相同的子命令调度。以 UTF-8 生成器 为例一次可复现的生成可以写成# 生成确定性的 UTF-8 随机字节流语料重定向保存到仓库外 ghostty-gen utf8 --seed42 /tmp/bench-utf8.raw # 可以调节各长度 UTF-8 序列的相对权重、是否只输出可打印 ASCII、 # 以及注入畸形 UTF-8 的比例0.0 ~ 1.0 ghostty-gen utf8 --seed42 --weight-one2.0 --ascii-printable-onlyfalse \ --invalid-rate0.01 /tmp/bench-utf8-mixed.rawUtf8.zig 的参数结构 表明可用选项包括--seed确定性种子、--weight-one/--weight-two/--weight-three/--weight-four1~4 字节 UTF-8 序列相对权重默认各 1.0权重和为负或为 0 会被判定非法、--ascii-printable-only是否仅限可打印 ASCII、--invalid-rate畸形序列注入概率必须落在[0, 1]越界返回InvalidValue。加上ascii、kitty、osc三个生成器可以组合出覆盖纯 ASCII、kitty 键盘协议、OSC 序列等不同压力面的语料集合。注意此处参数名以各生成器模块内实际定义为准子命令名可对照 synthetic/cli.zig 的 Action 枚举。运行 ghostty-bench--data 输入约定所有面向数据流的基准都通过统一的--data path指定输入。其语义定义在 benchmark/options.zig 的dataFile()未传路径返回null路径为-时读 stdin否则打开指定文件。特别地--data未设置时基准是 noop多个基准模块都写明这一约定例如 TerminalStream.zig 与 PageCompression.zig。这意味着漏传数据文件不会跑坏只会测出一个空的循环开销文档推荐传入预生成的文件而非 stdin因为文件可以让不同分支、不同轮次读到完全一致的字节。示例一terminal-stream端到端吞吐TerminalStream 使用完整的只读终端流处理器每条转义序列都会真实更新终端状态样式、光标移动、擦除、模式等是最贴近真实 IO 线程的吞吐基准。它有两个额外选项--terminal-rows默认 80与--terminal-cols默认 120软换行行为与页大小内存开销都受终端尺寸影响因此分支比较时必须让两边尺寸完全一致内部以 64 KiB 的读缓冲消费输入文件缓冲区大小刻意对齐真实 IO 线程的读缓冲见 TerminalStream.zig 的注释。ghostty-bench terminal-stream --data /tmp/bench-utf8.raw ghostty-bench terminal-stream --data /tmp/bench-utf8.raw \ --terminal-rows40 --terminal-cols160示例二page-compression压缩专项PageCompression 对“页大小”的原始字节做 LZ4 块级压缩/解压测量刻意不涉及终端页所有权与生命周期便于把编解码器本身的吞吐独立出来。它通过--mode选择计时区间内的操作mode行为用途noop只按页边界遍历输入不调用编解码器度量基准循环本身的最小开销下限基线compress把每个输入块压缩进可复用输出缓冲无分配编解码器纯吞吐store压缩后把精确大小的编码块拷贝进受限环ring保留模拟滚动回有界存储时的分配/驱逐/复用成本decompresssetup 阶段预压缩好全部块再逐块解压进可复用缓冲解压吞吐report逐页打印 raw / encoded 与压缩比看压缩率不做计时结论关键参数--data预生成语料最大读入上限 64 MiB防止坏语料耗尽内存、--page-size默认 400 KiB匹配 ReleaseFast 构建下当前目标的标准终端页若语料不是整倍数末块按短块保留、--loops每步重复整个语料多少次默认 1、--retained-pagesstore模式保留的精确编码块数默认 25近似由标准 400 KiB 页构成的约 10 MB 滚动回。真实页背衬内存的 raw dump 是最具代表性的输入——它包含 cells、rows、styles、grapheme、hyperlinks 及分配器元数据正是编解码器实际会看到的字节。# 先看压缩率非计时 ghostty-bench page-compression --modereport --data/tmp/pages.raw # 用 hyperfine 对比“纯编解码”与“带精确存储”两条路径 hyperfine --warmup 3 \ ghostty-bench page-compression --modecompress --loops100 --data/tmp/pages.raw \ ghostty-bench page-compression --modestore --loops100 --data/tmp/pages.rawreport模式会逐页输出page/raw/encoded/ratio并在末尾汇总总量与压缩后 workspace 与输出上界信息实现见 PageCompression.zig适合先用于校验语料的压缩率是否合理再进入计时环节。底层运行模型一次进程 一轮测量了解 Benchmark.zig 的模型有助于正确解读 hyperfine 结果每个基准模块向Benchmark.init提供一个vtablestepFn必选执行被测工作可被调用多次以及可选的setupFn/teardownFn各只执行一次不计入测量结果数据加载、输出分配、decompress 模式预压缩等准备工作都放在 setup见 Benchmark.zig运行模式RunMode分为once只跑一次 step与duration(纳秒)跑到指定时长为止不会打断单个 stepcli.zig主入口以b.run(.once)结束benchmark/cli.zig运行结果返回iterations与duration在 macOS 上Benchmark.zig 会用os_signpostcategory 为points_of_interest区间名为ghostty标记单次测量区间便于在 Instruments 中定位因此ghostty-bench单次进程是一个完整的“setup → 计时 step → teardown”单元。hyperfine 测量的是整个进程生命周期而 setup 开销打开文件、载入语料也包含在内——所以 PageCompression.zig 特别提示语料较小时用--loops放大每进程内的工作量从而把 setup/teardown 摊薄到单次测量里。用 hyperfine 做严谨的分支性能对比benchmark AGENTS.md 明确要求优先用 hyperfine 比较基准耗时并且比较对象永远是ghostty-bench命令行而不是生成器。# 单二进制预热 5 次、测 30 轮hyperfine 会给出中位数/均值/标准差 hyperfine --warmup 5 --runs 30 \ ./zig-out/bin/ghostty-bench terminal-stream --data /tmp/bench-utf8.raw为什么要 warmup 多次测量CPU 频率爬升、缓存与 TLB 预热都会让第一次运行显著偏慢。多次 warmup 和重复测量之后分支比较应当基于中位数而不是单次运行的值。这也是选择 hyperfine 而非手工time的原因——后者只有单次样本噪声没有机会被平均掉。分支对比的标准流程假设要比较当前提交与某个 feature 分支# 1) 切到分支 A构建 git checkout branch-A zig build -Demit-bench -DoptimizeReleaseFast # 2) 重命名产物避免下一个构建覆盖它名字可以起得更有意义如 -baseline mv zig-out/bin/ghostty-bench zig-out/bin/ghostty-bench-A # 3) 切到分支 B构建重命名 git checkout branch-B zig build -Demit-bench -DoptimizeReleaseFast mv zig-out/bin/ghostty-bench zig-out/bin/ghostty-bench-B # 4) 用 hyperfine 一次比较全部二进制 hyperfine --warmup 5 --runs 30 \ ./zig-out/bin/ghostty-bench-A terminal-stream --data /tmp/bench-utf8.raw \ ./zig-out/bin/ghostty-bench-B terminal-stream --data /tmp/bench-utf8.raw需要 N 个二进制参与比较时同理“replace branch1 with something better”hyperfine 支持任意多个命令并行比较。整个过程中必须保持所有基准输入与 CLI 标志一致——包括终端尺寸--terminal-rows/--terminal-cols因为尺寸既影响软换行路径也影响页的内存开销尺寸不一致会让对比失去意义。输入与环境的守则清单对比前逐条检查浓缩自 benchmark AGENTS.md 的运行守则数据来自同一个预生成文件而不是每次重新生成的“新随机”数据能固定种子的生成器都用固定种子语料放在仓库外如/tmp保持与仓库改动解耦两边 CLI 标志逐字一致终端行/列尺寸相同同一台机器上绝不并行跑多个基准——并发基准会抢占 CPU 与内存带宽互相干扰产生不可靠结果测量目标是ghostty-bench不是ghostty-gen通过--warmup与--runs让结论建立在多次样本的中位数上。这份指南在 herdr 仓库中的位置需要说明的是以上全部源码与守则都位于vendored 的 libghostty-vt 组件内vendor/libghostty-vt/该组件是 herdr 引入的第三方终端引擎herdr 通过 C 头文件vendor/libghostty-vt/include/ghostty/vt.h调用它并在此基础上维护了两处本地补丁见 libghostty-vt.patches.md——其一让新终端默认开启字素簇聚合以满足 herdr 直接渲染终端 cell 的需求其二暴露modifyOtherKeys模式查询起因正是由 herdr 侧改动暴露的性能回归。也就是说benchmark 目录这套 gen/bench 工具是在 herdr 中评估终端解析、压缩、渲染等热路径改动时值得复用的本地测量设施而本文的“先生成→再测量→hyperfine 对比”流程正是这类改动合入前应走的验证闭环。【免费下载链接】herdrthe runtime your coding agents live on项目地址: https://gitcode.com/GitHub_Trending/her/herdr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表