diff --git a/docs-developer/CHANGELOG-formats.md b/docs-developer/CHANGELOG-formats.md index b1be78b6bb..50da5c96d4 100644 --- a/docs-developer/CHANGELOG-formats.md +++ b/docs-developer/CHANGELOG-formats.md @@ -6,6 +6,12 @@ Note that this is not an exhaustive list. Processed profile format upgraders can ## Processed profile format +### Version 62 + +A new `display` field of type `CounterDisplayConfig` was added to `RawCounter`. +This metadata makes counters self-describing in terms of how they are rendered in the UI. +For existing profiles, the display config is derived from the counter's `category` and `name`. + ### Version 61 The `SourceTable` in `profile.shared.sources` was updated: diff --git a/src/app-logic/constants.ts b/src/app-logic/constants.ts index f70f544144..14e3185680 100644 --- a/src/app-logic/constants.ts +++ b/src/app-logic/constants.ts @@ -12,7 +12,7 @@ export const GECKO_PROFILE_VERSION = 34; // The current version of the "processed" profile format. // Please don't forget to update the processed profile format changelog in // `docs-developer/CHANGELOG-formats.md`. -export const PROCESSED_PROFILE_VERSION = 61; +export const PROCESSED_PROFILE_VERSION = 62; // The following are the margin sizes for the left and right of the timeline. Independent // components need to share these values. diff --git a/src/profile-logic/process-profile.ts b/src/profile-logic/process-profile.ts index fbf4c99cb5..d95355d18d 100644 --- a/src/profile-logic/process-profile.ts +++ b/src/profile-logic/process-profile.ts @@ -97,6 +97,7 @@ import type { GeckoSourceTable, IndexIntoCategoryList, IndexIntoFrameTable, + CounterDisplayConfig, } from 'firefox-profiler/types'; import { decompress, isGzip } from 'firefox-profiler/utils/gz'; @@ -972,6 +973,61 @@ function _processSamples( return samples; } +/** + * Derive a CounterDisplayConfig from a counter's category and name. + */ +function _deriveCounterDisplay( + category: string, + name: string +): CounterDisplayConfig { + if (category === 'Memory') { + return { + graphType: 'line-accumulated', + unit: 'bytes', + color: 'orange', + markerSchemaLocation: 'timeline-memory', + sortWeight: 20, + label: 'Memory', + }; + } else if (category === 'power') { + return { + graphType: 'line-rate', + unit: 'pWh', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 30, + label: name, + }; + } else if (category === 'Bandwidth') { + return { + graphType: 'line-rate', + unit: 'bytes', + color: 'blue', + markerSchemaLocation: null, + sortWeight: 10, + label: 'Bandwidth', + }; + } else if (category === 'CPU' && name === 'processCPU') { + return { + graphType: 'line-rate', + unit: 'percent', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 40, + label: 'Process CPU', + }; + } + + return { + graphType: 'line-rate', + unit: '', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 50, + label: name, + }; +} + /** * Converts the Gecko list of counters into the processed format. */ @@ -1031,6 +1087,7 @@ function _processCounters( pid: mainThreadPid, mainThreadIndex, samples: adjustTableTimeDeltas(processedCounterSamples, delta), + display: _deriveCounterDisplay(category, name), }); return result; }, diff --git a/src/profile-logic/processed-profile-versioning.ts b/src/profile-logic/processed-profile-versioning.ts index 691380cf78..c6b48dec51 100644 --- a/src/profile-logic/processed-profile-versioning.ts +++ b/src/profile-logic/processed-profile-versioning.ts @@ -3049,6 +3049,66 @@ const _upgraders: { } }, + [62]: (profile: any) => { + // Added CounterDisplayConfig to counters. This metadata controls how a + // counter is rendered (graph type, color, unit, etc.). + // Derive defaults from the counter's category and name. + if (profile.counters) { + for (const counter of profile.counters) { + if (counter.display !== undefined) { + continue; + } + const { category, name } = counter; + if (category === 'Memory') { + counter.display = { + graphType: 'line-accumulated', + unit: 'bytes', + color: 'orange', + markerSchemaLocation: 'timeline-memory', + sortWeight: 20, + label: 'Memory', + }; + } else if (category === 'power') { + counter.display = { + graphType: 'line-rate', + unit: 'pWh', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 30, + label: name, + }; + } else if (category === 'Bandwidth') { + counter.display = { + graphType: 'line-rate', + unit: 'bytes', + color: 'blue', + markerSchemaLocation: null, + sortWeight: 10, + label: 'Bandwidth', + }; + } else if (category === 'CPU' && name === 'processCPU') { + counter.display = { + graphType: 'line-rate', + unit: 'percent', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 40, + label: 'Process CPU', + }; + } else { + counter.display = { + graphType: 'line-rate', + unit: '', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 50, + label: name, + }; + } + } + } + }, + // If you add a new upgrader here, please document the change in // `docs-developer/CHANGELOG-formats.md`. }; diff --git a/src/profile-logic/profile-data.ts b/src/profile-logic/profile-data.ts index 645d8a9cc8..d4e7a5d964 100644 --- a/src/profile-logic/profile-data.ts +++ b/src/profile-logic/profile-data.ts @@ -2307,7 +2307,7 @@ export function processCounter(rawCounter: RawCounter): Counter { color: rawCounter.color, pid: rawCounter.pid, mainThreadIndex: rawCounter.mainThreadIndex, - + display: rawCounter.display, samples, }; diff --git a/src/test/fixtures/profiles/processed-profile.ts b/src/test/fixtures/profiles/processed-profile.ts index 5961d2c0bf..428b559836 100644 --- a/src/test/fixtures/profiles/processed-profile.ts +++ b/src/test/fixtures/profiles/processed-profile.ts @@ -33,6 +33,7 @@ import type { CategoryList, JsTracerTable, RawCounter, + CounterDisplayConfig, TabID, MarkerPayload, NetworkPayload, @@ -1479,6 +1480,18 @@ export function getProfileWithJsTracerEvents( return profile; } +/** + * Default display configuration for test counters. + */ +const DEFAULT_TEST_COUNTER_DISPLAY: CounterDisplayConfig = { + graphType: 'line-rate', + unit: '', + color: 'grey', + markerSchemaLocation: null, + sortWeight: 50, + label: 'My Counter', +}; + /** * Creates a Counter fixture for a given thread. */ @@ -1504,6 +1517,7 @@ export function getCounterForThread( count: sampleTimes.map((_, i) => Math.sin(i)), length: thread.samples.length, }, + display: DEFAULT_TEST_COUNTER_DISPLAY, }; return counter; } @@ -1541,6 +1555,7 @@ export function getCounterForThreadWithSamples( pid: thread.pid, mainThreadIndex, samples: newSamples, + display: DEFAULT_TEST_COUNTER_DISPLAY, }; return counter; } diff --git a/src/test/integration/symbolicator-cli/__snapshots__/symbolicator-cli.test.ts.snap b/src/test/integration/symbolicator-cli/__snapshots__/symbolicator-cli.test.ts.snap index 19dd70789f..3af235db1a 100644 --- a/src/test/integration/symbolicator-cli/__snapshots__/symbolicator-cli.test.ts.snap +++ b/src/test/integration/symbolicator-cli/__snapshots__/symbolicator-cli.test.ts.snap @@ -87,7 +87,7 @@ Object { "markerSchema": Array [], "oscpu": "macOS 14.6.1", "pausedRanges": Array [], - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "a.out", "sampleUnits": Object { @@ -1415,7 +1415,7 @@ Object { "markerSchema": Array [], "oscpu": "macOS 14.6.1", "pausedRanges": Array [], - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "a.out", "sampleUnits": Object { diff --git a/src/test/store/__snapshots__/profile-view.test.ts.snap b/src/test/store/__snapshots__/profile-view.test.ts.snap index f04baf9582..9f9343610e 100644 --- a/src/test/store/__snapshots__/profile-view.test.ts.snap +++ b/src/test/store/__snapshots__/profile-view.test.ts.snap @@ -418,7 +418,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "sourceURL": "", diff --git a/src/test/unit/__snapshots__/profile-conversion.test.ts.snap b/src/test/unit/__snapshots__/profile-conversion.test.ts.snap index 6a5e04368e..b804fe58c0 100644 --- a/src/test/unit/__snapshots__/profile-conversion.test.ts.snap +++ b/src/test/unit/__snapshots__/profile-conversion.test.ts.snap @@ -591,7 +591,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "ART Trace (Android)", "sampleUnits": undefined, @@ -79192,7 +79192,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "ART Trace (Android)", "sampleUnits": undefined, @@ -315562,7 +315562,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "profilingEndTime": 119159778.026, @@ -350479,7 +350479,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "profilingEndTime": 119159778.026, @@ -385375,7 +385375,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "profilingEndTime": 66155012.423, @@ -387980,7 +387980,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "sourceURL": "", @@ -389809,7 +389809,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "profilingEndTime": 355035987.653, @@ -393482,7 +393482,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "sourceURL": "", @@ -398697,7 +398697,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Chrome Trace", "profilingEndTime": 66155012.423, @@ -399739,7 +399739,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "sampleUnits": undefined, @@ -403614,7 +403614,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "sampleUnits": undefined, @@ -418512,7 +418512,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "sampleUnits": undefined, @@ -424719,7 +424719,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "sampleUnits": undefined, @@ -441164,7 +441164,7 @@ Object { "keepProfileThreadOrder": true, "markerSchema": Array [], "platform": "Android", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "com.example.sampleapplication", "sourceCodeIsNotOnSearchfox": true, @@ -498819,7 +498819,7 @@ Object { "keepProfileThreadOrder": true, "markerSchema": Array [], "platform": "Android", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "com.example.sampleapplication", "sourceCodeIsNotOnSearchfox": true, @@ -561079,7 +561079,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "target/debug/examples/work_log (dhat)", "sourceURL": "", @@ -563127,7 +563127,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Flamegraph", "sourceURL": "", @@ -871013,7 +871013,7 @@ Object { "oscpu": "", "physicalCPUs": 0, "platform": "", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Flamegraph", "sourceURL": "", diff --git a/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap b/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap index e139904c6d..e85d4f0300 100644 --- a/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap +++ b/src/test/unit/__snapshots__/profile-upgrading.test.ts.snap @@ -40,7 +40,7 @@ Object { "oscpu": undefined, "physicalCPUs": undefined, "platform": undefined, - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "sampleUnits": undefined, @@ -7358,7 +7358,7 @@ Object { "misc": "rv:48.0", "oscpu": "Intel Mac OS X 10.11", "platform": "Macintosh", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "stackwalk": 1, @@ -8693,7 +8693,7 @@ Object { "misc": "rv:48.0", "oscpu": "Intel Mac OS X 10.11", "platform": "Macintosh", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "stackwalk": 1, @@ -9693,6 +9693,14 @@ Object { Object { "category": "Memory", "description": "Amount of allocated memory", + "display": Object { + "color": "orange", + "graphType": "line-accumulated", + "label": "Memory", + "markerSchemaLocation": "timeline-memory", + "sortWeight": 20, + "unit": "bytes", + }, "mainThreadIndex": 0, "name": "malloc", "pid": "11111", @@ -10155,7 +10163,7 @@ Object { "misc": "rv:48.0", "oscpu": "Intel Mac OS X 10.11", "platform": "Macintosh", - "preprocessedProfileVersion": 61, + "preprocessedProfileVersion": 62, "processType": 0, "product": "Firefox", "stackwalk": 1, diff --git a/src/types/profile-derived.ts b/src/types/profile-derived.ts index f52454fd9e..e1a3802aa6 100644 --- a/src/types/profile-derived.ts +++ b/src/types/profile-derived.ts @@ -33,6 +33,7 @@ import type { IndexIntoFrameTable, SourceTable, IndexIntoSourceTable, + CounterDisplayConfig, } from './profile'; import type { IndexedArray } from './utils'; import type { BitSet } from '../utils/bitset'; @@ -191,6 +192,7 @@ export type Counter = { pid: Pid; mainThreadIndex: ThreadIndex; samples: CounterSamplesTable; + display: CounterDisplayConfig; }; /** diff --git a/src/types/profile.ts b/src/types/profile.ts index 90486b7ecd..70e2ba91d1 100644 --- a/src/types/profile.ts +++ b/src/types/profile.ts @@ -529,6 +529,27 @@ export type GraphColor = | 'teal' | 'yellow'; +export type CounterGraphType = 'line-accumulated' | 'line-rate'; + +/** + * Specifies how a counter should be displayed in the UI. + */ +export type CounterDisplayConfig = { + graphType: CounterGraphType; + unit: string; + color: GraphColor; + // The marker schema display location to filter markers for this track, + // e.g., "timeline-memory". If null, no markers are shown. + markerSchemaLocation: string | null; + // Controls the default display position of this counter track relative to + // other tracks. Tracks with lower values appear closer to the top. + sortWeight: number; + // The human-readable label shown in the track sidebar. For known counter + // types this is a friendly name (eg, "Memory"); for generic counters + // it falls back to counter.name. + label: string; +}; + export type RawCounter = { name: string; category: string; @@ -537,6 +558,7 @@ export type RawCounter = { pid: Pid; mainThreadIndex: ThreadIndex; samples: RawCounterSamplesTable; + display: CounterDisplayConfig; }; /**