Repository navigation
Add --profile to record a CPU profile of every sample - #132
Merged
NullVoxPopuli merged 3 commits intoOct 4, 2026
Merged
Conversation
`pnpm bench --profile=<dir>` records a Chrome trace of each sample and keeps the CPU profile of the page's main thread between :start and :done. A trace has the user timing marks and the profiler samples on one clock, so the cut is exact. Per bench, the directory gets one JSON line per sample (self time per frame, and time per stack) and the full trace of the first sample. The app's source maps are copied as well, because the next build replaces dist. `pnpm profile:report <dir> [--base=<dir>]` prints self time per package and per function, and inclusive time per function, or the largest changes against a base run. Frames go through the source maps, and the name comes from the original source line, so two builds line up by function and file. The result file records PROFILE in its args, because a profiled run is only comparable with other profiled runs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When the report finds no name in the original source, it used the minified name, which changes with every build. Two runs of different builds then showed the same harness function as one removed and one added frame. An unnamed function now shows as (anonymous) with its original file and line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@NullVoxPopuli is attempting to deploy a commit to the NullVoxPopuli's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
On the ember apps at 8x, profiled runs added 10 to 20 points to one build's gain on the sync benches, compared with unprofiled runs of the same two builds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
NullVoxPopuli
approved these changes
Oct 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
pnpm bench --profile=<dir>records a CPU profile of every sample, cut to the time between:startand:done.pnpm profile:reportshows where that time went, or what changed against another profiled run.How it records
blink.user_timingand the V8 CPU profiler on. The trace has the marks and the profiler samples on one clock, so the cut at:startand:doneis exact. TheProfilerdomain alone has no clock in common withperformance.mark.<bench>.jsonl(one line per sample: self time per frame, and time per stack) and<bench>.trace.json.gz(the full trace of the first sample, for DevTools or Perfetto).<dir>/<framework>/maps, because the next build replacesdist.PROFILEin itsargs. Profiling slows the page down, so a profiled run is only comparable with other profiled runs.What the report shows
Per bench: self time per package, self time per function, and inclusive time per function. With
--base, it shows the largest changes for each instead.Frames go through the source maps. ember-source ships no maps of its own, but its
distkeeps real names, so the report reads the function name from the original source line. It also drops the content hash from chunk names (tracked-JcbMdnul.jsbecomestracked.js), so two different ember-source builds line up by function and file.Example, ember on
1 item, 100k updatesat 8x, 3 samples:Size
At 8x, a trace has a sample about every 180 µs. A 100 ms sample is about 300 KB of trace and 12 KB of JSON lines. Only the first trace per bench is kept.
🤖 Generated with Claude Code