关于OpenCode CLI上下翻页的卡顿问题

2026-04-13 12:221阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐
问题描述:

最近一直在用 OpenCode CLI 作为日常编码助手,整体体验还不错,但有个问题困扰我很
久了——对话稍微长一点,上下翻页就卡得要命。

我的配置是 9950X3D + 64GB DDR5
内存,按理说不应该卡成这样。所以花了点时间研究了一下,把发现分享给大家。


问题现象

  • 新建会话时滚动很流畅
  • 对话持续一段时间后(比如来回讨论十几轮),滚动开始明显掉帧
  • 对话越长越卡,最后基本没法用鼠标滚轮翻页了
  • 此时 CPU 占用会飙到 100%+

我用的是 Termius SSH
连服务器,一开始以为是网络问题或者终端模拟器的锅,后来发现换什么终端都一样卡。


排查过程

先去 GitHub 上搜了一圈,发现这是个已知问题,相关 issue 一大堆:

  • High CPU usage (100%+) during LLM streaming in long sessions due to O(n) text buffer rendering · Issue #6172 · anomalyco/opencode · GitHub — 长会话 CPU
    100%+,有人做了详细的性能分析
  • Add configurable scrollback/message limit to reduce TUI lag · Issue #9930 · anomalyco/opencode · GitHub — 请求加个消息数量限制
  • Long prompt history stalls the app, long load time · Issue #3746 · anomalyco/opencode · GitHub — 长对话历史导致卡顿
  • Text rendering is VERY slow (and CPU usage is really high even when idle) · Issue #811 · anomalyco/opencode · GitHub — 文本渲染巨慢 + 空闲时 CPU
    也高

看了 #6172 那个 issue,里面有人用 macOS 的 sample 命令抓了 CPU
热点,定位到了问题所在。


根本原因

OpenCode 用的是 OpenTUI(一个 Zig 写的终端 UI
框架)来渲染界面。问题出在它的文本缓冲区渲染逻辑:

每次滚动 → 重新计算全部内容的虚拟行布局 → O(n) 复杂度

也就是说,你对话历史有 1000 行,滚动一下就要遍历 1000 行重新算换行;有 10000
行就遍历 10000 行。对话越长,n 越大,越卡。

从 CPU 采样来看,热点调用栈是这样的:

textBufferViewMeasureForDimensions
→ calculateVirtualLinesGeneric
→ rope.Rope.walkNode (递归遍历)
→ segment_callback
→ ArrayListAlignedUnmanaged.append
→ ArenaAllocator.alloc
→ PageAllocator.alloc
→ mmap (系统调用)

每次滚动都在疯狂 mmap 分配内存,怪不得卡。


正确的解决思路

其实这类问题在 GUI/TUI
领域是有成熟方案的,核心思路是把布局计算和视图渲染解耦。

滚动本质上只是视口(Viewport)的位移,不应该触发文本重新排版。

策略一:布局缓存

  • 只在窗口大小改变或有新内容时才重算布局
  • 维护一个持久化的 VirtualLine 缓存列表
  • 滚动时只改 offset,直接从缓存里取数据

优化前:scroll → layout() → draw()
优化后:scroll → offset += dy → draw_from_cache(offset)

策略二:视口裁剪(虚拟滚动)

就算有了缓存,如果 draw 还在遍历所有行判断"在不在屏幕里",依然会慢。

正确做法是只处理可见区域:

const start = scroll_y;
const end = @min(scroll_y + viewport_height, virtual_lines.len);

// 只遍历切片
for (virtual_lines[start..end]) |line| {
render_line(line);
}

策略三:增量布局(应对流式输出)

AI 在流式生成内容时,不要重算整个历史,只算新追加的部分。


优化前后对比
动作————————优化前————————————优化后
滚动触发————遍历全部文本,计算换行————直接读缓存索引
数据量——————处理 N 行(可能上万)————只取屏幕能显示的 ~50 行
复杂度——————————O(N)————————O(H),H 是屏幕高度


上游进展

