Skip to content

(Codex) 优化 RuntimeService.getScriptsForTab#1404

Draft
cyfung1031 wants to merge 3 commits intomainfrom
perf/getScriptsForTab
Draft

(Codex) 优化 RuntimeService.getScriptsForTab#1404
cyfung1031 wants to merge 3 commits intomainfrom
perf/getScriptsForTab

Conversation

@cyfung1031
Copy link
Copy Markdown
Collaborator

@cyfung1031 cyfung1031 commented May 6, 2026

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

Description / 描述

这个 PR 主要优化 RuntimeService.getScriptsForTab 和 service worker 初始化流程,目标是减少页面加载时不必要的重复计算,尤其改善“安装脚本很多,但实际启用脚本很少”的场景。

背景

原来的实现里,每次页面加载调用 getScriptsForTab 时,都会重新处理一批相对固定的脚本运行资料,包括:

  • 读取脚本资料
  • 读取 compiled resource
  • 加载 resource
  • 读取 script code
  • 解析 metadata / userConfig
  • 生成 URL match 相关资料

但这些内容大多数并不会因为普通的 value 更新而变化。比如用户脚本调用 GM_setValue 后,变化的通常只是脚本 value;脚本代码、metadata、match 规则、resource 等静态资料并没有变。每次页面加载都重新读取和解析这些资料,会造成不必要的开销。

另外,service worker 启动时原本会处理全部普通脚本,包括 disabled 脚本。对于安装了大量脚本但只启用少量脚本的用户来说,启动阶段仍然会为 disabled 脚本建立 compiled resource / matcher cache,成本偏高。

修改内容

1. 为页面加载增加运行期缓存

runtime.ts 中新增 service worker 生命周期内的 page-load cache,用来缓存单个脚本在页面加载时需要的静态资料:

  • scriptUrlPatterns
  • originalUrlPatterns
  • resource
  • metadataStr
  • userConfigStr
  • userConfig
  • code

这些缓存只存在于当前 service worker 生命周期内,不写入持久化存储,也不改变 getScriptsForTab 的输入输出结构。

2. getScriptsForTab 只刷新动态 value

新的 getScriptsForTab 流程会先根据当前 URL 找到匹配的 enabled 脚本,然后检查该脚本的静态资料缓存是否可用。

如果 cache 命中:

  • 复用 metadata / userConfig / resource / URL patterns / code 等静态资料
  • 只重新读取当前脚本 value

如果 cache 未命中:

  • 读取或生成 compiled resource
  • 加载 resource
  • 读取 script code
  • 解析 metadataStr / userConfigStr / userConfig
  • 写入 page-load cache

这样 GM_setValue / value-only 更新不会导致整套静态资料重新计算。

3. 保留脚本执行顺序

重写 getScriptsForTab 时,特别处理了 cache hit 和 cache miss 混合出现的情况。

现在会先按照 matcher 返回的顺序建立结果槽位,再把 cache hit / miss 的脚本回填到对应位置,避免因为部分脚本 cache miss 后异步追加,导致脚本执行顺序改变。

4. 更完整的 cache 失效处理

page-load cache 的 key 基于会影响运行静态资料的字段生成,包括:

  • metadata
  • originalMetadata
  • selfMetadata
  • status
  • type
  • updatetime

当脚本安装、更新、删除、启用、停用时,会清理相关 runtime cache,避免复用旧资料。

这次也把 code cache 一起纳入统一清理,避免只清理 page-load cache 但留下旧 code cache 的情况。

5. 保留本地 file:/// resource 热更新能力

对于 file:/// resource,页面加载时仍然会检查本地资源内容是否变化。

如果本地资源发生变化:

  • 更新 page-load cache 中的 resource
  • 更新当前返回给 content/inject 的 resource
  • 使用 cache 中保存的原始 code 重新编译注入代码
  • 更新已经注册的 userScript

这样优化缓存后,本地开发脚本时修改 file:/// 资源仍然可以生效。

6. service worker 初始化只预热 enabled 普通脚本

waitInit() 做了调整:

  • 不再通过 compiledResourceDAO.all() 读取全部 compiled resource
  • 改用 compiledResourceNamespace flag 判断是否需要清理旧注册
  • 只为 SCRIPT_TYPE_NORMAL && SCRIPT_STATUS_ENABLE 的脚本建立 matcher / compiled resource
  • disabled 普通脚本不再在 service worker 启动阶段预热

这样在“安装很多脚本,但只启用少量脚本”的场景下,service worker 启动时不需要处理大量 disabled 脚本。

7. Popup 的 disabled 脚本匹配改为按需计算,并增加缓存

Popup 需要显示“当前页面匹配但 disabled 的脚本”。原来这依赖初始化时预先建立的 scriptMatchDisable cache。

现在改为:

  • 正常页面加载路径只维护 enabled matcher
  • Popup 请求时单独处理 disabled 普通脚本
  • disabled matcher 会在首次 Popup 请求时按需构建
  • 后续 Popup 请求复用这个 matcher,避免每次打开 Popup 都扫描全部脚本
  • 当脚本安装、更新、删除、启用、停用、排序变化时,会清理该 matcher cache

这样页面加载路径不会被 disabled 脚本拖慢,同时 Popup 也不会每次都重复扫描全部脚本。

8. Popup 调用入口调整

popup.ts 中 Popup 获取页面匹配结果的逻辑从:

getPageScriptMatchingResultByUrl(url, true, true)

改为:

getPopupPageScriptMatchingResultByUrl(url)

这样 Popup 使用专门的匹配流程,避免普通页面加载逻辑继续依赖 disabled matcher。

测试覆盖

本 PR 补充了多组 runtime 测试,覆盖以下场景:

  • page-load cache 命中时复用静态资料
  • 每次页面加载仍然刷新 script value
  • 全局停用、黑名单、无匹配脚本时直接返回 null
  • run-innoframesinject-into 正确过滤和拆分脚本
  • cache hit / miss 混合时保持脚本顺序
  • 脚本更新时间变化后重建 page-load cache
  • file:/// resource 改变后更新缓存、返回结果和已注册 userScript
  • Popup 按需匹配 disabled 脚本
  • Popup disabled matcher 可复用,避免重复扫描全部脚本
  • runtime cache 清理后 Popup disabled matcher 会重建
  • Popup 合并 enabled / disabled 匹配结果,并保留 effective / non-effective 状态
  • disabled 脚本按 sort 顺序返回
  • 非普通脚本、enabled 脚本、无匹配规则的 disabled 脚本不会进入 disabled 扫描结果

兼容性

这个 PR 不改变 getScriptsForTab 的输入输出结构,也不改变 content / inject 接收到的数据格式。

新增缓存都只存在于 service worker 内存中。service worker 重启后,会按照现有流程重新建立需要的 matcher、compiled resource 和 page-load cache。

持久化数据结构没有变更。

Screenshots / 截图

@cyfung1031 cyfung1031 changed the title 优化 RuntimeService.getScriptsForTab (Codex) 优化 RuntimeService.getScriptsForTab May 6, 2026
@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented May 6, 2026

越来越激进了,我觉得要做好自动化测试

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

越来越激进了,我觉得要做好自动化测试

这个改动大。先放在这里做 draft PR
( 没 AI 根本改不动。尝试过手动改但很痛苦放弃了 )

会加测试

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants