Bug Report: Qoder 聊天输入框打字导致 IDE 冻结 65 秒

Bug Report: Qoder 聊天输入框打字导致 IDE 冻结 65 秒

环境信息

项目值
IDEAndroid Studio Rabbit 2 \2026.2.2 Patch 1 (Build AI-262.10968.63.2622.16840690)
OSLinux 6.8.0-138-generic (Ubuntu 22.04, Wayland)
Qoder CN 版本2026.1105.86773116 (com.alibabacloud.intellij.cosy)
JDKJava 25.0.4 (JBR bundled)
CPU12 核
JVM Heap总计 8624MB,冻结时已用 3623MB(内存充足,非内存问题)

问题描述

在 Qoder 聊天面板的输入框中打字时,IDE 完全冻结无响应,持续约 65 秒。
冻结发生在 Wayland 输入法协议(zwp_text_input_v3)请求光标矩形位置时,触发了 ChatStyledEditorKit$CustomParagraphView 对整个文档的全量重新布局计算,该计算在 EDT(AWT-EventQueue-0)线程上同步执行,导致 UI 完全卡死。

复现条件

  1. 在 Qoder 聊天面板中有一段较长的对话(包含多轮对话、代码块、工具调用结果等)
  2. 在聊天输入框中打字(特别是使用中文输入法时)
  3. Wayland 输入法协议每次按键都会请求精确的光标矩形坐标
  4. 这触发 modelToView() → 整个文档重新布局 → EDT 阻塞数十秒

冻结诊断数据

冻结事件

  • 冻结时间: 2026-11-11 16:31:45
  • 冻结时长: 65 秒(65343ms)
  • 死锁: 无
  • 低内存事件: 0
  • 冻结时 CPU 占用: AWT-EventQueue-0 线程独占 92.46%
  • 冻结报告路径: threadDumps-freeze-20261111-163145-AI-262.10968.63.2622.16840690/

EDT 线程热点堆栈(Hot Path Stack Trace)

"AWT-EventQueue-0" tid=0x0 runnable
     java.lang.Thread.State: RUNNABLE
     Frozen for 65secs
    at java.desktop@25.0.4/javax.swing.text.BoxView.updateLayoutArray(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.BoxView.replace(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.View.append(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.FlowView$FlowStrategy.layout(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.FlowView.layout(Unknown Source)
    at com.alibabacloud.intellij.qoder.ui.chat.component.textpane.ChatStyledEditorKit$CustomParagraphView.layout(ChatStyledEditorKit.kt:87)
    at java.desktop@25.0.4/javax.swing.text.BoxView.setSize(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.BoxView.updateChildSizes(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.BoxView.setSpanOnAxis(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.BoxView.layout(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.BoxView.setSize(Unknown Source)
    at java.desktop@25.0.4/javax.swing.plaf.basic.BasicTextUI$RootView.setSize(Unknown Source)
    at java.desktop@25.0.4/javax.swing.plaf.basic.BasicTextUI.modelToView(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.JTextComponent.modelToView(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.JTextComponent$InputMethodRequestsHandler.getTextLocation(Unknown Source)
    at java.desktop@25.0.4/sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3.awtGetCaretOf(Unknown Source)
    at java.desktop@25.0.4/sun.awt.wl.im.text_input_unstable_v3.WLInputMethodZwpTextInputV3.wlUpdateCursorRectangle(Unknown Source)
    at java.desktop@25.0.4/sun.awt.wl.im.text_input_unstable_v3.ClientComponentCaretPositionTracker.caretUpdate(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.JTextComponent.fireCaretUpdate(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.DefaultCaret.changeCaretPosition(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.DefaultCaret.setDot(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.JTextComponent.setInputMethodCaretPosition(Unknown Source)
    at java.desktop@25.0.4/javax.swing.text.JTextComponent.processInputMethodEvent(Unknown Source)
    ... (EDT event dispatch chain)

CPU 采样 Profile(关键耗时分解)

AWT-EventQueue-0, TID: 42 [56300ms]
  └─ ChatStyledEditorKit$CustomParagraphView.layout(ChatStyledEditorKit.kt:87) [56300ms]
     ├─ View.append() [42100ms]                    ← 追加子视图到布局数组 (O(n))
     │  └─ BoxView.replace() + updateLayoutArray() [25000ms]
     └─ FlowView$FlowStrategy.layoutRow() [14000ms]
        └─ ChatStyledEditorKit$CustomLabelView.getBreakWeight(ChatStyledEditorKit.kt:169) [6800ms]
           └─ GlyphPainter1.getBoundedPosition() [6500ms]
              └─ GlyphPainter1.sync() [3800ms]      ← 字体度量计算
                 └─ FontDesignMetrics.getMetrics() [多次, 总计 ~3000ms]

根本原因分析

瓶颈在 ChatStyledEditorKit$CustomParagraphView.layout()(ChatStyledEditorKit.kt:87)

  1. 当聊天记录变长后,JTextPane 文档中包含大量子 View(代码块、工具调用卡片、Markdown 渲染等)
  2. Wayland 输入法协议(zwp_text_input_v3)在每次按键时都调用 modelToView() 获取光标矩形
  3. modelToView() 触发 BoxView.layout() → CustomParagraphView.layout() 对整个文档做全量布局
  4. View.append() 操作耗时 42.1 秒,是 O(n) 的数组扩展操作
  5. CustomLabelView.getBreakWeight() 中的字体度量计算又额外消耗了 6.8 秒
  6. 以上全部在 EDT 线程同步执行,导致 UI 完全冻结

建议修复方向

  1. 虚拟化/懒布局: CustomParagraphView 应只布局可见区域的子 View,而非整个文档
  2. modelToView 缓存: 对 modelToView 的结果做增量缓存,避免每次按键都全量重排
  3. 异步化布局: 将 layout() 中的 View.append() 和 BoxView.replace() 移到后台线程预计算
  4. 限制布局数组的频繁扩容: updateLayoutArray() 中的数组拷贝操作可以优化为批量操作或使用 ArrayList

完整冻结报告文件位置

~/.cache/Google/AndroidStudio2026.2.2/log/threadDumps-freeze-20261111-163145-AI-262.10968.63.2622.16840690/
├── diagnosticReport-hotPathStackTrace.txt
├── diagnosticReport-profileDiagnostics.txt
├── diagnosticReport-cpuUseDiagnostics.txt
├── diagnosticReport-memoryUseDiagnostics.txt
├── diagnosticReport-lockDiagnostics.txt
├── diagnosticReport-actionsDiagnostics.txt
├── diagnosticReport-plugin.name.txt
├── threadDump-20261111-163146.txt  (共 8 个 thread dump 文件)
└── ...

展开
收起
风雨雷电 2026-11-11 16:51:51 22 分享 版权
0 条回答
写回答
取消 提交回答

Qoder CN 是 Qoder CN 系列中面向软件开发场景的核心子产品(原“通义灵码”),提供 IDE、JetBrains 插件、Visual Studio Code 插件等多种使用形态。Qoder CN 持续提供代码智能生成、智能问答、多文件修改、编程智能体等能力,并在模型选择、专家协作、任务规划等方向全面升级,为开发者带来高效、流畅的编码体验。同时面向企业客户提供企业标准版、企业专属版,具备企业级场景自定义、私域知识增强等能力,助力企业研发智能化升级。

热门讨论

热门文章

还有其他疑问?
咨询AI助理