Chromium 定制版 PGO 实战:Chrome 与 V8 Builtins 两套体系以及打包踩坑

📅 2026/7/3 3:09:20
Chromium 定制版 PGO 实战:Chrome 与 V8 Builtins 两套体系以及打包踩坑
本文基于一次真实升核M148 / V8 14.8.x打包与 PGO 训练整理前言为什么 PGO 会「编着编着就缺文件」切到 Official Release PGO Phase 2 后常见报错../../v8/tools/builtins-pgo/profiles/x64-rl.profileneeded by snapshot_blob.bin - gen/v8/embedded.Smissing and no known rule to make it这往往不是 snapshot 坏了而是 Chrome 主程序 PGO 与 V8 Builtins PGO 是两套机制只提交了 Chrome 的*.profdata却默认打开了 V8 builtins 优化构建在 schedule 阶段就失败。一、两套 PGO别混成一个「PGO 包」Chrome PGOV8 Builtins PGO优化对象chrome.dll等 CV8 builtinsmksnapshot/ snapshot训练产物*.profdatax64-rl.profile等训练工具tools/pgo/generate_profile.py官方下载或v8/tools/builtins-pgo/generate.pyPhase 2 开关chrome_pgo_phase2v8_enable_builtins_optimizationtruePhase 2 默认常开is_official_buildtrue→ chrome_pgo_phase2→ v8_enable_builtins_optimization 默认为 true若未显式关闭→ Windows x64 需要 x64-rl.profileChrome profdata 有了 ≠ V8 profile 有了。二、Chrome PGOPhase 1 与 Phase 2Phase 1插桩采集GNchrome_pgo_phase1编译带-fprofile-generate插桩版浏览器跑 benchmark →.profraw→llvm-profdata merge→profile.profdatapython3 tools/pgo/generate_profile.py -C out/PGOPhase1需要 完整源码树 Phase 1 输出目录不能只有二进制。Phase 2用 profile 优化-fprofile-use...profdata ThinLTO链接chrome.dll通常最慢CI 若每次 clean 全量每次都像第一次全编三、Phase 1 链接坑升核后 fork 与上游 API 类型不一致Phase 1 除了「能编过、能跑 benchmark」还可能遇到 链接阶段 才暴露的问题。下面是一次 M148 升核 chrome_pgo_phase1时的案例扩展工具栏 ViewModel与 V8 profile 无关但 不做修复就过不了 Phase 1也就训不出 Chrome profdata。3.1 现象在args.gn中设置chrome_pgo_phase 1# fork 定制宏已开启如扩展工具栏仍走 vector 顺序语义执行autoninja -C out/Release chromechrome.dll链接失败lld-link 报 undefined symbol符号栈与base::flat_tree/flat_set析构相关——表面看像 STL 或 libc 链接问题实际是 接口返回类型与底层实现不一致 在 PGO 插桩 下被放大。3.2 根因148 上游 vs fork 历史行为148 上游把ExtensionsToolbarViewModel::GetAllActionIds()改成了返回const base::flat_setActionId与ToolbarActionsModel::action_ids()对齐。定制 fork 在 产品宏分支 下仍保留ToolbarActionsModel::action_ids()返回std::vectorActionId扩展工具栏顺序语义依赖 vector而非 sorted flat_set。若 ViewModel 仍声明返回flat_set实现里却return actions_model_-action_ids()编译器对vector→flat_set做隐式转换构造 临时flat_set函数返回的是 临时对象的引用本身已是危险写法PGO Phase 1 插桩 下flat_tree析构路径 无法如 Release 那样内联链接器找不到对应符号 →chrome.dll链接失败非 PGO 或 Phase 0 构建有时能「侥幸过」或表现不同Phase 1 是更严格的照妖镜。3.3 修复思路与上游分叉的最小对齐在 fork 宏分支 让声明、实现与底层 同一类型——返回const std::vectorActionId直接转发action_ids()避免任何 vector→flat_set 临时对象#ifdef FORK_EXTENSIONS_TOOLBAR /* 示意你们实际的 fork 宏名 */const std::vectorToolbarActionsModel::ActionIdExtensionsToolbarViewModel::GetAllActionIds() const {return actions_model_-action_ids();}#elseconst base::flat_setToolbarActionsModel::ActionIdExtensionsToolbarViewModel::GetAllActionIds() const {return actions_model_-action_ids();}#endifHasAnyExtensions()在 fork 分支改为 直接读action_ids().empty()不要再经可能触发转换的GetAllActionIds()bool ExtensionsToolbarViewModel::HasAnyExtensions() const {#ifdef FORK_EXTENSIONS_TOOLBARreturn !actions_model_-action_ids().empty();#elsereturn !GetAllActionIds().empty();#endif}头文件同步改返回类型并加注释说明禁止在 fork 路径返回flat_set否则 PGO 链接可能再炸。3.4 测试建议项做法链接chrome_pgo_phase1autoninja -C out/Release chrome确认 chrome.dll 链接通过功能启动浏览器扩展工具栏图标显示、拖拽、溢出菜单回归Phase 0 / Phase 2 各编一次确认无新增链接错误3.5 对 PGO 流程的启示升核 → 先过 Phase 1 链接 能启动→ 再 generate_profile.py 训 profdata→ 再 Phase 2 V8 profilePhase 1 链接问题 和 Phase 2 缺 x64-rl.profile 是 不同阶段、不同层 的故障阶段典型错误性质Phase 1lld-link undefined symbolflat_set/flat_treefork 与 148 API 类型不一致 插桩Phase 2missing x64-rl.profileV8 builtins PGO 文件缺失升核合并时建议对flat_set/span/ 容器类型变更 做专项 grep凡 fork 仍用 vector 的模型上层 ViewModel 不要声明成 upstream 的 flat_set。四、V8 Builtins PGO官方包 vs 自训4.1 官方 profilehttps://storage.googleapis.com/chromium-v8-builtins-pgo/by-version/{V8四段版本}/meta.jsonhttps://storage.googleapis.com/chromium-v8-builtins-pgo/by-version/{V8四段版本}/x64-rl.profile版本来自v8/include/v8-version.h如14.8.178.4不是 Chrome 产品号。meta.json里revision需与DEPS的v8_revision一致 再用。4.2x64.profilevsx64-rl.profileWindows 正式构建x64-rl.profileLinux/macOS Clangx64.profile4.3 内网镜像 404、Google 有多为 镜像未同步chromium-v8-builtins-pgo桶。4.4 自训难点摘要Windows 要-rl、GN 须与正式 Release 一致、benchmark 环境、每次 bump V8 重做、profile 默认 gitignore。revision 对齐时 优先官方。五、推荐策略决策树升核 / 出包├─ Phase 1│ ├─ chrome.dll 链接过 → 修 fork/上游 API 不一致如 GetAllActionIds│ └─ generate_profile.py → profdata├─ Phase 2│ ├─ Chromepgo_data_path / 已提交 profdata│ └─ V8x64-rl.profile官方 revision 对齐或 v8_enable_builtins_optimizationfalse└─ CI确认 gn gen 真正传入 extra_args务实组合Chrome profdata 自训V8x64-rl.profile用官方revision 一致时。六、换机器训练 Chrome PGO 要带什么同 commit 完整srcPhase 1 的out/去掉obj/、*.pdb可瘦身llvm-profdata定制主程序若不叫chrome.exe需与generate_profile.py期望名对齐复制/改名七、Phase 2 编译慢场景体验首次全量很慢同目录无改动增量几乎为 0CI 每次 clean每次都慢八、官方 V8 下载示例 14.8.178.4https://storage.googleapis.com/chromium-v8-builtins-pgo/by-version/14.8.178.4/meta.jsonhttps://storage.googleapis.com/chromium-v8-builtins-pgo/by-version/14.8.178.4/x64-rl.profile放置v8/tools/builtins-pgo/profiles/meta.jsonv8/tools/builtins-pgo/profiles/x64-rl.profile九、总结Chrome PGO 与 V8 Builtins PGO 两套文件、两套流程。Phase 1 要先过 链接 benchmarkfork 与 148 返回类型 不一致会在 PGO 插桩下触发 lld-link。Phase 2 常见缺x64-rl.profileWindows 勿用x64.profile顶替。官方 V8 profile 在 revision 对齐时可直接用。CI 检查gn gen是否传入v8_enable_builtins_optimization等参数。代码示例中的FORK_EXTENSIONS_TOOLBAR为脱敏占位符请替换为你们仓库实际的 fork 宏名。