好消息是开发者知道这个问题,已经有相关 PR 了:

  • perf(tui/chat): virtualize message rendering to remove O(n) reflows during streaming by paulbettner · Pull Request #3346 · anomalyco/opencode · GitHub — 虚拟化消息渲染,移除 O(n)
    reflow
  • perf(tui): Eliminate O(n) scans from render hot path for smooth animations by paulbettner · Pull Request #2867 · anomalyco/opencode · GitHub — 虚拟视口渲染,O(1) 滚动

坏消息是目前还没合入主分支,不知道什么时候能发版。


目前的临时缓解方案

在等上游修复的这段时间,能做的有限:

  1. 降低滚动速度 — 在 opencode.json 里加:
    {
    “tui”: {
    “scroll_speed”: 1
    }
    }
  2. 勤开新会话 — 对话别太长,感觉开始卡了就新建一个,这是目前最有效的规避方式
  3. 用 GPU 加速的终端 — 如果是本地用,Kitty / Alacritty / WezTerm 比 VSCode
    内置终端或 Electron 类终端(如 Termius)渲染效率高
  4. 去 GitHub 给相关 issue 点个赞 — 让开发者知道这个问题影响了很多人

最后

写这篇主要是想整理一下思路,也给遇到同样问题的朋友一个参考。OpenCode
整体还是很好用的,就是这个性能问题确实影响体验。

如果有大佬愿意去贡献代码把那几个 PR 推进一下就更好了

有问题欢迎讨论

网友解答:
--【壹】--:

我一直以为是对win不太友好 我在win上用 时间稍长就会这种情况

但是再mac上 没有明显的卡顿或者闪动 偶尔有一会

原来是这个问题 感谢大佬科普了


--【贰】--:

今天试一下,好卡,来 L 站果然搜到有人吐槽。claude 和 codex 在 autodl 好难用,配置代理麻烦。


--【叁】--:

不用 OpenCode


--【肆】--:

为啥技术贴没人回复?


--【伍】--:

不用是对的,一天崩溃n次,烦的不行了,issue多到爆

问题描述:

最近一直在用 OpenCode CLI 作为日常编码助手,整体体验还不错,但有个问题困扰我很
久了——对话稍微长一点,上下翻页就卡得要命。

我的配置是 9950X3D + 64GB DDR5
内存,按理说不应该卡成这样。所以花了点时间研究了一下,把发现分享给大家。


问题现象

  • 新建会话时滚动很流畅
  • 对话持续一段时间后(比如来回讨论十几轮),滚动开始明显掉帧
  • 对话越长越卡,最后基本没法用鼠标滚轮翻页了
  • 此时 CPU 占用会飙到 100%+

我用的是 Termius SSH
连服务器,一开始以为是网络问题或者终端模拟器的锅,后来发现换什么终端都一样卡。


排查过程

先去 GitHub 上搜了一圈,发现这是个已知问题,相关 issue 一大堆:

  • High CPU usage (100%+) during LLM streaming in long sessions due to O(n) text buffer rendering · Issue #6172 · anomalyco/opencode · GitHub — 长会话 CPU
    100%+,有人做了详细的性能分析
  • Add configurable scrollback/message limit to reduce TUI lag · Issue #9930 · anomalyco/opencode · GitHub — 请求加个消息数量限制
  • Long prompt history stalls the app, long load time · Issue #3746 · anomalyco/opencode · GitHub — 长对话历史导致卡顿
  • Text rendering is VERY slow (and CPU usage is really high even when idle) · Issue #811 · anomalyco/opencode · GitHub — 文本渲染巨慢 + 空闲时 CPU
    也高

看了 #6172 那个 issue,里面有人用 macOS 的 sample 命令抓了 CPU
热点,定位到了问题所在。


根本原因

OpenCode 用的是 OpenTUI(一个 Zig 写的终端 UI
框架)来渲染界面。问题出在它的文本缓冲区渲染逻辑:

每次滚动 → 重新计算全部内容的虚拟行布局 → O(n) 复杂度

