[控场AI]
· 11 分钟阅读· 5,876 字

用 hyperfine 测四款编程 Agent CLI 的启动耗时

用 hyperfine 测四款编程 Agent CLI 的启动耗时

用 hyperfine 逐层测量四款编程 Agent CLI 的启动开销,定位首 token 延迟来源。

文章拆解了编程 Agent 命令行工具在输出首个 token 之前的四层开销:进程启动、配置与记忆文件加载、MCP 服务器握手、模型调用。作者提出一套基于 hyperfine 2.0 的可复现测量方法,对 Claude Code、Codex、GitHub Copilot CLI 和 OpenCode 进行三轮基准测试:第一轮用 --version 测纯启动地板值,第二轮测从单提示词到完整回答的耗时,第三轮加入 MCP 配置、AGENTS.md 和挂起服务器做压力测试,并用精简模式(如 --bare、--ignore-user-config)做对照以剥离本地开销。文章强调所有文档中的超时数字(30 秒、1000 毫秒、5000 毫秒)只是坏服务器的上限而非实测值,真正的基准必须由开发者在自己机器上产出。最后将测量结果换算为每日任务的时间成本,指出每个新 worktree 都会重新支付启动与 MCP 冷启动开销。

为什么你的编程 Agent 总是"慢半拍"

你敲下 claude -p hello,然后盯着终端。三秒?五秒?半分钟?这个等待时间并非玄学,而是由进程启动、配置加载、MCP 服务器握手和模型调用四层叠加而成。问题在于,大多数开发者只知道"它有点慢",却从没量过每一层到底吃掉多少时间。

本文拆解一套可复现的测量方法:用 hyperfine 对 Claude Code、Codex、GitHub Copilot CLI 和 OpenCode 四款编程 Agent 的命令行接口做基准测试,逐层剥离启动开销。需要注意的是,原文作者明确表示自己并未实际跑过这些命令——文中给出的数字全部来自官方文档中的超时上限,真正有意义的测量数据只能由你自己的机器产出。

rss source: How Long Before Your Agent Says Anything? Time 4 Coding Agent CLIs With hyperfine

首 token 之前的四层开销

一个全新会话在提示词抵达模型之前,要完成四件事。

第一层:进程启动。 如果 Codex 是通过 npm 安装的,你 PATH 上的 codex 实际是一个 Node 脚本(codex.js),它会再去 spawn 原生二进制文件。这意味着它的启动时间里包含了 Node 运行时的冷启动成本。

第二层:配置与记忆文件加载。 Claude Code 的文档说明,一个普通的 claude -p 会像交互式会话一样发现 hooks、skills、自定义命令、子 Agent、插件、MCP 服务器、自动记忆和 CLAUDE.md;而 --bare 标志会跳过全部这些内容以"减少启动时间"。Codex 则会在启动时构建一条指令链,从 AGENTS.md 文件逐级向上读取,默认上限 32 KiB。

第三层:MCP 服务器启动。 这是差异最大的一层。各 CLI 等待慢速 MCP 服务器的耐心完全不同:Claude Code 在 --mcp-config 模式下会等到待连接的服务器全部连上,上限是 MCP_TIMEOUT 的 30 秒;Codex 对可选服务器只给 mcp_optional_startup_grace_ms 的 1000 毫秒,必需服务器则用 startup_timeout_sec 的 10 秒;OpenCode 给服务器 5000 毫秒来交付工具列表;Copilot CLI 的相关页面里没有写明具体数值。

第四层:模型调用。 网络、排队、读取整个前缀、写出答案。这一层的耗时取决于你的网络状况和模型服务端的负载,与 CLI 本身关系不大。

MCP(Model Context Protocol) 是由 Anthropic 提出并开源的一种标准协议,用于让大语言模型应用以统一方式连接外部工具和数据源。在编程 Agent 的语境里,MCP 服务器本质上是一个独立进程,通过 JSON-RPC 与 CLI 通信,启动后向客户端宣告自己提供哪些工具(即“工具列表”)。这意味着每次冷启动一个 MCP 服务器,CLI 不仅要等待该进程完成初始化,还要等它返回工具定义,并将这些定义序列化进发送给模型的提示词前缀——前缀越长,模型的预填充阶段就越慢。这也是为什么文章将 MCP 握手单列为四层开销中差异最大的一层:服务器本身的启动时间、工具发现时间以及前缀膨胀三者叠加,会显著拉长首 token 延迟。

