From 2e5e2567a56ae9a62a6eada8b0a8f7aff7109d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Qu=C3=A8ze?= Date: Wed, 31 May 2023 06:40:36 +0200 Subject: [PATCH] Use the meta.profilingStartTime and meta.profilingEndTime fields to decide the profile root range. --- locales/en-US/app.ftl | 3 + src/components/app/MenuButtons/MetaInfo.js | 32 +- src/components/app/WindowTitle.js | 4 +- src/profile-logic/process-profile.js | 9 +- src/profile-logic/profile-data.js | 9 + src/profile-logic/sanitize.js | 6 + src/test/components/MenuButtons.test.js | 15 + .../__snapshots__/MenuButtons.test.js.snap | 402 +++++++++++++++++- src/test/fixtures/profiles/gecko-profile.js | 2 + src/test/unit/process-profile.test.js | 28 ++ src/test/unit/sanitize.test.js | 6 + src/types/gecko-profile.js | 6 + src/types/profile.js | 7 +- 13 files changed, 519 insertions(+), 10 deletions(-) diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index f9155a7ad7..5fb9160452 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -506,6 +506,8 @@ MenuButtons--metaInfo--logical-cpu = *[other] { $logicalCPUs } logical cores } +MenuButtons--metaInfo--profiling-started = Recording started: +MenuButtons--metaInfo--profiling-session = Recording length: MenuButtons--metaInfo--main-process-started = Main process started: MenuButtons--metaInfo--main-process-ended = Main process ended: MenuButtons--metaInfo--interval = Interval: @@ -525,6 +527,7 @@ MenuButtons--metaInfo--buffer-duration-seconds = MenuButtons--metaInfo--buffer-duration-unlimited = Unlimited MenuButtons--metaInfo--application = Application MenuButtons--metaInfo--name-and-version = Name and version: +MenuButtons--metaInfo--application-uptime = Uptime: MenuButtons--metaInfo--update-channel = Update channel: MenuButtons--metaInfo--build-id = Build ID: MenuButtons--metaInfo--build-type = Build type: diff --git a/src/components/app/MenuButtons/MetaInfo.js b/src/components/app/MenuButtons/MetaInfo.js index d21524fbf6..1893b0cdc6 100644 --- a/src/components/app/MenuButtons/MetaInfo.js +++ b/src/components/app/MenuButtons/MetaInfo.js @@ -218,7 +218,27 @@ class MetaInfoPanelImpl extends React.PureComponent { return ( <>
- {meta.startTime ? ( + {meta.profilingStartTime !== undefined ? ( +
+ + + Recording started: + + + {_formatDate(meta.startTime + meta.profilingStartTime)} +
+ ) : null} + {meta.profilingStartTime !== undefined && meta.profilingEndTime ? ( +
+ + + Recording length: + + + {formatTimestamp(meta.profilingEndTime - meta.profilingStartTime)} +
+ ) : null} + {meta.profilingStartTime === undefined && meta.startTime ? (
@@ -310,6 +330,16 @@ class MetaInfoPanelImpl extends React.PureComponent { {formatProductAndVersion(meta)}
) : null} + {meta.profilingStartTime ? ( +
+ + + Uptime: + + + {formatTimestamp(meta.profilingStartTime)} +
+ ) : null} {meta.updateChannel ? (
diff --git a/src/components/app/WindowTitle.js b/src/components/app/WindowTitle.js index 0913ec8a51..af330b0fbb 100644 --- a/src/components/app/WindowTitle.js +++ b/src/components/app/WindowTitle.js @@ -71,7 +71,9 @@ class WindowTitleImpl extends PureComponent { if (formattedMetaInfoString) { title += formattedMetaInfoString + SEPARATOR; } - title += _formatDateTime(meta.startTime); + title += _formatDateTime( + meta.startTime + (meta.profilingStartTime || 0) + ); if (dataSource === 'public') { title += ` (${dataSource})`; } diff --git a/src/profile-logic/process-profile.js b/src/profile-logic/process-profile.js index 7f2d2258ab..4406e24bb1 100644 --- a/src/profile-logic/process-profile.js +++ b/src/profile-logic/process-profile.js @@ -1508,7 +1508,7 @@ export function processGeckoProfile(geckoProfile: GeckoProfile): Profile { pages = pages.concat(subprocessProfile.pages || []); } - const meta = { + const meta: ProfileMeta = { interval: geckoProfile.meta.interval, startTime: geckoProfile.meta.startTime, abi: geckoProfile.meta.abi, @@ -1544,6 +1544,11 @@ export function processGeckoProfile(geckoProfile: GeckoProfile): Profile { device: geckoProfile.meta.device, }; + if (geckoProfile.meta.profilingStartTime !== undefined) { + meta.profilingStartTime = geckoProfile.meta.profilingStartTime; + meta.profilingEndTime = geckoProfile.meta.profilingEndTime; + } + const profilerOverhead: ProfilerOverhead[] = nullableProfilerOverhead.reduce( (acc, overhead) => { if (overhead !== null) { @@ -1578,7 +1583,7 @@ export function processGeckoProfile(geckoProfile: GeckoProfile): Profile { const jsTracerThread = convertJsTracerToThread( thread, jsTracer, - meta.categories + geckoProfile.meta.categories ); jsTracerThread.isJsTracer = true; jsTracerThread.name = `JS Tracer of ${friendlyThreadName}`; diff --git a/src/profile-logic/profile-data.js b/src/profile-logic/profile-data.js index f13ff60f5d..65039b31d6 100644 --- a/src/profile-logic/profile-data.js +++ b/src/profile-logic/profile-data.js @@ -919,6 +919,15 @@ export function getTimeRangeIncludingAllThreads( profile: Profile ): StartEndRange { const completeRange = { start: Infinity, end: -Infinity }; + if ( + profile.meta.profilingStartTime !== undefined && + profile.meta.profilingEndTime + ) { + return { + start: profile.meta.profilingStartTime, + end: profile.meta.profilingEndTime, + }; + } profile.threads.forEach((thread) => { const threadRange = memoizedGetTimeRangeForThread( thread, diff --git a/src/profile-logic/sanitize.js b/src/profile-logic/sanitize.js index 1b0267b205..eb02b75093 100644 --- a/src/profile-logic/sanitize.js +++ b/src/profile-logic/sanitize.js @@ -191,6 +191,12 @@ export function sanitizePII( : undefined, }; + if (PIIToBeRemoved.shouldFilterToCommittedRange !== null) { + const { start, end } = PIIToBeRemoved.shouldFilterToCommittedRange; + newProfile.meta.profilingStartTime = start; + newProfile.meta.profilingEndTime = end; + } + return { profile: newProfile, // Note that the profile was sanitized. diff --git a/src/test/components/MenuButtons.test.js b/src/test/components/MenuButtons.test.js index 4b8d10db88..e1933fb632 100644 --- a/src/test/components/MenuButtons.test.js +++ b/src/test/components/MenuButtons.test.js @@ -524,6 +524,21 @@ describe('app/MenuButtons', function () { expect(getMetaInfoPanel()).toMatchSnapshot(); }); + it('matches the snapshot with uptime', async () => { + // Using gecko profile because it has metadata and profilerOverhead data in it. + const profile = processGeckoProfile(createGeckoProfile()); + // The profiler was started 500ms after the parent process. + profile.meta.profilingStartTime = 500; + + const { displayMetaInfoPanel, getMetaInfoPanel } = + await setupForMetaInfoPanel(profile); + await displayMetaInfoPanel(); + + const uptime = ensureExists(screen.getByText(/Uptime:/).nextSibling); + expect(uptime).toHaveTextContent('500ms'); + expect(getMetaInfoPanel()).toMatchSnapshot(); + }); + it('with no statistics object should not make the app crash', async () => { // Using gecko profile because it has metadata and profilerOverhead data in it. const profile = processGeckoProfile(createGeckoProfile()); diff --git a/src/test/components/__snapshots__/MenuButtons.test.js.snap b/src/test/components/__snapshots__/MenuButtons.test.js.snap index 099244be1e..4d8bf7d7e9 100644 --- a/src/test/components/__snapshots__/MenuButtons.test.js.snap +++ b/src/test/components/__snapshots__/MenuButtons.test.js.snap @@ -415,10 +415,20 @@ exports[`app/MenuButtons matches the snapshot 1`] = ` - Main process started: + Recording started: toLocaleString Sat, 09 Apr 2016 17:02:32 GMT
+
+ + Recording length: + + 1.007s +
@@ -804,10 +814,20 @@ exports[`app/MenuButtons matches the snapshot with device inform - Main process started: + Recording started: toLocaleString Sat, 09 Apr 2016 17:02:32 GMT
+
+ + Recording length: + + 1.007s +
@@ -1132,6 +1152,368 @@ exports[`app/MenuButtons matches the snapshot with device inform
`; +exports[`app/MenuButtons matches the snapshot with uptime 1`] = ` +
+
+
+

+ Profile Information +

+
+
+ + Recording started: + + toLocaleString Sat, 09 Apr 2016 17:02:33 GMT +
+
+ + Recording length: + + 507ms +
+
+ + Interval: + + 1ms +
+
+ + Buffer capacity: + + 8MB +
+
+ + Buffer duration: + + Unlimited +
+
+
+ + Symbols: + + Profile is not symbolicated +
+
+ + +
+
+

+ Application +

+
+
+ + Name and version: + + Firefox 48 +
+
+ + Uptime: + + 500ms +
+
+ + Update channel: + + nightly +
+
+ + Build ID: + + 20181126165837 +
+
+ + Build type: + + Debug +
+
+ + Extensions: + +
    +
  • + Firefox Screenshots +
  • +
  • + Form Autofill +
  • +
  • + Gecko Profiler +
  • +
+
+
+

+ Platform +

+
+
+ + OS: + + macOS 10.11 +
+
+ + ABI: + + x86_64-gcc3 +
+
+ + CPU cores: + + ⁨⁨4⁩ physical cores⁩, ⁨⁨8⁩ logical cores⁩ +
+
+
+ + ⁨Profiler⁩ overhead + +
+
+
+
+ Mean +
+
+ Max +
+
+ Min +
+
+ Overhead +
+
+ 227μs +
+
+ 410μs +
+
+ 38μs +
+
+ Cleaning +
+
+ 54μs +
+
+ 100μs +
+
+ 7.0μs +
+
+ Counter +
+
+ 59μs +
+
+ 105μs +
+
+ 12μs +
+
+ Interval +
+
+ 857μs +
+
+ 1,000μs +
+
+ 0.000μs +
+
+ Lockings +
+
+ 49μs +
+
+ 95μs +
+
+ 2.0μs +
+
+
+ + Overhead durations: + + + 1,586μs + +
+
+ + Overhead percentage: + + + 26,433% + +
+
+ + Profiled duration: + + + 6.0μs + +
+
+
+
+
+`; + exports[`app/MenuButtons with more extra info, opens more info section if clicked 1`] = `
with no statistics object should not ma - Main process started: + Recording started: toLocaleString Sat, 09 Apr 2016 17:02:32 GMT
+
+ + Recording length: + + 1.007s +
@@ -1819,7 +2211,7 @@ exports[`app/MenuButtons matches the snapshot for the menu buttons and class="menuButtonsDownloadSize" > ( - 1.55 kB + 1.57 kB ) @@ -2050,7 +2442,7 @@ exports[`app/MenuButtons matches the snapshot for the opened panel for class="menuButtonsDownloadSize" > ( - 1.55 kB + 1.57 kB ) diff --git a/src/test/fixtures/profiles/gecko-profile.js b/src/test/fixtures/profiles/gecko-profile.js index 588dcfaf70..8704b5d990 100644 --- a/src/test/fixtures/profiles/gecko-profile.js +++ b/src/test/fixtures/profiles/gecko-profile.js @@ -195,6 +195,8 @@ export function createGeckoProfile(): GeckoProfile { stackwalk: 1, debug: 1, startTime: 1460221352723.438, + profilingStartTime: 0, + profilingEndTime: 1007, shutdownTime: 1560221352723, toolkit: 'cocoa', version: GECKO_PROFILE_VERSION, diff --git a/src/test/unit/process-profile.test.js b/src/test/unit/process-profile.test.js index 5615bd0371..d94efaa3b3 100644 --- a/src/test/unit/process-profile.test.js +++ b/src/test/unit/process-profile.test.js @@ -677,6 +677,34 @@ describe('profile meta processing', function () { // Checking if it keeps the sampleUnits object. expect(processedMeta.sampleUnits).toEqual(geckoMeta.sampleUnits); }); + + it('keeps the profilingStartTime and profilingEndTime', function () { + const geckoProfile = createGeckoProfile(); + const geckoMeta = geckoProfile.meta; + + // Processing the profile. + const processedProfile = processGeckoProfile(geckoProfile); + const processedMeta = processedProfile.meta; + + expect(processedMeta.profilingStartTime).toEqual( + geckoMeta.profilingStartTime + ); + expect(processedMeta.profilingEndTime).toEqual(geckoMeta.profilingEndTime); + }); + + it('does not create the profilingStartTime and profilingEndTime fields', function () { + const geckoProfile = createGeckoProfile(); + const geckoMeta = geckoProfile.meta; + delete geckoMeta.profilingStartTime; + delete geckoMeta.profilingEndTime; + + // Processing the profile. + const processedProfile = processGeckoProfile(geckoProfile); + const processedMeta = processedProfile.meta; + + expect(processedMeta.profilingStartTime).toEqual(undefined); + expect(processedMeta.profilingEndTime).toEqual(undefined); + }); }); describe('visualMetrics processing', function () { diff --git a/src/test/unit/sanitize.test.js b/src/test/unit/sanitize.test.js index 349104e702..fdb316caa5 100644 --- a/src/test/unit/sanitize.test.js +++ b/src/test/unit/sanitize.test.js @@ -186,6 +186,12 @@ describe('sanitizePII', function () { ); } + // Make sure the meta data contains the new profile range + expect(sanitizedProfile.meta.profilingStartTime).toEqual( + sanitizedRange.start + ); + expect(sanitizedProfile.meta.profilingEndTime).toEqual(sanitizedRange.end); + // Make sure that we still have the same number of counters. expect(ensureExists(originalProfile.counters).length).toEqual(1); expect(ensureExists(sanitizedProfile.counters).length).toEqual(1); diff --git a/src/types/gecko-profile.js b/src/types/gecko-profile.js index 413c056746..e9fb92b21c 100644 --- a/src/types/gecko-profile.js +++ b/src/types/gecko-profile.js @@ -303,6 +303,8 @@ export type GeckoProfilerOverhead = {| * */ export type GeckoProfileShortMeta = {| version: number, + // When the main process started. Timestamp expressed in milliseconds since + // midnight January 1, 1970 GMT. startTime: Milliseconds, shutdownTime: Milliseconds | null, categories: CategoryList, @@ -315,6 +317,10 @@ export type GeckoProfileShortMeta = {| * */ export type GeckoProfileFullMeta = {| ...GeckoProfileShortMeta, + // When the recording started (in milliseconds after startTime). + profilingStartTime?: Milliseconds, + // When the recording ended (in milliseconds after startTime). + profilingEndTime?: Milliseconds, interval: Milliseconds, stackwalk: 0 | 1, // This value represents a boolean, but for some reason is written out as an int diff --git a/src/types/profile.js b/src/types/profile.js index 3bd31d7d7c..d321f4f94a 100644 --- a/src/types/profile.js +++ b/src/types/profile.js @@ -750,10 +750,15 @@ export type ExtraProfileInfoSection = {| export type ProfileMeta = {| // The interval at which the threads are sampled. interval: Milliseconds, - // The number of milliseconds since midnight January 1, 1970 GMT. + // When the main process started. Timestamp expressed in milliseconds since + // midnight January 1, 1970 GMT. startTime: Milliseconds, // The number of milliseconds since midnight January 1, 1970 GMT. endTime?: Milliseconds, + // When the recording started (in milliseconds after startTime). + profilingStartTime?: Milliseconds, + // When the recording ended (in milliseconds after startTime). + profilingEndTime?: Milliseconds, // The process type where the Gecko profiler was started. This is the raw enum // numeric value as defined here: // https://searchfox.org/mozilla-central/rev/819cd31a93fd50b7167979607371878c4d6f18e8/xpcom/build/nsXULAppAPI.h#365