Skip to content

More typed arrays: sample + counter times, some frametable columns - #6139

Merged
mstange merged 7 commits into
firefox-devtools:mainfrom
mstange:time-f64
Jul 10, 2026
Merged

More typed arrays: sample + counter times, some frametable columns#6139
mstange merged 7 commits into
firefox-devtools:mainfrom
mstange:time-f64

Conversation

@mstange

@mstangemstange commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Main | Deploy preview

This PR adds version 67.

Here's a JSLB size profile for this sp3 profile before the changes from this PR: https://share.firefox.dev/4vleTif

This PR takes care of a few more columns, i.e. lets us store more of them as separate slabs.

@codecov

codecovBot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.50649% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.54%. Comparing base (b33aa23) to head (e8dbbcf).
⚠️ Report is 1 commits behind head on main.

Files with missing linesPatch %Lines
src/profile-logic/data-structures.ts84.84%4 Missing and 1 partial ⚠️
src/profile-logic/process-profile.ts75.00%2 Missing ⚠️
src/test/fixtures/utils.ts71.42%2 Missing ⚠️
src/profile-logic/merge-compare.ts85.71%1 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #6139 +/- ##
==========================================
+ Coverage 83.53% 83.54% +0.01% 
==========================================
Files 343 343 Lines 36776 36852 +76 Branches 10321 10350 +29 ==========================================
+ Hits 30720 30789 +69 - Misses 5629 5635 +6 - Partials 427 428 +1 

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mstange
mstangeforce-pushed the time-f64 branch 7 times, most recently from f7c1d0c to fcdcf3dCompareJuly 7, 2026 04:39
@mstangemstange changed the title More typed arrays: sample + counter timesMore typed arrays: sample + counter times, some frametable columnsJul 7, 2026
@mstange
mstange marked this pull request as ready for review July 7, 2026 04:41
@mstange
mstange requested a review from canovaJuly 7, 2026 04:42
@mstange
mstangeforce-pushed the time-f64 branch 3 times, most recently from 0c3feb0 to 3b38bd6CompareJuly 7, 2026 20:26
@canova

Copy link
Copy Markdown
Member

Here's a JSLB size profile for this sp3 profile before the changes from this PR: https://share.firefox.dev/4vleTif

Curious, is there a size profile from after?

@mstange

Copy link
Copy Markdown
ContributorAuthor

Here's a JSLB size profile for this sp3 profile before the changes from this PR: https://share.firefox.dev/4vleTif

Curious, is there a size profile from after?

Before: https://share.firefox.dev/4peCGi7
After: https://share.firefox.dev/4grQPq0

This profile only has one thread.

The uncompressed size shrank from 219MB to 202MB. The compressed size got slightly worse: 35.8 MB to 36.1 MB. But this change isn't really about size anyway, it's about reducing the time spent in JSON.parse (and eventually JSON.stringify, once we upload as JSLB).

Here are profiles of loading the profile:
Before: https://share.firefox.dev/4fcLtNa (2.2s total, 258ms in JSON.parse, 1.22GB memory usage)
After: https://share.firefox.dev/4pjSz7i (1.9s total, 174ms in JSON.parse, 0.98GB memory usage)

@canova

Copy link
Copy Markdown
Member

Nice, thanks for the links!

@canovacanova left a comment

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.

Thanks for the PR! Looks good to me, but it would be good to reduce the unnecessary copy if possible.

And also with this PR, we start to always narrow address/func/inlineDepth values. I think that's fine for func and inlineDepth, but do you think it's also okay for address?

Comment threadsrc/profile-logic/profile-data.ts Outdated
raw: RawJsAllocationsTable
): JsAllocationsTable {
return {
time: Float64Array.from(raw.time),

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.

This will copy if raw.time is already a Float64Array, right? Can we avoid copying for that case here and below?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good catch! I think we need helpers like toFloat64Array somewhere which do this. I might add those in a follow-up.

ProfileSelectors.getStackTable,
(state: State) =>
ProfileSelectors.getRawProfileSharedData(state).frameTable,
ProfileSelectors.getFrameTable,

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.

I also see getStackTable using getRawProfileSharedData(state).frameTable. Should we replace that as well, or is it fine to leave it that way:

exportconstgetStackTable: Selector<StackTable>=createSelector(
(state: State)=>getRawProfileSharedData(state).stackTable,
(state: State)=>getRawProfileSharedData(state).frameTable,
getCategories,
getDefaultCategory,
computeStackTableFromRawStackTable
);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Oh yeah better to replace it. Doesn't really make a difference at the moment but it might make a difference once we start using typed arrays for the frameTable's category/subcategory columns. Thanks for catching that.

address: Array<Address | -1>;
inlineDepth: number[];
// Differs from RawFrameTable: always Int32Array (-1 sentinel preserved).
address: Int32Array<ArrayBuffer>;

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.

Hm, I think we are reducing the address relative space now that we use Int32Array. I think now we can only keep ~2GB relative space compared to what we had before. Probably that's fine though? What do you think? I guess BigInt64Array would bring a performance hit also for this case?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Hmm that's true, 2GiB is somewhat restrictive. These addresses are always library-relative addresses of an instruction, so the 2GiB only becomes a problem if your binary contains a lot of code; for a Linux debug build of libxul.so, the highest address in an executable section is currently 0xe7160b0 which is 231MiB. For a Linux opt build it's 173MiB.

Samply's symbolication code uses u32 for relative addresses, so it can go up to 4GiB.

We have other frame columns where it would be annoying to use -1 for null, and I'm not really sure what to do about it. I was thinking of adding a flags column where we'd have a flag bit for HAS_CATEGORY, for example. If we do that, we could have a HAS_ADDRESS flag as well, and then make the address column a Uint32Array and go up to 4GiB.

I'm going to go ahead with the 2GiB restriction for now, and we can always change the format once people run into it.

We already have this split for the SamplesTable, but not yet for the
other tables. Having it for all tables means that SamplesLikeTable can
always be one of the derived tables.
The goal is to make the derived SamplesTable have a Float64Array for the
time column, and for the raw tables to allow both number[] and Float64Array
for their time or timeDeltas columns. This will be easier once
SamplesLikeTable is always a derived table.
The following derived tables now use `Float64Array` for their `time` column:
- `SamplesTable` (derived samples)
- `CounterSamplesTable`
- `JsAllocationsTable` and `UnbalancedNativeAllocationsTable`
(derived allocations, introduced by the previous commit)
- `SamplesLikeTable`
The raw tables still use `number[]`, as before, so the profile format is unchanged.
Same principle as what we've done for the stack table and the samples table.
The goal is to have the columns in the derived version always be typed arrays,
and the raw ones can take either a typed array or a plain array.
This commit doesn't introduce any differences between the raw and derived
frame table; the two are identical for now.
Specifically:
- `func` as Int32Array
- `address` as Int32Array (already uses -1 for "no address")
- `inlineDepth` as a Uint8Array.
The raw frame table is unchanged, so this does not affect the profile format.
Similar to what we've done for the raw stack table builder:
The builder always has plain arrays so that we can add frames
one by one by pushing to the column arrays.
…tables.
Same idea as with the other builders.
@mstange
mstange merged commit 5ffe961 into firefox-devtools:mainJul 10, 2026
23 checks passed
mstange added a commit that referenced this pull request Jul 13, 2026
…r-edit (#6167)
<!-- profiler-preview-links:start -->
[Main](https://main--perf-html.netlify.app/) | [Deploy
preview](https://deploy-preview-6167--perf-html.netlify.app/)
<!-- profiler-preview-links:end -->
profiler-edit runs profile compacting on the output profile, and profile
compacting converts some columns to their typed array form but not
others - it only touches columns which contain indexes which refer to
other tables. So this adds a separate pass over the profile to "optimize
the profile for storage".
We'll be able to use this new function for the "upload profile" code
path once we switch that to uploading JSLB files; before we make that
change, converting to typed arrays would be a waste because serializing
to JSON would need to convert them back to regular arrays again.
I had these patches applied when I generated the "after" profile in
#6139 (comment)
- without this, profiler-edit would have left most of those columns
alone and the size profile wouldn't have looked much different.
@canovacanova mentioned this pull request Jul 21, 2026
canova added a commit that referenced this pull request Jul 21, 2026
Changes:
[Sky Ning] Skip preview links for non-main PRs (#6161)
[spokodev] fix(gecko-upgrade): don't crash on a counter with empty
sample_groups (#6160)
[fatadel] Show counter values over time in profiler-cli (#6136)
[Markus Stange] Make profile-conversion snapshots more compact and
meaningful (#6152)
[Markus Stange] More typed arrays: sample + counter times, some
frametable columns (#6139)
[Nazım Can Altınova] Only render a marker url field as a link when the
whole value is a URL (#6163)
[fatadel] Show each counter's owning process in profiler-cli (#6164)
[Nazım Can Altınova] Document the pre-existing thread info and network
JSON schemas in the cli (#6171)
[Markus Stange] Copy column contents in
getRawSamplesTableBuilderFromExisting for consistency (#6168)
[Markus Stange] Convert eligible columns to typed arrays when outputting
from profiler-edit (#6167)
[Markus Stange] Remove unused samples.thread column (#6151)
[Markus Stange] Fixed botched merge which broke 'yarn ts' (#6174)
[Nazım Can Altınova] Add marker handles to `profiler-cli thread network`
(#6172)
[Markus Stange] Update json-slabs 0.3.0 → 0.4.0 (major) (#6176)
[Nazım Can Altınova] Surface network activity across profiler-cli
(#6175)
[Nazım Can Altınova] Add `profile meta` command to profiler-cli (#6177)
[Markus Stange] Allow raw marker table's `startTime` and `endTime`
columns to be Float64Array (#6169)
[nightcityblade] Fix light theme text selection colors (#6186)
[Nazım Can Altınova] Import source map URLs from Chrome DevTools traces
(#6190)
[Nazım Can Altınova] Rename yarn `build-profiler-cli` script to
`build-cli` (#6191)
[Nazım Can Altınova] Migrate husky to version 9 (#6201)
[Nazım Can Altınova] Fix horizontal overflow when the transform
navigator is long (#6199)
[fatadel] Add a 'hexadecimal' marker schema field format (#6197)
[Nazım Can Altınova] Bump source-map to 0.8.0 and remove the old type
workaround (#6202)
[Nazım Can Altınova] 🔃 Sync: l10n -> main (July 21, 2026) (#6209)
And special thanks to our localizers:
fr: parmegiani.thomas
fr: Théo Chevalier
sr: Марко Костић (Marko Kostić)
sv-SE: Luna Jernberg
tr: Grk
zh-CN: Ariel
zh-CN: Olvcpr423
Sign up for freeto 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

@mstange@canova