搭建测试环境:hyperfine 与空仓库

安装 hyperfine 只需一行:brew install hyperfine、apt install hyperfine 或 cargo install --locked hyperfine。

hyperfine 2.0.0 有一个对本次测量很关键的变化:默认直接运行被基准测试的命令,不经过 shell。这正是你想要的——你要计时的是 Agent,不是 sh。如果你还在 1.x 版本,需要在每个 hyperfine 调用里加上 -N 才能获得相同行为。2.0 还新增了 --env 标志来传递环境变量,因为不再有 shell 去解析 FOO=bar cmd 这种写法。

准备一个空的 git 仓库作为测试目录,然后循环记录四个 CLI 的路径和版本号。Codex 在非 git 仓库中会拒绝运行(除非传 --skip-git-repo-check),所以 git init 是必要的。把版本号记进笔记,因为下个月的 release 就会改变这些数字。

MCP 测试服务器建议全局安装一次,避免计时结果里混入 npx 解析包的时间:npm install -g @modelcontextprotocol/server-everything。

在跑任何基准之前,还有一个习惯:先手动跑一遍每个提示词命令。一个停在登录界面或者提前报错退出的 CLI,在表格里看起来会非常"快"。

hyperfine 是 Rust 编写的命令行基准测试工具,专门用于测量单条命令的墙钟耗时。它的核心机制是:先执行若干次预热(warmup)以排除文件系统缓存冷启动的干扰,然后进行多轮正式测量,最终报告均值、标准差、最小值、最大值以及离群值检测结果。与简单的 time 命令相比,hyperfine 能自动处理多次运行的统计、支持运行前清理命令(--prepare)、并可将结果导出为 JSON 或 Markdown。文中强调的 2.0 版本变化——默认不经过 shell——至关重要:经由 shell 启动会额外引入 shell 解析和 fork 开销,对于毫秒级的启动测量而言是显著噪声。--env 标志则解决了不经过 shell 时无法用 FOO=bar cmd 语法传递环境变量的问题。

三轮测量:从进程启动到挂起的 MCP

第一轮:进程启动地板值

用 --version 命令测量四个 CLI 的纯启动开销,--warmup 3 --runs 30。这是你的地板值:二进制加载、打印一个字符串、退出。hyperfine 2.0 默认会同时报告峰值内存和实际耗时,一条命令拿到两个数据。

地板值(floor value) 在性能测量中指的是在剥离所有业务逻辑后,系统仍然必须支付的最小固定开销。对 CLI 而言,--version 命令几乎不触发任何配置加载、网络请求或模型调用,只完成二进制加载、打印版本字符串并退出,因此它测出的时间就是该 CLI 的启动地板。之所以要先测地板值,是因为后续轮次的耗时都是“地板 + 增量”的叠加;只有知道地板有多高,才能判断第二轮、第三轮中多出来的时间究竟来自配置发现、MCP 握手还是模型响应。此外,预热运行(--warmup 3)的作用是让操作系统把二进制和共享库载入页缓存,避免首次运行的磁盘 I/O 污染统计结果。

第二轮:从一个词到完整回答

'claude -p hello'、'codex exec hello'、'copilot -p hello'、'opencode run hello',--runs 10 意味着 44 次真实模型调用,每一次都会计入你的套餐或 API 账单。如果在意成本,降到 --runs 5。

这一轮测的是"CLI + 模型"的组合,因为每个 CLI 都用自己的默认模型和 effort 设置。如果想单独比较 CLI,需要用各自的模型标志把它们统一到相近的模型上。

第二轮减去第一轮,得到的是配置发现、已配置的 MCP 服务器、网络和模型的总和。想单独剥离本地部分,就要跑一个精简版本做对照:

CLI精简运行方式跳过的内容
Claude Codeclaude --bare -p hellohooks、skills、插件、MCP、自动记忆、CLAUDE.md;需要 ANTHROPIC_API_KEY
Codexcodex exec --ignore-user-config hello$CODEX_HOME/config.toml 及其中的 MCP 服务器
Copilot CLIcopilot -p hello --no-custom-instructions --disable-builtin-mcpsAGENTS.md 等文件和内置 GitHub MCP
OpenCode对 opencode serve 用 --attach <url>每次运行的冷启动

