Uh oh!
There was an error while loading. Please reload this page.
More typed arrays: sample + counter times, some frametable columns - #6139
Conversation
Codecov Report❌ Patch coverage is 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. 🚀 New features to boost your workflow:
|
f7c1d0c to
fcdcf3dCompare0c3feb0 to
3b38bd6Comparecanova
commented
Jul 10, 2026
Curious, is there a size profile from after? |
mstange
commented
Jul 10, 2026
Before: https://share.firefox.dev/4peCGi7 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: |
canova
commented
Jul 10, 2026
Nice, thanks for the links! |
canova
left a comment
There was a problem hiding this comment.
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?
| raw: RawJsAllocationsTable | ||
| ): JsAllocationsTable { | ||
| return { | ||
| time: Float64Array.from(raw.time), |
There was a problem hiding this comment.
This will copy if raw.time is already a Float64Array, right? Can we avoid copying for that case here and below?
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
I also see getStackTable using getRawProfileSharedData(state).frameTable. Should we replace that as well, or is it fine to leave it that way:
profiler/src/selectors/profile.ts
Lines 278 to 284 in 3d4d114
There was a problem hiding this comment.
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>; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
Uh oh!
There was an error while loading. Please reload this page.
…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.
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
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.