Skip to content

build: generate Electron-specific PGO profiles in CI#51812

Merged
MarshallOfSound merged 1 commit into
mainfrom
sam/pgo-generation
Jun 1, 2026
Merged

build: generate Electron-specific PGO profiles in CI#51812
MarshallOfSound merged 1 commit into
mainfrom
sam/pgo-generation

Conversation

@MarshallOfSound

@MarshallOfSound MarshallOfSound commented May 31, 2026

Copy link
Copy Markdown
Member

Description of Change

Adds a manually-triggered (workflow_dispatch) pipeline that builds PGO-instrumented Electron for every published platform/arch combo, collects optimization profiles by running benchmark and app-style workloads against each build, and publishes merged profiles to https://dev-cdn.electronjs.org/pgo/.

Why Electron needs its own profiles

Electron release builds apply Chrome's published PGO profile (chrome_pgo_phase = 2). PGO profiles match functions by symbol name + control-flow hash, so every function that differs from Chrome — all of Node.js, patched Chromium code, V8 built with Node's flags, and the shell/ code itself — silently gets no optimization guidance and is laid out as cold. The same applies to V8's builtins profile: Chrome's published profiles reject Electron's promise/async builtins (RunMicrotasks, AsyncFunctionAwait, FulfillPromise, …) because Node's integration changes their codegen.

Measured impact of replacing Chrome's profile with an Electron-collected one (Linux x64, otherwise identical builds):

Workload Improvement
Speedometer 3.1 +9.5%
contextBridge calls +44–51%
ipcRenderer.invoke (5 MB payloads) +10%
renderer fetch() round-trips +31–35%
Node crypto.randomBytes +13% (recovers a 2× regression vs Electron 42 caused by Chrome-profile mismatch on patched BoringSSL)
Geomean of 22 app-operation benchmarks +16%

What the pipeline does

8x instrumented builds          1x instrumented d8
(chrome_pgo_phase = 1)          (v8_enable_builtins_profiling)
        |                                |
        v                                v
8x profile collection            JetStream 2 -> get_hints.py
(benchmarks + app workloads)             |
        |                                |
        v                                v