需要注意,bare 模式用 API key 而非订阅登录,所以 Claude 那一行只是近似值。OpenCode 的文档本身就建议走 server 路线,"以避免每次运行时的 MCP 服务器冷启动时间"。

Claude Code 还会在 JSON 结果里报告自己的计时,可以用 jq 提取 duration_ms、duration_api_ms、ttft_ms、ttft_stream_ms 和 num_turns。Agent SDK 的 TypeScript 参考文档把 ttft_ms 定义为首个完整助手消息到达的时间,且只在成功运行时存在。要检查 num_turns——如果 Agent 为了回答"hello"还跑了一次工具调用,那你计时的不止一次模型调用。Codex 的 --json 事件只带 token 用量、没有计时字段,所以对 Codex 来说 hyperfine 就是唯一的钟表。

第三轮:一个 MCP 服务器、一个 AGENTS.md、一个挂起的服务器

为三种格式各准备一个小配置文件:Claude Code 的 mcp.json、Copilot 的 copilot-mcp.json("type": "local" 加 "tools": ["*"])、OpenCode 的配置("type": "local",command 用数组)。然后带上服务器重新计时。

Copilot 的 --additional-mcp-config 接受 @ 前缀的文件路径,只在本次会话生效。OpenCode 会把 OPENCODE_CONFIG 指定的配置合并进全局和项目配置之间。Codex 则需要用 codex mcp add everything -- mcp-server-everything 写入配置,测完再 codex mcp remove。

第二轮和第三轮之间的差值,就是一个服务器启动加上它的工具定义搭车进入提示词的成本。

接着把一个真实的 AGENTS.md 从工作仓库复制到测试目录,重跑第二轮。四个 CLI 都会读它,但触发条件不同:Claude Code 在目录及上层没有 CLAUDE.md 或 CLAUDE.local.md 时才读;Codex 从 git 根目录向下读;OpenCode 从当前目录向上走;Copilot CLI 除非传了 --no-custom-instructions。文件越长,模型回答前要读的文本越多。测完记得删掉,否则会污染下一轮。

最后一个实验最有戏剧性:把一个 MCP 配置指向 sleep 60,制造一个永远不回答的服务器。Claude Code 大约 30 秒后应该继续前进,Codex 和 OpenCode 会按各自的超时上限行事。如果你的数字和文档不符,或者某次运行真的等满了 60 秒,那你就找到了一个值得给该 CLI 提 issue 的问题。

把测量结果换算成你每天的时间成本

原文作者同时是 Hermes IDE 的开发者,这一节需要带着这个背景来看。在 Hermes 中,⌘N 会为每个任务创建独立的 hermes/<name> 分支和 worktree,任务作为 Agent 的第一个提示词。每个 Agent 都在真实终端里运行自己的界面,"和它在别处运行的样子完全一样"。所以每个任务都是一次全新的厂商 CLI 启动,都要支付你刚刚测出来的启动成本。

界面里"Hermes will run"的预览展示了实际要执行的命令,把它直接放进 hyperfine 就行。然后做算术:第三轮减去精简版,乘以你每天启动的任务数。如果你的仓库提交了 .mcp.json 或 opencode.json,每个新 worktree 都有一份副本,因为它是被跟踪的文件,于是每个任务都会重新启动那个服务器。

Hermes 运行的就是你自己会敲的命令,所以这些数字不会缩小。它的价值在别处:在 macOS 和 Linux 上,Agent 在 Hermes 退出、更新或崩溃时继续工作,重新打开后可以接回原处,关闭应用不会让运行中的 Agent 重新启动。

结论:测量属于你的那台机器

这篇文章给出的所有具体数字——30 秒、1000 毫秒、5000 毫秒——都是文档里的超时上限,针对的是坏掉的服务器。一个健康的会话要快得多,而快多少只有你自己的环境能给出答案。

第三轮之前加入的一切,都是你主动选择的上下文:一个 MCP 服务器的工具列表、一个 AGENTS.md、一个记忆文件。判断哪些内容该放进前缀、哪些可以等到 Agent 主动索取时再给,是优化启动体验的核心。

原文作者在文末邀请读者在评论区贴出自己的四行数据,附上版本号和操作系统。这个邀请值得响应——同一款 CLI 在不同机器上的差异,可能比不同 CLI 之间的差异还要大。

#编程 Agent CLI#hyperfine 基准测试#Claude Code 启动时间#MCP 服务器超时#Codex CLI#OpenCode#Agent 性能优化
分享:

相关推荐