现状是一个有意的取舍,但依据只有一半
2026-09-06 那一轮只把「时长不可控」的命令挪出了主线程,留下的这些还是同步的
(也就是跑在主线程上):
git_status、git_diff、git_log_entries、git_commit_files、
git_commit_diff、git_branches、git_worktrees、git_stage、
git_unstage、git_outgoing、git_root、read_text、list_dir、
probe_path、file_stamp、detect_encoding
依据是这组实测(M 系列 Mac,1.1GB / 3518 文件的仓库,热缓存):
| 命令 |
耗时 |
git status --porcelain=v2 -uall |
0.04s |
rg --files |
0.02s |
rg 全文搜一个高频词 |
0.07s |
git log -300 |
0.02s |
40ms 是两帧半,不值得为它换来「命令之间不再串行」这个新变量。
没量过的三种情况
- 冷缓存。 刚开机 / 刚 checkout 完的第一次
git status。这是最常见的
「打开应用第一眼」的场景,而它恰恰是最慢的一次。
- 网络卷 / 外部盘上的仓库。
stat 一次几毫秒的话,3518 个文件就是十几秒。
- 真正的大仓库。 3518 个文件不算大。十万文件的 monorepo 上
git status 是秒级的,那时主线程就真的堵住了。
建议怎么做
先量,再决定,别先改。量法:
- 冷缓存:
sudo purge 之后跑一次(会清掉整个系统的磁盘缓存,代价是之后
一切都慢一会儿)
- 大仓库:找一个十万文件级别的仓库,或者
git clone --depth 1 一个大的
- 网络卷:挂一个 SMB 共享,把仓库放上去
如果冷缓存下 git_status 超过 100ms,那 git_status 就该跟着挪走 ——
它是刷新循环里最高频的一条。
一条不该动的
log_*(日志引擎的数据面)和 pty_write 有意留在主线程上:它们是常数
时间的内存操作(首屏 50 行实测 0.008ms),挪到 runtime 上只会多一次调度延迟。
这条已经写进 .claude/rules/rust.md,别在优化时顺手改掉。
现状是一个有意的取舍,但依据只有一半
2026-09-06 那一轮只把「时长不可控」的命令挪出了主线程,留下的这些还是同步的
(也就是跑在主线程上):
git_status、git_diff、git_log_entries、git_commit_files、git_commit_diff、git_branches、git_worktrees、git_stage、git_unstage、git_outgoing、git_root、read_text、list_dir、probe_path、file_stamp、detect_encoding依据是这组实测(M 系列 Mac,1.1GB / 3518 文件的仓库,热缓存):
git status --porcelain=v2 -uallrg --filesrg全文搜一个高频词git log -30040ms 是两帧半,不值得为它换来「命令之间不再串行」这个新变量。
没量过的三种情况
git status。这是最常见的「打开应用第一眼」的场景,而它恰恰是最慢的一次。
stat一次几毫秒的话,3518 个文件就是十几秒。git status是秒级的,那时主线程就真的堵住了。建议怎么做
先量,再决定,别先改。量法:
sudo purge之后跑一次(会清掉整个系统的磁盘缓存,代价是之后一切都慢一会儿)
git clone --depth 1一个大的如果冷缓存下
git_status超过 100ms,那git_status就该跟着挪走 ——它是刷新循环里最高频的一条。
一条不该动的
log_*(日志引擎的数据面)和pty_write有意留在主线程上:它们是常数时间的内存操作(首屏 50 行实测 0.008ms),挪到 runtime 上只会多一次调度延迟。
这条已经写进
.claude/rules/rust.md,别在优化时顺手改掉。