merge (llvm-profdata)            electron-v8-x64.profile
        |                                |
        +----------------+---------------+
                         v
     OIDC upload -> dev-cdn.electronjs.org/pgo/
  • Platforms: linux x64/arm/arm64, win x64/x86/arm64, macos x64/arm64 — each combo collects on hardware/containers that can run its own binaries (matching how Chrome generates per-arch profiles)
  • Collection workloads: Speedometer 3 (×3), JetStream 2, MotionMark — the same set Chromium's PGO recipe uses — plus Electron-specific phases that browser benchmarks can't cover: main-process Node.js (Buffer/crypto/fs/JSON), contextBridge + ipcRenderer.invoke marshaling, and renderer/Node networking over HTTPS + HTTP/2 with real certificate verification (an ephemeral CA is installed in the collection host's trust store)
  • V8 builtins profile: generated from an instrumented d8 built with Electron's exact V8 configuration; one x64 profile covers x64 + arm64 (block graphs are arch-independent, mirroring upstream)
  • Upload: gated behind the pgo-upload GitHub environment (manual approval) and authenticated via OIDC — no long-lived credentials. Infra side: electron/infra#287 (merged)

Build-system changes

  • build/args/pgo-instrument.gn / pgo-builtins-instrument.gn — instrumented build configurations
  • New Chromium patch fixing profile-runtime resolution for instrumented builds on Linux arm32 and Windows cross-compiles (upstreamable; Chrome never builds these configurations)
  • generate-chromedriver / generate-test-artifacts flags on the build segment (default true, no behavior change for existing callers) — instrumented builds skip artifacts only consumed by test jobs, saving ~10–20 min and ~700–950 MB per platform

What this PR does not do

Release builds do not consume these profiles yet — that's a follow-up PR (download profile + set pgo_data_path / v8_builtins_profiling_log_file). This PR only adds the generation side.

The pipeline was validated end-to-end on this branch's history: 13 full runs, with the final runs producing all 8 platform profiles + the builtins profile and uploading them to dev-cdn through the OIDC environment.

Checklist

  • I have built and tested this change
  • I have filled out the PR description
  • I have reviewed and verified the changes
  • npm test passes
  • PR release notes describe the change in a way relevant to app developers

Release Notes

Notes: none

@MarshallOfSound MarshallOfSound requested a review from a team as a code owner May 31, 2026 14:49
@MarshallOfSound MarshallOfSound force-pushed the sam/pgo-generation branch 8 times, most recently from 9162bca to b74c74a Compare May 31, 2026 18:02
@MarshallOfSound MarshallOfSound force-pushed the sam/pgo-generation branch 5 times, most recently from b610abd to a185fbf Compare June 1, 2026 03:25
Adds a workflow_dispatch pipeline that builds PGO-instrumented Electron
for every published platform/arch combo, collects optimization profiles
by running benchmark and app-style workloads against each build, and
publishes merged profiles to https://dev-cdn.electronjs.org/pgo/.

Why: Electron release builds apply Chrome's published PGO profile, which
matches functions by symbol name and control-flow hash. Every function
that differs from Chrome - all of Node.js, patched Chromium code, V8
built with Node's flags, and the shell/ code - silently gets no
optimization guidance and is laid out as cold. The same applies to V8's
builtins profile: Chrome's published profiles reject Electron's
promise/async builtins because the Node integration changes their
codegen. Measured on Linux x64, an Electron-collected profile is worth
+9.5% on Speedometer 3.1 and +16% geomean across 22 app-operation
benchmarks (contextBridge calls +44-51%) versus Chrome's profile.

The pipeline:

- Instrumented builds (chrome_pgo_phase = 1) for linux x64/arm/arm64,
  win x64/x86/arm64, and macos x64/arm64, each collecting on hosts that
  can run its own binaries.
- Collection workloads: Speedometer 3 (x3), JetStream 2, and MotionMark
  (the same set Chromium's PGO recipe uses), plus Electron-specific
  phases browser benchmarks cannot cover: main-process Node.js
  (Buffer/crypto/fs/JSON), contextBridge and ipcRenderer.invoke
  marshaling, and renderer/Node networking over HTTPS + HTTP/2 with real
  certificate verification via an ephemeral CA installed in the
  collection host's trust store.
- A V8 builtins profile generated from an instrumented d8 built with
  Electron's exact V8 configuration; one x64 profile covers x64 and
  arm64 (builtin block graphs are arch-independent, mirroring upstream).
- Per-platform profraw sets merged with in-tree llvm-profdata tooling,
  then uploaded via OIDC through the pgo-upload GitHub environment
  (manual approval, no long-lived credentials).

Build-system changes:

- build/args/pgo-instrument.gn and pgo-builtins-instrument.gn
  instrumented build configurations (symbol_level = 0, no dSYMs -
  instrumented binaries are never shipped and do not fit on macOS
  runners with debug info).
- A Chromium patch fixing profile-runtime resolution for instrumented
  builds on Linux arm32 (clang package ships the armv7 triple; the
  driver resolves the arm triple) and Windows cross-compiles (objects
  embed the per-target runtime lib name; the Windows package ships the
  legacy layout). Chrome never builds these configurations; the patch is
  upstreamable.
- generate-chromedriver and generate-test-artifacts flags on the build
  segment and build-electron action (default true, no behavior change
  for existing callers) so instrumented builds skip artifacts only
  consumed by test jobs.

Release builds do not consume these profiles yet; that is a follow-up
change.
@MarshallOfSound MarshallOfSound added target/42-x-y PR should also be added to the "42-x-y" branch. target/43-x-y PR should also be added to the "43-x-y" branch. and removed no-backport labels Jun 1, 2026
@MarshallOfSound MarshallOfSound enabled auto-merge (squash) June 1, 2026 19:29
@MarshallOfSound MarshallOfSound disabled auto-merge June 1, 2026 19:33
@MarshallOfSound

Copy link
Copy Markdown
Member Author

Merging this in to get PGOs cooking for backport branches. Please ping me directly if I missed something here. 🏃

@MarshallOfSound MarshallOfSound merged commit b034f49 into main Jun 1, 2026
119 of 121 checks passed
@MarshallOfSound MarshallOfSound deleted the sam/pgo-generation branch June 1, 2026 19:34
@release-clerk

release-clerk Bot commented Jun 1, 2026

Copy link
Copy Markdown

No Release Notes

@trop

trop Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "43-x-y", please check out #51825

@trop trop Bot added the in-flight/43-x-y label Jun 1, 2026
@trop

trop Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "42-x-y", please check out #51826

@trop trop Bot added in-flight/42-x-y merged/42-x-y PR was merged to the "42-x-y" branch. merged/43-x-y PR was merged to the "43-x-y" branch. and removed target/43-x-y PR should also be added to the "43-x-y" branch. target/42-x-y PR should also be added to the "42-x-y" branch. in-flight/42-x-y in-flight/43-x-y labels Jun 1, 2026
# JetStream 2.2 at the same pinned revision the browser collection uses.
git init /tmp/jetstream
git -C /tmp/jetstream remote add origin https://github.com/WebKit/JetStream.git
git -C /tmp/jetstream fetch --quiet --depth 1 origin 332d8ee1e4d5c40d9492c56f6865e64a9525ee9f

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's important to keep this in-sync with the the revision in script/pgo/serve-benchmarks.js, we should put it in a single place and plumb it through to both spots.

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

Labels

merged/42-x-y PR was merged to the "42-x-y" branch. merged/43-x-y PR was merged to the "43-x-y" branch. semver/none

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants