CI: Track SWC native binary size in PR stats comment#92938
Conversation
Adds a dedicated "Native Binary" section to the stats PR comment that tracks the size of `packages/next-swc/native/*.node`. Because the same binary is reused across the canary and PR checkouts in a single run, the canary baseline is sourced from the most recent value stored in Vercel KV history; canary runs record the measured value so the baseline stays up-to-date. Significant changes also surface in the top summary and get a trend sparkline. Co-Authored-By: Claude <noreply@anthropic.com>
…ctions Co-Authored-By: Claude <noreply@anthropic.com>
Failing test suitesCommit: 8ec5f99 | About building and testing Next.js
Expand output● rewrites manual href/as › development mode › should allow manual href/as on index page ● rewrites manual href/as › production mode › should allow manual href/as on index page |
Stats from current PR✅ No significant changes detected📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📎 Tarball URL |
| const nativeBinaryDir = path.join(__dirname, '../../native') | ||
|
|
||
| // Sum the size of all *.node files in the action's native/ directory. | ||
| async function getSwcBinarySize() { |
There was a problem hiding this comment.
This might be more valuable if we either break out per-platform or choose one/two to focus on (maybe x86_64 Linux + aarch64 darwin?). The total size is only somewhat meaningful.
There was a problem hiding this comment.
It's only Linux, since we only build linux
| return undefined | ||
| } | ||
|
|
||
| // Generate the dedicated Native Binary section shown after Bundle Sizes. |
There was a problem hiding this comment.
We could probably test this by adding something like this to the binary cdylib crate:
#[used]
#[unsafe(no_mangle)]
pub static LARGE_ARRAY: [u8; 10_000_000] = [1; 10_000_000];
// elsewhere...
if std::hint::black_box(&LARGE_ARRAY).len() == 0 {
eprintln!("{LARGE_ARRAY:?}");
}
mmastrac
left a comment
There was a problem hiding this comment.
We can land it and tweak.
| if (!entry.endsWith('.node')) continue | ||
| const stat = await fs.stat(path.join(nativeBinaryDir, entry)) | ||
| if (stat.isFile()) { | ||
| total += stat.size |
There was a problem hiding this comment.
it would be good to measure the size when it is stripped and when it is gzipped as well
|
Landing, and look at your comments as follow-up |
What?
Adds a new "Native Binary" section to the
Stats from current PRcomment posted by thegenerate-pull-request-statsGitHub Action. The section reports the size of the SWC native binary (packages/next-swc/native/*.node) built for the PR and the change relative to the latest value recorded oncanary.Example row:
Why?
The
.nodebinary is a sizable, user-facing artifact (it ships withnext). Today there's no visibility on its size in PRs, so regressions from Rust/Cargo changes are easy to miss. Surfacing the size (and a diff vs. canary) in the existing stats comment gives immediate feedback on any change that affects the binary.How?
.github/actions/next-stats-action/src/run/index.js): After the action copies the pre-built native binary into the working dirs, sum the size of every*.nodefile under the action'snative/directory and store it asGeneral.swcBinarySizeon both the canary and PR stat sets..github/actions/next-stats-action/src/add-comment.js): The workflow downloads a single pre-built binary and copies it into both the canary and PR checkouts, so an in-run diff would always be zero. Instead, for PR runs we overridemainRepoStats.General.swcBinarySizewith the most recentswcBinarySizefrom the Vercel KV history (the same store already used for other canary metrics). Canary runs keep the measured value, and the existing persistence path (saveToHistory/General) writes it back so future PRs see an updated baseline. If no history exists yet, the Canary column rendersN/Aand no change is shown.generateNativeBinarySectionemits a<details>-wrapped section styled like Bundle Sizes / All Metrics, rendered right after the Bundle Sizes block. It reusesprettify,formatChange, andgenerateTrendBarso formatting, thresholds, and sparklines are consistent with the rest of the comment. A tight threshold entry (swcBinarySize: { absoluteMin: 10 KB, percentMin: 0.5%, percentOnly: 0.05% }) is added so meaningful movement is flagged while tiny determinism noise is ignored.swcBinarySizelives onGeneral, the existinggenerateChangeSummaryautomatically promotes significant changes into the headline regression/improvement table at the top of the comment, using the labelSWC Binary Size.aggregate-results.jsmergesGeneralviaObject.assign, which is correct here (last-writer-wins on an identical value).No workflow changes are required — the existing
pull_request_stats.ymlalready downloads thenext-swc-binaryartifact and copies it into the action'snative/directory.Verification
Smoke-tested
add-comment.jslocally withLOCAL_STATS=1in two scenarios:N/A, PR value renders, Change is-, section still shown.swcBinarySizevalues → full diff rendered in both the Native Binary section and the top-level significance summary, with a sparkline of the last 5 historical entries.Closes NEXT-