也就是说,你对话历史有 1000 行,滚动一下就要遍历 1000 行重新算换行;有 10000
行就遍历 10000 行。对话越长,n 越大,越卡。

从 CPU 采样来看,热点调用栈是这样的:

textBufferViewMeasureForDimensions
→ calculateVirtualLinesGeneric
→ rope.Rope.walkNode (递归遍历)
→ segment_callback
→ ArrayListAlignedUnmanaged.append
→ ArenaAllocator.alloc
→ PageAllocator.alloc
→ mmap (系统调用)

每次滚动都在疯狂 mmap 分配内存,怪不得卡。


正确的解决思路

其实这类问题在 GUI/TUI
领域是有成熟方案的,核心思路是把布局计算和视图渲染解耦。

滚动本质上只是视口(Viewport)的位移,不应该触发文本重新排版。

策略一:布局缓存

  • 只在窗口大小改变或有新内容时才重算布局
  • 维护一个持久化的 VirtualLine 缓存列表
  • 滚动时只改 offset,直接从缓存里取数据

优化前:scroll → layout() → draw()
优化后:scroll → offset += dy → draw_from_cache(offset)

策略二:视口裁剪(虚拟滚动)

就算有了缓存,如果 draw 还在遍历所有行判断"在不在屏幕里",依然会慢。

正确做法是只处理可见区域:

const start = scroll_y;
const end = @min(scroll_y + viewport_height, virtual_lines.len);

// 只遍历切片
for (virtual_lines[start..end]) |line| {
render_line(line);
}

策略三:增量布局(应对流式输出)

AI 在流式生成内容时,不要重算整个历史,只算新追加的部分。


优化前后对比
动作————————优化前————————————优化后
滚动触发————遍历全部文本,计算换行————直接读缓存索引
数据量——————处理 N 行(可能上万)————只取屏幕能显示的 ~50 行
复杂度——————————O(N)————————O(H),H 是屏幕高度


上游进展

好消息是开发者知道这个问题,已经有相关 PR 了:

  • perf(tui/chat): virtualize message rendering to remove O(n) reflows during streaming by paulbettner · Pull Request #3346 · anomalyco/opencode · GitHub — 虚拟化消息渲染,移除 O(n)
    reflow
  • perf(tui): Eliminate O(n) scans from render hot path for smooth animations by paulbettner · Pull Request #2867 · anomalyco/opencode · GitHub — 虚拟视口渲染,O(1) 滚动

坏消息是目前还没合入主分支,不知道什么时候能发版。


目前的临时缓解方案

在等上游修复的这段时间,能做的有限:

  1. 降低滚动速度 — 在 opencode.json 里加:
    {
    “tui”: {
    “scroll_speed”: 1
    }
    }
  2. 勤开新会话 — 对话别太长,感觉开始卡了就新建一个,这是目前最有效的规避方式
  3. 用 GPU 加速的终端 — 如果是本地用,Kitty / Alacritty / WezTerm 比 VSCode
    内置终端或 Electron 类终端(如 Termius)渲染效率高
  4. 去 GitHub 给相关 issue 点个赞 — 让开发者知道这个问题影响了很多人

最后

写这篇主要是想整理一下思路,也给遇到同样问题的朋友一个参考。OpenCode
整体还是很好用的,就是这个性能问题确实影响体验。

如果有大佬愿意去贡献代码把那几个 PR 推进一下就更好了

有问题欢迎讨论

网友解答:
--【壹】--:

我一直以为是对win不太友好 我在win上用 时间稍长就会这种情况

但是再mac上 没有明显的卡顿或者闪动 偶尔有一会

原来是这个问题 感谢大佬科普了


--【贰】--:

今天试一下,好卡,来 L 站果然搜到有人吐槽。claude 和 codex 在 autodl 好难用,配置代理麻烦。


--【叁】--:

不用 OpenCode


--【肆】--:

为啥技术贴没人回复?


--【伍】--:

不用是对的,一天崩溃n次,烦的不行了,issue多到爆