# 距离，不是时间：一次终端滚动排查

七轮排查都没有解释“不跟手”。直到我们开始比较，同一段手指位移究竟让画面走了多远。

杨永安 + Claude Code · 2026-11-05 · 原始记录: 2026-09-21

https://flydogai.com/bruce/blog/distance-not-time?lang=zh

<a id="the-feeling"></a>

## “不跟手”还不是一个诊断

最初的反馈是：在 Bruce 终端里滚动全屏 TUI，惯性滚动很流畅，手指频繁上下往复时却觉得沉。对照是熟悉的 IDE 终端。我们很快把问题理解成了响应慢，于是开始量延迟。

这篇整理自 2026 年 9 月的开发记录。文中的数值属于当时的设备、版本和测试场景，不是对所有终端或机器的性能承诺。真正值得留下的是，如何把一个准确的体感描述，变成可以区分原因的测量。

<a id="good-numbers"></a>

## 数字都不错，为什么手感仍然不对

我们依次检查写入、传输、程序回包、终端解析、渲染帧率和字形图集。确实找到了可以改进的地方：更短的合并窗口、更合适的调度方式，以及不让阻塞写入拖住其它工作的处理。但这些改动都没有解释那个稳定的“沉”。

另一个问题是测量对象。浏览器里的最小页面、刚启动而没有内容的 TUI，和用户正在操作的原生窗口，是不同的现场。我们给实际窗口补上了可请求求值、返回结果的开发调试通道，才看清一次手势到底走了哪条路径。

那次追踪发现，眼前滚动的是终端自己的回滚缓冲，事件根本没有经过我们一直优化的“把滚轮报告交给程序”那条路。先确认手势归谁处理，应该发生在优化之前。

<a id="travel"></a>

## 转折来自一个更朴素的对照

用户在另一款终端里做了同样的动作，给出更精确的描述：不是等得太久，是走得不够远。时间和距离终于被分开了。一个没有明显延迟的系统，也能因为位移增益不对而显得迟钝。

当时记录的一次三秒手势有 165 个事件，总位移约 1002px，平均每个事件约 6.1px。相关路径在把像素换算为行数时，对小于 50px 的事件额外乘了 0.3。触控板把手势切成许多小步，几乎每一步都被缩短。按当时约 15px 的行高估算，本该产生约 66 份报告，实际只有约 20 份。

影响的是交给全屏程序的滚轮报告，而不是所有滚动。两条路径混在一起测，延迟曲线再漂亮，也无法说明行程是否正确。

<a id="fix-the-path"></a>

## 修复必须落在对应的路径上

第一版补偿用错了地方：把本来正常的回滚缓冲也放大，反而产生过冲。后来才把判断收窄到三个条件：事件会送给程序、使用像素模式、原始位移落在会被缩短的范围内。下面只保留当时判断的核心。

这不是把灵敏度统一调大。大步进的鼠标事件没有经过相同的缩短，不能一起放大。我们也把相同总位移、不同事件分片方式的结果整理为回归用例，并在当时向上游提交了问题与修复建议；本地行为仍需要独立验证。

```typescript
const sensitivity = toProgram && pixelMode && Math.abs(deltaY) < 50
  ? configured / 0.3
  : configured;
```

<a id="takeaways"></a>

## 让下一次排查少绕一点路

这次排查留下的，不只是滚动补偿。能进入实际窗口的调试通道、会报告失败的测量脚本，以及对照同一手势的习惯，都能帮助后来的开发者和 Agent 避免把正确的数字用在错误的对象上。

- 先确认事件属于哪块表面、哪条处理路径。
- “跟手”同时涉及时间和位移，两个量都要检查。
- 记录设备、版本、内容和前台状态，让数字有明确出处。
- 把决定性的对照写成回归用例，避免只留下“感觉好了”。
