Skip to content

[Bug] 大的Java文件打开编辑器卡顿 #561

Closed

Description

@viquu

Platform / 平台

macOS

Area / 模块

Editor / 编辑器

Lithe version / Lithe 版本

0.4.3

Priority / 优先级

P0 / 立即处理:已严重影响使用体验,核心流程受阻或无法正常使用

OS and architecture / 操作系统与架构

macOS15.5, Apple Silicon

Environment / 环境信息

No response

Steps to reproduce / 复现步骤

  1. 打开一个java文件,文件大概有8000多行,编辑器就比较卡顿了, 看状态栏的只有2~7FPS

Expected behavior / 预期行为

  1. 正常编辑

Actual behavior / 实际行为

No response

Logs or diagnostic output / 日志或诊断输出

Screenshots or recordings / 截图或录屏

No response

Checklist / 提交前检查

  • I searched existing issues for duplicates. / 我已搜索现有 Issue,确认没有重复报告。
  • I removed secrets and personal data from the report. / 我已从报告中移除敏感信息和个人数据。

Activity

  1. added
    bugSomething isn't working
    on Sep 8, 2026
  2. added
    P0立即处理:已严重影响使用体验,核心流程受阻或无法正常使用
    on Sep 8, 2026
  3. xiaoyumuxi commented on Sep 8, 2026

    @xiaoyumuxi
    Collaborator

    @1lck 这个不是热加载了么,是你没有修改还是啥问题呀,如果改了应该不至于出现这种情况来着
    @viquu 你这个文件还是这个项目的问题,项目的数据可以说一下么,因为最近又LSP堆内存导致的项目的问题有可能有影响

  4. viquu commented on Sep 8, 2026

    @viquu
    Author

    项目概况

    • 语言:Java 8
    • 构建:Maven 多模块(约 9 个 pom)
    • Java 源文件:约 3564 个
    • 磁盘占用:约 3.3 GB(含 target 编译产物约 1.5 GB;源码本身约 35 MB)
    • 大文件较多:>=1000 行约 181 个,>=5000 行约 14 个,>=8000 行约 5 个
      问题文件(某个超大 Service 实现类)
    • 模块:xxx-service/xxx-core
    • 行数:8329 行(项目中排名第 3,前两名是更大的 PO/DTO 类)
    • 文件大小:~447 KB
    • import:164 个
    • 方法数:约 142 个
    • 依赖注入:约 69 处 @Autowired/@Resource
    • 性质:业务 Service 实现类(God Class),不是简单数据类
      现象对比
    • 同项目内普通小文件(几百行):打开时短暂卡顿,很快恢复
    • 该超大文件:打开后长时间卡住,鼠标出现彩虹圈,需要等很久
  5. xiaoyumuxi commented on Sep 9, 2026

    @xiaoyumuxi
    Collaborator

    项目概况

    • 语言:Java 8
    • 构建:Maven 多模块(约 9 个 pom)
    • Java 源文件:约 3564 个
    • 磁盘占用:约 3.3 GB(含 target 编译产物约 1.5 GB;源码本身约 35 MB)
    • 大文件较多:>=1000 行约 181 个,>=5000 行约 14 个,>=8000 行约 5 个
      问题文件(某个超大 Service 实现类)
    • 模块:xxx-service/xxx-core
    • 行数:8329 行(项目中排名第 3,前两名是更大的 PO/DTO 类)
    • 文件大小:~447 KB
    • import:164 个
    • 方法数:约 142 个
    • 依赖注入:约 69 处 @Autowired/@Resource
    • 性质:业务 Service 实现类(God Class),不是简单数据类
      现象对比
    • 同项目内普通小文件(几百行):打开时短暂卡顿,很快恢复
    • 该超大文件:打开后长时间卡住,鼠标出现彩虹圈,需要等很久

    可以试试单独打开一个文件夹,文件夹里面只有一些日志文件,然后试试浏览那个日志文件夹看看卡不卡,如果不卡那就是LSP的问题了

  6. viquu commented on Sep 9, 2026

    @viquu
    Author

    我分别试了2个工程:

    • 工程1: 只有一个8000多行的java文件,打开Java文件还是卡顿
    • 工程2: 一个10000多行的log文件,不卡
  7. xiaoyumuxi commented on Sep 9, 2026

    @xiaoyumuxi
    Collaborator

    我分别试了2个工程:

    • 工程1: 只有一个8000多行的java文件,打开Java文件还是卡顿
    • 工程2: 一个10000多行的log文件,不卡

    非常感觉,我觉得应该是LSP的问题或者是语法渲染逻辑的问题,应该不是编辑器的问题的,我们会考虑一下大型文件和项目场景下如何优化LSP的

  8. self-assigned this
    on Sep 11, 2026
  9. xiaoyumuxi commented on Sep 11, 2026

    @xiaoyumuxi
    Collaborator

    补充这个问题最初的复现报告、完整产品的单变量分析及配套测量数据。

    结论:普通语法染色确实有视口缓存,但 Java 结构结果返回后的语义染色仍会写入全文。持续滚动卡顿的主要热点则是折叠箭头绘制中的二次遍历;重复全文排版是另一个独立停顿来源。 完整应用的主线程采样与保留全文着色的单变量对照相互印证,开启实际 JDT LS 后也观察到了相同问题。

    以下两份完整报告产生于正式修复之前,按当时阶段保留。因此其中的“未交付正式产品修复”、实验开关、31 个回归测试等描述属于历史记录。第一阶段使用约 266 KiB 的原生探针文件,第二阶段使用 447 KiB 的完整产品文件,两个阶段的计时不能混用;两者均使用合成文件,没有取得原问题中的业务源码。

    第一阶段:最初的原生文本操作诊断

    展开完整原始报告:独立 AppKit 探针、测量表、限制及后续验证矩阵

    Issue 561: isolated Java text diagnostic

    Scope

    No product source was changed. No IDE window or LSP was started. This is an isolated native text-operation probe, not an end-to-end reproduction of the user report.

    Fixture: 8329 lines, 271949 UTF-8 bytes (265.6 KiB), 142 methods, 164 imports, 69 injected fields. The fixture has 1990 fold regions and 50701 classified tokens; its structure may differ substantially from the unavailable user file.

    LargeService.java and LargeService.txt contain identical bytes. The native probe loads the Java fixture and does not test extension routing.

    Host: macOS 27.0 / arm64. Rust library: existing release binary, modified 2026-09-07 09:13:10; no fresh product build. The inspected Java source files predate this binary, but embedded-source provenance has not been independently verified.

    Measurements

    Each row is a median of five measured repetitions after one warmup. The attributed-string setup and initial viewport layout are excluded. Units: milliseconds.

    Colored tokens Layout requested Tokens Attribute mutation Subsequent layout Total
    none visible 0 0.000 0.015 0.016
    none full 0 0.000 75.202 75.203
    visible visible 1347 0.375 6.290 6.685
    visible full 1347 0.398 87.341 87.711
    full visible 50701 14.591 9.227 23.931
    full full 50701 14.676 246.190 261.200

    The separate Rust java.structure C ABI call took 948.395 ms median, including response serialization and copying but excluding Python JSON decoding. This call runs in a background task in the product and must not be added directly to main-thread blocking time.

    Interpretation

    Full-document layout after full-document token coloring was the largest measured native step. Keeping only viewport layout reduced this operation-level cost substantially; restricting token coloring reduced it further. These results justify collecting a product main-thread profile around applyJavaStructure/updateFolds. They do not prove that this is the sole cause of the reported 2–7 FPS, or exclude LSP and other product paths.

    Limitations

    • NativeTextProbe reproduces the NSLayoutManager fold delegate and NSTextStorage foreground-attribute loop, not the complete CodeTextView or SwiftUI view tree.
    • System monospaced font and simplified five-color palette; product theme/font costs are not included.
    • Viewport token filtering, setup, initial viewport layout, and JSON decoding are excluded from reported native timing.
    • One warmup and five measured repetitions per condition; these are diagnostic medians, not performance assertions.
    • No actual typing, scrolling, or product FPS was measured.

    Product verification matrix

    Use the same Java file and initial viewport; hold theme, font, window size, import folding and Code Vision constant. Use a Release build, separate cold-open and warm-open runs, then check a single-character edit and continuous scrolling.

    Condition LSP Semantic coloring Fold layout What it isolates
    A On Current Current Product baseline
    B Off Current Current LSP contribution
    C Off Viewport only Current Coloring contribution
    D Off Current Skip unchanged/full invalidation Layout contribution
    E Off Viewport only Skip unchanged/full invalidation Combined local change

    Add timing spans for structure request/response, applyJavaSemanticHighlights, updateFolds, and editor input. Sample the main thread while the hitch occurs. Record ranges processed, token counts, layout refresh count, and input-to-visible-update latency. A matching hot stack plus repeatable improvement in the single-variable condition confirms attribution. Re-enable LSP before accepting a fix.

    Rerun native probe

    swiftc -O .artifacts/issue-561/NativeTextProbe.swift -o .artifacts/issue-561/native-text-probe
    .artifacts/issue-561/native-text-probe .artifacts/issue-561

    The original compiler and native execution were supervised with 60-second and 90-second subprocess deadlines. The optional run-core-probe.py accepts an explicit dylib path and enforces a 30-second parent-owned deadline.

    Raw native timings: native-results.json. Core times and provenance: metadata.json. Fixture and decoded Rust response are retained in the same directory.

    第二阶段:完整 macOS 产品复现

    展开完整原始报告:实际应用、主线程采样、单变量对照及 JDT LS 验证

    Issue #561:完整 macOS 产品性能验证

    结论

    在本次合成文件复现中,持续卡顿的主要热点是行号栏的折叠箭头绘制。主线程采样、直接计时和保留全文语义着色的单变量对照相互印证。全文语义染色后反复强制全文排版是另一个独立的打开/编辑停顿来源。

    本次只做验证,未交付正式产品修复。所有临时探针和行为开关已经从产品源码撤回,原文件(包括任务开始前已有的用户改动)已按 SHA-256 验证逐字节恢复。

    实验环境

    • 日期:2026-09-11;macOS 27.0,Apple Silicon。
    • 当前工作树构建的完整 Release 产品;HEAD:6a1ae4d43f3e。工作树含任务开始前已有改动。
    • 使用本机 Swift 6.3.3。仓库要求的 Swift 6.2 工具链符号链接失效,本次没有安装/切换工具链。
    • 新构建并链接了 Rust Core,使用实际 CodeEditorView、CodeTextView、NSTextStorage、NSLayoutManager、行号栏和 SwiftUI 工作台。
    • 实际打包 .app,并复用已有捆绑 JDK/JDT LS;语言服务器开启组保留 JDT LS 初始化日志和 Java 子进程证据。
    • 固定合成 Java 文件:8329 行、457728 字节(447 KiB)、164 个 import、142 个方法、69 个注入字段,约 50701 个语义 token、1990 个折叠区域。
    • 固定默认主题、字体、窗口尺寸、默认 import 折叠和开启的 Code Vision 配置。没有修改用户真实项目文件。

    主结果

    表中多轮结果取各轮中位数的中位数;每轮独立启动进程并使用新的测试工作区。关闭 LSP 的主比较使用第二版同一探针二进制,排除了首次 UI 观察尝试的探索轮。

    条件 轮数 结构结果应用中位数 滚动时箭头绘制中位数 26 次滚动序列耗时
    当前行为,LSP 关闭 2 808.9 ms 957.116 ms 22.228 s
    仅优化折叠箭头遍历,LSP 关闭 2 752.9 ms 0.881 ms 0.553 s
    三项实验优化一起启用,LSP 关闭 2 9.9 ms 0.916 ms 0.551 s
    当前行为,LSP 开启 1 920.7 ms 992.752 ms 24.917 s
    仅优化折叠箭头遍历,LSP 开启 1 957.3 ms 1.044 ms 0.721 s

    结构结果应用包括语义着色和 applyFoldState;其中不包含异步 Rust 分析等待时间。每轮实际经历打开、三处单字符插入、26 次滚动。滚动以 16 ms 的主线程定时器产生相同刺激,因此上表反映完成同一操作序列的耗时,不能换算成产品实际渲染 FPS。

    如何定位到折叠箭头

    1. 最初三个探索组分别保留当前行为、仅限制语义着色范围、仅跳过未变化的折叠几何刷新。三者的滚动序列分别耗时约 22.7、23.3、20.2 秒,后两者仍有持续卡顿。
    2. 编辑期间采样主线程,后两个探索组中 drawFoldIndicators 调用栈分别占 2559/4007(63.9%)、3302/4107(80.4%)样本;大量下层调用涉及字符串构造/分配。
    3. 代码在每次绘制中,对每个折叠区域再次 regions.contains 遍历全部区域,判断父折叠。视口范围判断在这之后。1990 个区域对应最坏约 396 万次父区域检查,每次还会计算字符串形式的 id。
    4. 单变量实验仅先筛出 collapsedFoldIDs 中的候选父区域,再使用原有的父区域判断;保留全文语义着色和原有全文排版。当前文件默认只折叠 import,于是内层由约 1990 个候选降为 1 个。
    5. 两轮关闭 LSP 对照均从约 22 秒降至约 0.55 秒。启用并完成初始化的 JDT LS 对照也从约 24.9 秒降至约 0.72 秒。

    定位:CodeEditorView.swift:4605,LineNumberGutterView.drawFoldIndicators。
    ID 构造:JavaNavigationModels.swift:86。

    次要但独立的停顿

    仅优化箭头后,结构结果应用仍约 0.75 秒。updateFolds 在折叠几何没有改变时依然使全文布局失效,再同步 ensureLayout 整个文本容器。将语义着色限制到视口,并跳过未变化的折叠几何刷新,再配合箭头遍历优化后,结果应用降至约 10 ms。

    定位:CodeEditorView.swift:2693。

    限制

    • 没有获得 issue 中的原始业务源码。合成文件对齐行数和字节数,但控制流、折叠密度、依赖完整性和语义复杂度可能不同;这些结果确认了本地热点,不能证明原报告只有这些根因。
    • 原报告为 macOS 15.5 / Lithe 0.4.3,本次为 macOS 27 / 当前工作树。此前已确认所分析的关键路径在 v0.4.3 中存在。
    • 没有搭建报告中的 3564 文件、9 个 Maven 模块工程;LSP 开启组是实际单文件 Java 工作区,不代表大型 Maven 索引负载。
    • 未单独完成同一应用会话内关闭标签页再重新打开的暖打开对照;重复启动轮不能替代该场景。
    • 操作由进程内诊断驱动调用实际 AppKit 编辑和滚动入口;没有声称测到了物理键盘/触控板到屏幕的端到端延迟。
    • 视口语义着色实验仅筛选当前视口 token,未实现完整的滚动补色、缓存失效和跨行语义处理,因此不能直接作为正式修复提交。
    • 第一版探针的 heartbeat 输出没有保留阶段标签,仅使用其整体阻塞证据;主结果使用第二版同一二进制。
    • 第一次探索轮尝试通过辅助功能观察窗口超时;该轮不进入第二版的主要对照汇总。

    原始证据和复现材料

    • summary.json:每轮统计。
    • 各运行目录的 events.jsonl:直接计时、阶段和操作记录;sample.txt:启动阶段采样;active-sample.txt:编辑阶段采样。
    • processes.txt、status.json:测试进程及完成记录;JDT LS 开启组的 Java 进程已被观测。
    • *.jdtls.log:两个测试工作区的 JDT LS 初始化日志副本。
    • instrumentation-v2.patch、JavaEditorPerformanceProbe.swift:临时诊断改动,已从产品源码撤回。
    • run-product.py:打包和逐轮运行监督器,每轮 90 秒单调时钟截止时间,并清理进程树和采样子进程。
    • originals.json、restoration.json:原文件指纹及恢复验证。
    • workspace/LargeService.java:可复用合成文件;build.log 和 build-v2.log:两次成功的 Release 构建。

    收尾验证

    • 两次完整 macOS Release 构建成功。
    • 临时改动期间测试稳定性静态检查、服务边界检查及 git diff --check 通过。
    • 原源码已恢复,临时 .app 和两个本次创建的 JDT LS 缓存目录已删除。
    • 源码恢复后,通过计时 harness 运行相关编辑器回归测试:31 个测试、4 个套件全部通过,测试执行共 0.379 秒。逐项耗时和 HTML/JUnit 已生成。
    • 回归命令:./.agents/skills/write-stable-tests/scripts/test-stability-macos.sh --report .artifacts/test-stability/issue-561-macos-swift.json -- --filter 'EditorSyntaxHighlighterTests|EditorCaretGeometryTests|TextViewportLayoutTests'。
    • 最终服务边界检查和 git diff --check 再次通过。

    最慢的三个相关测试:yamlIncrementalHighlightingUsesCachedLineStateNearDocumentEnd() 106 ms;xmlIncrementalHighlightingUsesCachedLineStateNearDocumentEnd() 98 ms;caretAfterLastCharacterSitsPastTheFinalGlyphWhenFileHasNoTrailingNewline() 75 ms。所有测试均低于 1000 ms 警告阈值。

    配套测量数据

    以下包含第一阶段全部 30 次原生操作测量、环境及 Rust 调用记录,以及第二阶段全部 11 轮统计。两份结果 JSON 与原始诊断归档一致;元数据仅将 Rust 库的本机绝对路径改为仓库相对路径。null 表示未采集到该项数据,不表示零耗时。第二阶段主比较排除第一版探索轮,具体分组以报告说明为准。

    native-metadata.json
    {
      "lines": 8329,
      "utf8Bytes": 271949,
      "methods": 142,
      "imports": 164,
      "injectedFields": 69,
      "tokens": 50701,
      "folds": 1990,
      "structureMs": [
        945.9102919936413,
        954.8951250035316,
        945.8428340003593,
        948.3947919943603,
        951.0688330046833
      ],
      "structureMedianMs": 948.3947919943603,
      "binary": "rust/target/macos/aarch64-apple-darwin/release/liblithe_core.dylib",
      "binaryModified": "2026-09-07 09:13:10",
      "limitations": [
        "Synthetic source; no user file available.",
        "Existing release Rust binary from 2026-09-07; no fresh application build.",
        "No LSP or full IDE launched."
      ],
      "sourceSHA256": "16361866a35c82e981440d1d4ae2413da3dcce0b210107c837fa952491525897",
      "hostOS": "27.0",
      "hostMachine": "arm64",
      "nativeProbeLimitations": [
        "NativeTextProbe reproduces the NSLayoutManager fold delegate and NSTextStorage foreground-attribute loop, not the complete CodeTextView or SwiftUI view tree.",
        "System monospaced font and simplified five-color palette; product theme/font costs are not included.",
        "Viewport token filtering, setup, initial viewport layout, and JSON decoding are excluded from reported native timing.",
        "One warmup and five measured repetitions per condition; these are diagnostic medians, not performance assertions.",
        "No actual typing, scrolling, or product FPS was measured."
      ]
    }
    native-results.json
    [
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00095799999999999998,
        "colorScope" : "none",
        "iteration" : 1,
        "layoutMs" : 0.015583,
        "layoutScope" : "visible",
        "totalMs" : 0.016541,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.001083,
        "colorScope" : "none",
        "iteration" : 2,
        "layoutMs" : 0.014999999999999999,
        "layoutScope" : "visible",
        "totalMs" : 0.016083,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00033300000000000002,
        "colorScope" : "none",
        "iteration" : 3,
        "layoutMs" : 0.014833000000000001,
        "layoutScope" : "visible",
        "totalMs" : 0.015166000000000001,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00020799999999999999,
        "colorScope" : "none",
        "iteration" : 4,
        "layoutMs" : 0.013667,
        "layoutScope" : "visible",
        "totalMs" : 0.013875,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00029100000000000003,
        "colorScope" : "none",
        "iteration" : 5,
        "layoutMs" : 0.015834000000000001,
        "layoutScope" : "visible",
        "totalMs" : 0.016125,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00041599999999999997,
        "colorScope" : "none",
        "iteration" : 1,
        "layoutMs" : 75.475958000000006,
        "layoutScope" : "full",
        "totalMs" : 75.476374000000007,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00025000000000000001,
        "colorScope" : "none",
        "iteration" : 2,
        "layoutMs" : 75.558207999999993,
        "layoutScope" : "full",
        "totalMs" : 75.558457999999987,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00025000000000000001,
        "colorScope" : "none",
        "iteration" : 3,
        "layoutMs" : 75.135666000000001,
        "layoutScope" : "full",
        "totalMs" : 75.135915999999995,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00045800000000000002,
        "colorScope" : "none",
        "iteration" : 4,
        "layoutMs" : 75.202207999999999,
        "layoutScope" : "full",
        "totalMs" : 75.202665999999994,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 0,
        "colorMs" : 0.00025000000000000001,
        "colorScope" : "none",
        "iteration" : 5,
        "layoutMs" : 74.316458999999995,
        "layoutScope" : "full",
        "totalMs" : 74.316708999999989,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.376917,
        "colorScope" : "visible",
        "iteration" : 1,
        "layoutMs" : 6.2760420000000003,
        "layoutScope" : "visible",
        "totalMs" : 6.6529590000000001,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.37458399999999997,
        "colorScope" : "visible",
        "iteration" : 2,
        "layoutMs" : 6.5937919999999997,
        "layoutScope" : "visible",
        "totalMs" : 6.9683759999999992,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.36762499999999998,
        "colorScope" : "visible",
        "iteration" : 3,
        "layoutMs" : 6.2495000000000003,
        "layoutScope" : "visible",
        "totalMs" : 6.6171250000000006,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.39466699999999999,
        "colorScope" : "visible",
        "iteration" : 4,
        "layoutMs" : 6.2898750000000003,
        "layoutScope" : "visible",
        "totalMs" : 6.6845420000000004,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.36499999999999999,
        "colorScope" : "visible",
        "iteration" : 5,
        "layoutMs" : 6.5425420000000001,
        "layoutScope" : "visible",
        "totalMs" : 6.9075420000000003,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.37054100000000001,
        "colorScope" : "visible",
        "iteration" : 1,
        "layoutMs" : 87.340917000000005,
        "layoutScope" : "full",
        "totalMs" : 87.711458000000007,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.40204200000000001,
        "colorScope" : "visible",
        "iteration" : 2,
        "layoutMs" : 84.207791,
        "layoutScope" : "full",
        "totalMs" : 84.609832999999995,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.36670900000000001,
        "colorScope" : "visible",
        "iteration" : 3,
        "layoutMs" : 79.211250000000007,
        "layoutScope" : "full",
        "totalMs" : 79.577959000000007,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.39820800000000001,
        "colorScope" : "visible",
        "iteration" : 4,
        "layoutMs" : 96.397041999999999,
        "layoutScope" : "full",
        "totalMs" : 96.795249999999996,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 1347,
        "colorMs" : 0.846584,
        "colorScope" : "visible",
        "iteration" : 5,
        "layoutMs" : 104.387958,
        "layoutScope" : "full",
        "totalMs" : 105.234542,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.717625,
        "colorScope" : "full",
        "iteration" : 1,
        "layoutMs" : 9.2130410000000005,
        "layoutScope" : "visible",
        "totalMs" : 23.930666000000002,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.277749999999999,
        "colorScope" : "full",
        "iteration" : 2,
        "layoutMs" : 9.0090000000000003,
        "layoutScope" : "visible",
        "totalMs" : 23.286749999999998,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.305624999999999,
        "colorScope" : "full",
        "iteration" : 3,
        "layoutMs" : 9.2265420000000002,
        "layoutScope" : "visible",
        "totalMs" : 23.532167000000001,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.590833,
        "colorScope" : "full",
        "iteration" : 4,
        "layoutMs" : 9.3730419999999999,
        "layoutScope" : "visible",
        "totalMs" : 23.963875000000002,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.842541000000001,
        "colorScope" : "full",
        "iteration" : 5,
        "layoutMs" : 9.3969170000000002,
        "layoutScope" : "visible",
        "totalMs" : 24.239457999999999,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.678625,
        "colorScope" : "full",
        "iteration" : 1,
        "layoutMs" : 257.00383299999999,
        "layoutScope" : "full",
        "totalMs" : 271.682458,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 15.01,
        "colorScope" : "full",
        "iteration" : 2,
        "layoutMs" : 246.19045800000001,
        "layoutScope" : "full",
        "totalMs" : 261.20045800000003,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 13.989708,
        "colorScope" : "full",
        "iteration" : 3,
        "layoutMs" : 240.33179200000001,
        "layoutScope" : "full",
        "totalMs" : 254.32150000000001,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 13.994583,
        "colorScope" : "full",
        "iteration" : 4,
        "layoutMs" : 280.76008300000001,
        "layoutScope" : "full",
        "totalMs" : 294.75466599999999,
        "visibleUTF16Length" : 9091
      },
      {
        "coloredTokens" : 50701,
        "colorMs" : 14.676458,
        "colorScope" : "full",
        "iteration" : 5,
        "layoutMs" : 242.762833,
        "layoutScope" : "full",
        "totalMs" : 257.43929100000003,
        "visibleUTF16Length" : 9091
      }
    ]
    product-reproduction-summary.json
    [
      {
        "run": "all-lsp0-1",
        "mode": "all",
        "durationMs": 16135.51525,
        "structureApplyMedianMs": 9.6905205,
        "semanticMedianMs": 0.6828749999999999,
        "foldLayoutMedianMs": 351.326875,
        "gutterMedianMs": 0.9440625,
        "gutterScrollMedianMs": 0.939375,
        "gutterScrollP95Ms": 0.976875,
        "nativeInputMedianMs": 27.433875,
        "scrollSequenceMs": 626.3539170000004,
        "mainLoopMaxGapMs": 4731.95975,
        "mainLoopP95GapMs": 115.267542,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 3512,
        "gutterSamples": 8
      },
      {
        "run": "all-lsp0-2",
        "mode": "all",
        "durationMs": 15662.310292,
        "structureApplyMedianMs": 10.092646,
        "semanticMedianMs": 0.5066455,
        "foldLayoutMedianMs": 353.702167,
        "gutterMedianMs": 0.897125,
        "gutterScrollMedianMs": 0.892896,
        "gutterScrollP95Ms": 0.936625,
        "nativeInputMedianMs": 28.825667,
        "scrollSequenceMs": 475.7480839999989,
        "mainLoopMaxGapMs": 4817.884041,
        "mainLoopP95GapMs": 105.089625,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 3583,
        "gutterSamples": 10
      },
      {
        "run": "baseline-lsp0-1",
        "mode": "baseline",
        "durationMs": 54647.25225,
        "structureApplyMedianMs": 754.4141045,
        "semanticMedianMs": 8.1111255,
        "foldLayoutMedianMs": 746.722333,
        "gutterMedianMs": null,
        "gutterScrollMedianMs": null,
        "gutterScrollP95Ms": null,
        "nativeInputMedianMs": 28.295375,
        "scrollSequenceMs": 22709.611375,
        "mainLoopMaxGapMs": 5825.807333,
        "mainLoopP95GapMs": 2891.984834,
        "sampledJavaProcesses": false,
        "lspRequested": false
      },
      {
        "run": "baseline-lsp0-2",
        "mode": "baseline",
        "durationMs": 51828.780416,
        "structureApplyMedianMs": 833.0087920000001,
        "semanticMedianMs": 9.9156665,
        "foldLayoutMedianMs": 765.79225,
        "gutterMedianMs": 966.04625,
        "gutterScrollMedianMs": 963.1514585,
        "gutterScrollP95Ms": 983.834667,
        "nativeInputMedianMs": 30.392042,
        "scrollSequenceMs": 22306.455083,
        "mainLoopMaxGapMs": 4077.909459,
        "mainLoopP95GapMs": 3171.218041,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 4236,
        "gutterSamples": 2386
      },
      {
        "run": "baseline-lsp0-3",
        "mode": "baseline",
        "durationMs": 53534.224167,
        "structureApplyMedianMs": 784.8403125,
        "semanticMedianMs": 9.85925,
        "foldLayoutMedianMs": 735.790459,
        "gutterMedianMs": 955.647875,
        "gutterScrollMedianMs": 951.0796245,
        "gutterScrollP95Ms": 963.472125,
        "nativeInputMedianMs": 29.541375,
        "scrollSequenceMs": 22150.474875000004,
        "mainLoopMaxGapMs": 5271.945791,
        "mainLoopP95GapMs": 2816.595458,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 4173,
        "gutterSamples": 1625
      },
      {
        "run": "baseline-lsp1-1",
        "mode": "baseline",
        "durationMs": 64428.17725,
        "structureApplyMedianMs": 920.6885625,
        "semanticMedianMs": 10.6599585,
        "foldLayoutMedianMs": 896.085583,
        "gutterMedianMs": 1035.373875,
        "gutterScrollMedianMs": 992.752,
        "gutterScrollP95Ms": 1181.692917,
        "nativeInputMedianMs": 34.588625,
        "scrollSequenceMs": 24917.036458000002,
        "mainLoopMaxGapMs": 4934.814208,
        "mainLoopP95GapMs": 1935.062125,
        "sampledJavaProcesses": true,
        "lspRequested": true,
        "mainSamples": 3878,
        "gutterSamples": 1665
      },
      {
        "run": "fold-lsp0-1",
        "mode": "fold",
        "durationMs": 51176.290792,
        "structureApplyMedianMs": 265.445833,
        "semanticMedianMs": 9.7043125,
        "foldLayoutMedianMs": 349.05575,
        "gutterMedianMs": null,
        "gutterScrollMedianMs": null,
        "gutterScrollP95Ms": null,
        "nativeInputMedianMs": 32.624666,
        "scrollSequenceMs": 20177.453334,
        "mainLoopMaxGapMs": 4410.158375,
        "mainLoopP95GapMs": 2020.265375,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 4107,
        "gutterSamples": 3302
      },
      {
        "run": "gutter-lsp0-1",
        "mode": "gutter",
        "durationMs": 18882.58425,
        "structureApplyMedianMs": 752.5537919999999,
        "semanticMedianMs": 9.812042,
        "foldLayoutMedianMs": 734.88625,
        "gutterMedianMs": 0.89525,
        "gutterScrollMedianMs": 0.884584,
        "gutterScrollP95Ms": 1.062792,
        "nativeInputMedianMs": 39.438542,
        "scrollSequenceMs": 538.1626250000008,
        "mainLoopMaxGapMs": 3520.724625,
        "mainLoopP95GapMs": 762.485833,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 4044,
        "gutterSamples": 1040
      },
      {
        "run": "gutter-lsp0-2",
        "mode": "gutter",
        "durationMs": 19666.169708,
        "structureApplyMedianMs": 753.212479,
        "semanticMedianMs": 10.272104,
        "foldLayoutMedianMs": 731.31375,
        "gutterMedianMs": 0.8779375,
        "gutterScrollMedianMs": 0.877708,
        "gutterScrollP95Ms": 0.90275,
        "nativeInputMedianMs": 38.713667,
        "scrollSequenceMs": 567.2565830000021,
        "mainLoopMaxGapMs": 4211.400916,
        "mainLoopP95GapMs": 780.064583,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 4117,
        "gutterSamples": 1042
      },
      {
        "run": "gutter-lsp1-1",
        "mode": "gutter",
        "durationMs": 23291.304958,
        "structureApplyMedianMs": 957.3136045,
        "semanticMedianMs": 14.6593955,
        "foldLayoutMedianMs": 925.971063,
        "gutterMedianMs": 1.0436044999999998,
        "gutterScrollMedianMs": 1.0436044999999998,
        "gutterScrollP95Ms": 1.229833,
        "nativeInputMedianMs": 40.588459,
        "scrollSequenceMs": 720.6698749999996,
        "mainLoopMaxGapMs": 4665.652542,
        "mainLoopP95GapMs": 165.474791,
        "sampledJavaProcesses": true,
        "lspRequested": true,
        "mainSamples": 3305,
        "gutterSamples": 2
      },
      {
        "run": "viewport-lsp0-1",
        "mode": "viewport",
        "durationMs": 48061.829208,
        "structureApplyMedianMs": 292.13541699999996,
        "semanticMedianMs": 0.5286044999999999,
        "foldLayoutMedianMs": 307.754291,
        "gutterMedianMs": null,
        "gutterScrollMedianMs": null,
        "gutterScrollP95Ms": null,
        "nativeInputMedianMs": 29.968375,
        "scrollSequenceMs": 23320.388750000002,
        "mainLoopMaxGapMs": 4323.491041,
        "mainLoopP95GapMs": 2420.506959,
        "sampledJavaProcesses": false,
        "lspRequested": false,
        "mainSamples": 4007,
        "gutterSamples": 2559
      }
    ]

    后续正式修复及验证

    正式实现见 PR #621。修复补齐了视口语义缓存、跨行 token、编辑/主题失效、滚动补色和折叠布局复用,不是直接提交上面的实验开关。

    以 preview 的 481da5e8b551 为基础,使用同一份 8329 行、457728 字节的合成文件,在完整 Release 应用重新执行打开、三次单字符编辑和 26 次滚动:

    正式复测条件 完成轮数 结构结果应用中位数 滚动时整个行号栏绘制中位数 固定滚动序列
    对照,LSP 关闭 1 770.8 ms 915.204 ms 20.719 s
    正式修复,LSP 关闭 2 2.4 ms 0.633 ms 0.495–0.645 s
    对照,JDT LS 开启 1 847.5 ms 3329.100 ms 72.627 s
    正式修复,JDT LS 开启 1 2.7 ms 0.726 ms 0.660 s

    关闭 LSP 的另一轮对照在 90 秒内只完成了 21 次滚动,已保留为超时记录,未计入完成轮统计;后续监督器截止时间调整为 150 秒。对照版有明显波动,这些数据用于确认本地瓶颈和改进方向,不是稳定的性能承诺。此表计时的是整个行号栏,早期报告计时的是折叠箭头函数,两项不能直接混用。结构应用不包含后台 Rust 等待,也不等于整个文件打开耗时;滚动序列不能换算成渲染 FPS。

    正式修复的三轮运行共完成 15 次可见语义颜色检查、4644 个 token 颜色比较,零不匹配。移除临时探针后,189 个相关测试(21 个套件)、Release 构建、测试稳定性与服务边界检查均通过;新增的 11 个确定性测试覆盖滚动、跨行/UTF-16、编辑和主题失效、折叠几何及屏幕外布局查询。

    本机为 macOS 27.0 / Apple Silicon,使用 Swift 6.3.3;仓库要求的 Swift 6.2 工具链链接失效。没有搭建原报告的 3564 文件、9 个 Maven 模块工程,也未完成同一应用会话内的暖打开对照。完整应用操作通过真实 AppKit 入口驱动,未测量物理输入到屏幕的端到端延迟。

    报告中的 .artifacts/issue-561/ 路径和复现命令是当时的本地执行记录,依赖本地探针及输入文件。本评论包含完整报告和上述统计 JSON;可执行探针、完整进程采样及其他本地运行材料没有上传。测试应用、子进程及本次创建的 JDT LS 缓存均已清理。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

LSPproblems related to LSP serviceP0立即处理:已严重影响使用体验,核心流程受阻或无法正常使用area:languagebugSomething isn't workingplatform:macosMacOS的需求

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions