Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

perf(test): make the DOM projects hermetic so they can run isolate:false (~3-4x suite speedup) #2648

Closed as not planned

Description

@os-zhuang

目标

让 dom / dom-heavy 项目在 isolate: false 下也能全绿,从而把整个测试套件再提速 ~3-4×。这是 #2641(分片)→ #2644(setup 分档)→ #2647(unit isolate:false)之后,测试提速的最后一个、也是最大的一个杠杆。

为什么值得(实测,10 核本机,566 文件 / 6894 测试)

配置 全套件 Duration vs 基线 失败
基线(isolate:true) 124s — 0
全局 isolate:false ~30s 4.2× 19 文件 / 71 测试
pool=vmThreads 293s 2.4× 更慢 4

关 isolate 后,吃掉一切的 import 阶段从 734s 累计崩到 57s。那 4.2× 是带着 19 个失败测出来的(失败文件提前 bail,省了本该跑的测试),修好后失败文件会跑全、tests 阶段涨回一些,保守估计 3×(124→40s)。无论怎么算,这是本套件唯一能再上一个数量级的杠杆。

unit 项目已在 #2647 独立拿下 isolate:false(node-env 纯逻辑,零泄漏,3.2× 单跑提速)。剩下的全部卡在 dom 家族的跨文件状态泄漏。

障碍:19 个 dom 文件在 isolate:false 下泄漏

关 isolate 后,worker 内模块图跨文件共享 → 模块级可变状态(ComponentRegistry 覆盖、happy-dom 节点、store/cache 单例、全局 mock)会从一个文件漏到下一个。失败信息聚类:43× "Unable to find"(元素没渲染出来)+ 6× "Cannot read",是典型的顺序依赖泄漏。

全部集中在 dom 项目 —— dom-heavy / console / unit 在 isolate:false 下都干净。

19 个失败文件(isolate:false 下,基于 commit 0fc893544)
packages/app-shell/src/hooks/__tests__/useNavigationSync.test.tsx
packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.badge.test.tsx
packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.dirty.test.tsx
packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.scope.test.tsx
packages/components/src/__tests__/snapshot-critical.test.tsx
packages/layout/src/__tests__/AppSchemaRenderer.test.tsx
packages/mobile/src/__tests__/useBreakpoint.test.ts
packages/plugin-designer/src/__tests__/ObjectManager.test.tsx
packages/plugin-detail/src/__tests__/HeaderHighlight.editable.test.tsx
packages/plugin-detail/src/__tests__/RecordRelatedListRenderer.hostactions.test.tsx
packages/plugin-detail/src/__tests__/RelatedList.filecolumns.test.tsx
packages/plugin-form/src/ObjectForm.submitBehavior.test.tsx
packages/plugin-form/src/WizardForm.successBehavior.test.tsx
packages/plugin-form/src/WizardForm.successMessage.test.tsx
packages/plugin-gantt/src/ObjectGantt.writeerror.test.tsx
packages/plugin-gantt/src/ResourceWorkload.test.tsx
packages/plugin-grid/src/__tests__/exportServer.test.tsx
packages/plugin-map/src/ObjectMap.styleFallback.test.tsx
packages/plugin-view/src/__tests__/ObjectView.test.tsx

疑似根因(需逐簇确认)

  • ComponentRegistry 是模块级单例、后写覆盖(packages/core/src/registry/Registry.ts,private components = new Map)。某个文件注册/覆盖了 widget 却没清 → 漏给下一个文件。→ 需要确定性的 afterEach reset(或每文件重播规范注册)。
  • 其它模块级可变单例:store / cache / 全局 mock(vi.mock)、MSW handler、定时器 —— 需审计。
  • 快照测试(snapshot-critical)对泄漏的 DOM 特别敏感,常是第一个暴露的。

打法

  1. 先给 ComponentRegistry 加可复位能力 + afterEach 复位钩子,进 dom setup。
  2. pnpm exec vitest run --project dom --no-isolate → 修一批 → 重跑,迭代到 0 失败。
  3. 用 --sequence.shuffle(多 seed) 验证是真 hermetic,不是碰巧顺序对(这是 isolate:false 唯一靠谱的验收标准,见 perf(test): run the unit project with isolate:false #2647 的做法)。
  4. 全绿后:在 config 里给 dom / dom-heavy 项目也设 isolate: false。
  5. CI 收益兑现后,可考虑把分片从 4 降回 1-2 省 runner 分钟,或维持 4 片、每片压到 ~40s。

复现

pnpm exec vitest run --no-isolate --reporter=dot   # 全局关 isolate,看 19 个失败
pnpm exec vitest run --project unit --no-isolate    # 对照:unit 全绿(#2647 已落地)

范围外 / 已排除

  • 不要动 isolate 到 unit 以外之前先修泄漏 —— 直接翻会红 19 个文件。
  • pool=vmThreads 已被数据枪毙(慢 2.4× + 失败),不是这条路。
  • 不要用「宽容 fallback」在渲染器里绕过泄漏(违反 AGENTS.md #0.1);修的是测试的 hermetic 性,不是产品代码。

源自 #2644 之后的 isolate/pool A/B 基准。

Activity

  1. os-zhuang commented on Jul 18, 2026

    @os-zhuang
    ContributorAuthor

    决策:不采用 isolate:false,保持 isolate: true 以优先长期稳定性

    评估后,维护者明确选择长期稳定性优先于一次性速度。理由:

    isolate: false 能带来 ~3-4× 提速,但代价是让整个 dom 套件永久对跨文件状态泄漏敏感。在这个 80+ agent 并行的仓库里:

    • 任何人新加的测试都可能引入只在特定文件顺序下才炸的 flaky 失败;
    • 红 main 会污染所有并行 agent 的基线(AGENTS.md 反复强调的红线);
    • vitest.config.mts 白纸黑字记录过,关闭 isolate 曾导致「上千个顺序依赖失败」。

    这个取舍不值得:#2641 / #2644 / #2647 已经把 CI 从 8.9 min 压到 ~2.5 min/片,安全收益已经兑现。用「更高的长期维护脆弱性」换那点即时收益,不符合本仓库的多 agent 并行现实。

    若未来需要更多 CI 速度

    用加分片这个零脆弱性的杠杆(ci.yml 里把 shard 4 → 6),不要翻 isolate。

    若优先级改变要重开

    本 issue 的完整定性(19 个泄漏文件、失败聚类、打法)保留供参考。但任何重启都必须走「shuffle 护栏持续强制 hermetic」的路径(修完泄漏 + CI 常驻 --sequence.shuffle 守门),绝不裸翻开关。

    Closing as not planned.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions