diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni index 08ef22ae3f..a5ae1f2ddf 100644 --- a/config/gni/devtools_grd_files.gni +++ b/config/gni/devtools_grd_files.gni @@ -503,8 +503,8 @@ grd_files_release_sources = [ "front_end/panels/issues/components/components.js", "front_end/panels/issues/issues-meta.js", "front_end/panels/issues/issues.js", - "front_end/panels/js_profiler/js_profiler-meta.js", - "front_end/panels/js_profiler/js_profiler.js", + "front_end/panels/js_timeline/js_timeline-meta.js", + "front_end/panels/js_timeline/js_timeline.js", "front_end/panels/layer_viewer/layer_viewer-meta.js", "front_end/panels/layer_viewer/layer_viewer.js", "front_end/panels/layers/layers-meta.js", @@ -1418,8 +1418,6 @@ grd_files_debug_sources = [ "front_end/panels/performance_monitor/PerformanceMonitor.js", "front_end/panels/performance_monitor/performanceMonitor.css.js", "front_end/panels/profiler/BottomUpProfileDataGrid.js", - "front_end/panels/profiler/CPUProfileFlameChart.js", - "front_end/panels/profiler/CPUProfileView.js", "front_end/panels/profiler/ChildrenProvider.js", "front_end/panels/profiler/HeapProfileView.js", "front_end/panels/profiler/HeapProfilerPanel.js", @@ -1432,6 +1430,7 @@ grd_files_debug_sources = [ "front_end/panels/profiler/LiveHeapProfileView.js", "front_end/panels/profiler/ModuleUIStrings.js", "front_end/panels/profiler/ProfileDataGrid.js", + "front_end/panels/profiler/ProfileFlameChartDataProvider.js", "front_end/panels/profiler/ProfileHeader.js", "front_end/panels/profiler/ProfileLauncherView.js", "front_end/panels/profiler/ProfileSidebarTreeElement.js", diff --git a/front_end/BUILD.gn b/front_end/BUILD.gn index 85926fd08b..d79c680097 100644 --- a/front_end/BUILD.gn +++ b/front_end/BUILD.gn @@ -164,7 +164,6 @@ group("unittests") { "panels/network:unittests", "panels/network/components:unittests", "panels/performance_monitor:unittests", - "panels/profiler:unittests", "panels/protocol_monitor:unittests", "panels/protocol_monitor/components:unittests", "panels/recorder:unittests", diff --git a/front_end/core/host/UserMetrics.ts b/front_end/core/host/UserMetrics.ts index b3600a81d0..14a364f988 100644 --- a/front_end/core/host/UserMetrics.ts +++ b/front_end/core/host/UserMetrics.ts @@ -699,8 +699,6 @@ export enum PanelWithLocation { 'sources.search-drawer' = 28, 'security-main' = 29, 'security-drawer' = 30, - 'js_profiler-main' = 31, - 'js_profiler-drawer' = 32, 'lighthouse-main' = 33, 'lighthouse-drawer' = 34, 'coverage-main' = 35, diff --git a/front_end/entrypoints/js_app/BUILD.gn b/front_end/entrypoints/js_app/BUILD.gn index a917511e25..c44a7a352b 100644 --- a/front_end/entrypoints/js_app/BUILD.gn +++ b/front_end/entrypoints/js_app/BUILD.gn @@ -13,7 +13,7 @@ devtools_entrypoint("entrypoint") { "../../core/i18n:bundle", "../../core/sdk:bundle", "../../generated:protocol", - "../../panels/js_profiler:meta", + "../../panels/js_timeline:meta", "../../panels/mobile_throttling:meta", "../../ui/legacy/components/utils:bundle", "../main:bundle", diff --git a/front_end/entrypoints/js_app/js_app.ts b/front_end/entrypoints/js_app/js_app.ts index 3cffc5cf7f..e708b8bf24 100644 --- a/front_end/entrypoints/js_app/js_app.ts +++ b/front_end/entrypoints/js_app/js_app.ts @@ -3,7 +3,7 @@ // found in the LICENSE file. import '../shell/shell.js'; -import '../../panels/js_profiler/js_profiler-meta.js'; +import '../../panels/js_timeline/js_timeline-meta.js'; import '../../panels/mobile_throttling/mobile_throttling-meta.js'; import * as Common from '../../core/common/common.js'; diff --git a/front_end/entrypoints/node_app/BUILD.gn b/front_end/entrypoints/node_app/BUILD.gn index 939cb0b892..a9adb463d2 100644 --- a/front_end/entrypoints/node_app/BUILD.gn +++ b/front_end/entrypoints/node_app/BUILD.gn @@ -36,7 +36,7 @@ devtools_entrypoint("entrypoint") { ":node_app", "../../core/i18n:bundle", "../../core/root:bundle", - "../../panels/js_profiler:meta", + "../../panels/js_timeline:meta", "../../panels/mobile_throttling:meta", "../../panels/sources:bundle", "../../ui/legacy:bundle", diff --git a/front_end/entrypoints/node_app/node_app.ts b/front_end/entrypoints/node_app/node_app.ts index e27e34a8d0..37f64ef7c9 100644 --- a/front_end/entrypoints/node_app/node_app.ts +++ b/front_end/entrypoints/node_app/node_app.ts @@ -3,16 +3,17 @@ // found in the LICENSE file. import '../shell/shell.js'; import '../../panels/mobile_throttling/mobile_throttling-meta.js'; -import '../../panels/js_profiler/js_profiler-meta.js'; -import type * as Sources from '../../panels/sources/sources.js'; -import * as i18n from '../../core/i18n/i18n.js'; -import * as UI from '../../ui/legacy/legacy.js'; +import '../../panels/js_timeline/js_timeline-meta.js'; + import * as Common from '../../core/common/common.js'; +import * as i18n from '../../core/i18n/i18n.js'; import * as Root from '../../core/root/root.js'; +import type * as Sources from '../../panels/sources/sources.js'; +import * as UI from '../../ui/legacy/legacy.js'; import * as Main from '../main/main.js'; -import {NodeMainImpl} from './NodeMain.js'; // eslint-disable-line rulesdir/es_modules_import import {NodeConnectionsPanel} from './NodeConnectionsPanel.js'; // eslint-disable-line rulesdir/es_modules_import +import {NodeMainImpl} from './NodeMain.js'; // eslint-disable-line rulesdir/es_modules_import const UIStrings = { /** diff --git a/front_end/legacy_test_runner/BUILD.gn b/front_end/legacy_test_runner/BUILD.gn index 5d1b4ca6b4..a47edc5a3a 100644 --- a/front_end/legacy_test_runner/BUILD.gn +++ b/front_end/legacy_test_runner/BUILD.gn @@ -36,7 +36,6 @@ group("legacy_test_runner-resources") { "bindings_test_runner:bundle", "console_test_runner:bundle", "coverage_test_runner:bundle", - "cpu_profiler_test_runner:bundle", "data_grid_test_runner:bundle", "device_mode_test_runner:bundle", "elements_test_runner:bundle", diff --git a/front_end/legacy_test_runner/cpu_profiler_test_runner/BUILD.gn b/front_end/legacy_test_runner/cpu_profiler_test_runner/BUILD.gn deleted file mode 100644 index d50898a403..0000000000 --- a/front_end/legacy_test_runner/cpu_profiler_test_runner/BUILD.gn +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2020 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("../../../scripts/build/ninja/copy.gni") - -group("bundle") { - public_deps = [ ":gen" ] - - data_deps = [ ":gen" ] -} - -copy_to_gen("gen") { - sources = [ "cpu_profiler_test_runner.js" ] -} diff --git a/front_end/legacy_test_runner/cpu_profiler_test_runner/cpu_profiler_test_runner.js b/front_end/legacy_test_runner/cpu_profiler_test_runner/cpu_profiler_test_runner.js deleted file mode 100644 index 4b3946e0c9..0000000000 --- a/front_end/legacy_test_runner/cpu_profiler_test_runner/cpu_profiler_test_runner.js +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import * as Profiler from '../../panels/profiler/profiler.js'; -import {TestRunner} from '../test_runner/test_runner.js'; - -/** - * @fileoverview using private properties isn't a Closure violation in tests. - */ -export const CPUProfilerTestRunner = {}; - -CPUProfilerTestRunner.startProfilerTest = function(callback) { - TestRunner.addResult('Profiler was enabled.'); - TestRunner.addSniffer( - Profiler.ProfilesPanel.JSProfilerPanel.instance(), 'addProfileHeader', CPUProfilerTestRunner.profileHeaderAdded, - true); - TestRunner.addSniffer( - Profiler.ProfileView.ProfileView.prototype, 'refresh', CPUProfilerTestRunner.profileViewRefresh, true); - TestRunner.safeWrap(callback)(); -}; - -CPUProfilerTestRunner.completeProfilerTest = function() { - TestRunner.addResult(''); - TestRunner.addResult('Profiler was disabled.'); - TestRunner.completeTest(); -}; - -CPUProfilerTestRunner.runProfilerTestSuite = function(testSuite) { - const testSuiteTests = testSuite.slice(); - - function runner() { - if (!testSuiteTests.length) { - CPUProfilerTestRunner.completeProfilerTest(); - return; - } - - const nextTest = testSuiteTests.shift(); - TestRunner.addResult(''); - TestRunner.addResult( - 'Running: ' + - /function\s([^(]*)/.exec(nextTest)[1]); - TestRunner.safeWrap(nextTest)(runner, runner); - } - - CPUProfilerTestRunner.startProfilerTest(runner); -}; - -CPUProfilerTestRunner.showProfileWhenAdded = function(title) { - CPUProfilerTestRunner.showProfileWhenAdded = title; -}; - -CPUProfilerTestRunner.profileHeaderAdded = function(profile) { - if (CPUProfilerTestRunner.showProfileWhenAdded === profile.title) { - Profiler.ProfilesPanel.JSProfilerPanel.instance().showProfile(profile); - } -}; - -CPUProfilerTestRunner.waitUntilProfileViewIsShown = function(title, callback) { - callback = TestRunner.safeWrap(callback); - const profilesPanel = Profiler.ProfilesPanel.JSProfilerPanel.instance(); - - if (profilesPanel.visibleView && profilesPanel.visibleView.profile && - profilesPanel.visibleView.profileHeader.title === title) { - callback(profilesPanel.visibleView); - } else { - CPUProfilerTestRunner.waitUntilProfileViewIsShownCallback = {title: title, callback: callback}; - } -}; - -CPUProfilerTestRunner.profileViewRefresh = function() { - if (CPUProfilerTestRunner.waitUntilProfileViewIsShownCallback && - CPUProfilerTestRunner.waitUntilProfileViewIsShownCallback.title === this.profileHeader.title) { - const callback = CPUProfilerTestRunner.waitUntilProfileViewIsShownCallback; - delete CPUProfilerTestRunner.waitUntilProfileViewIsShownCallback; - callback.callback(this); - } -}; diff --git a/front_end/panels/js_profiler/BUILD.gn b/front_end/panels/js_timeline/BUILD.gn similarity index 75% rename from front_end/panels/js_profiler/BUILD.gn rename to front_end/panels/js_timeline/BUILD.gn index 1dbd39429d..716acd62bd 100644 --- a/front_end/panels/js_profiler/BUILD.gn +++ b/front_end/panels/js_timeline/BUILD.gn @@ -7,7 +7,7 @@ import("../../../scripts/build/ninja/devtools_module.gni") import("../visibility.gni") devtools_entrypoint("bundle") { - entrypoint = "js_profiler.ts" + entrypoint = "js_timeline.ts" deps = [] @@ -20,15 +20,11 @@ devtools_entrypoint("bundle") { } devtools_entrypoint("meta") { - entrypoint = "js_profiler-meta.ts" + entrypoint = "js_timeline-meta.ts" deps = [ ":bundle", - "../../core/i18n:bundle", - "../../core/root:bundle", - "../../panels/profiler:bundle", "../../panels/timeline:bundle", - "../../ui/legacy:bundle", ] visibility = [ "../../entrypoints/*" ] diff --git a/front_end/panels/js_profiler/DIR_METADATA b/front_end/panels/js_timeline/DIR_METADATA similarity index 100% rename from front_end/panels/js_profiler/DIR_METADATA rename to front_end/panels/js_timeline/DIR_METADATA diff --git a/front_end/panels/js_profiler/js_profiler-meta.ts b/front_end/panels/js_timeline/js_timeline-meta.ts similarity index 96% rename from front_end/panels/js_profiler/js_profiler-meta.ts rename to front_end/panels/js_timeline/js_timeline-meta.ts index a57836a5bc..1f11c4f0e1 100644 --- a/front_end/panels/js_profiler/js_profiler-meta.ts +++ b/front_end/panels/js_timeline/js_timeline-meta.ts @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; -import type * as Timeline from '../../panels/timeline/timeline.js'; +import type * as Timeline from '../timeline/timeline.js'; import * as UI from '../../ui/legacy/legacy.js'; const UIStrings = { @@ -32,7 +32,7 @@ const UIStrings = { */ startProfilingAndReloadPage: 'Start profiling and reload page', }; -const str_ = i18n.i18n.registerUIStrings('panels/js_profiler/js_profiler-meta.ts', UIStrings); +const str_ = i18n.i18n.registerUIStrings('panels/js_timeline/js_timeline-meta.ts', UIStrings); const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); let loadedTimelineModule: (typeof Timeline|undefined); diff --git a/front_end/panels/js_profiler/js_profiler.ts b/front_end/panels/js_timeline/js_timeline.ts similarity index 100% rename from front_end/panels/js_profiler/js_profiler.ts rename to front_end/panels/js_timeline/js_timeline.ts diff --git a/front_end/panels/profiler/BUILD.gn b/front_end/panels/profiler/BUILD.gn index d154023160..887c3e9341 100644 --- a/front_end/panels/profiler/BUILD.gn +++ b/front_end/panels/profiler/BUILD.gn @@ -21,8 +21,6 @@ generate_css("css_files") { devtools_module("profiler") { sources = [ "BottomUpProfileDataGrid.ts", - "CPUProfileFlameChart.ts", - "CPUProfileView.ts", "ChildrenProvider.ts", "HeapProfileView.ts", "HeapProfilerPanel.ts", @@ -35,6 +33,7 @@ devtools_module("profiler") { "LiveHeapProfileView.ts", "ModuleUIStrings.ts", "ProfileDataGrid.ts", + "ProfileFlameChartDataProvider.ts", "ProfileHeader.ts", "ProfileLauncherView.ts", "ProfileSidebarTreeElement.ts", @@ -75,7 +74,6 @@ devtools_entrypoint("bundle") { visibility = [ ":*", "../../entrypoints/*", - "../js_profiler/*", "../timeline/*", ] @@ -95,18 +93,3 @@ devtools_entrypoint("meta") { visibility = [ "../../entrypoints/*" ] } - -ts_library("unittests") { - testonly = true - - sources = [ "CPUProfileView.test.ts" ] - - deps = [ - ":bundle", - "../../core/common:bundle", - "../../core/protocol_client:bundle", - "../../core/sdk:bundle", - "../../generated:protocol", - "../../testing", - ] -} diff --git a/front_end/panels/profiler/CPUProfileView.test.ts b/front_end/panels/profiler/CPUProfileView.test.ts deleted file mode 100644 index d6a2d22826..0000000000 --- a/front_end/panels/profiler/CPUProfileView.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import * as SDK from '../../core/sdk/sdk.js'; -import type * as Protocol from '../../generated/protocol.js'; -import {createTarget} from '../../testing/EnvironmentHelpers.js'; -import {describeWithRealConnection} from '../../testing/RealConnection.js'; - -import type * as Profiler from './profiler.js'; - -describeWithRealConnection('CPUProfileView test', () => { - it('reads registered console profile messages from the model', async () => { - const Profiler = await import('./profiler.js'); - const target = createTarget(); - const model = target.model(SDK.CPUProfilerModel.CPUProfilerModel) as SDK.CPUProfilerModel.CPUProfilerModel; - const scriptId = 'bar' as Protocol.Runtime.ScriptId; - const lineNumber = 42; - const cpuProfile = { - nodes: [{ - id: 1, - callFrame: {functionName: 'fun', scriptId, lineNumber, url: 'http://foo', columnNumber: 1}, - hitCount: 42, - }], - startTime: 1, - endTime: 2, - }; - model.consoleProfileFinished({ - id: 'foo', - location: {scriptId, lineNumber}, - profile: cpuProfile, - }); - const profileType = new Profiler.CPUProfileView.CPUProfileType(); - const cpuProfileHeader = profileType.getProfiles()[0] as Profiler.CPUProfileView.CPUProfileHeader; - assert.deepEqual(cpuProfileHeader?.cpuProfilerModel?.registeredConsoleProfileMessages[0]?.cpuProfile, cpuProfile); - }); -}); diff --git a/front_end/panels/profiler/CPUProfileView.ts b/front_end/panels/profiler/CPUProfileView.ts deleted file mode 100644 index 62d44082fe..0000000000 --- a/front_end/panels/profiler/CPUProfileView.ts +++ /dev/null @@ -1,463 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import * as Common from '../../core/common/common.js'; -import * as Host from '../../core/host/host.js'; -import * as i18n from '../../core/i18n/i18n.js'; -import * as SDK from '../../core/sdk/sdk.js'; -import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; -import * as Components from '../../ui/legacy/components/utils/utils.js'; -import * as UI from '../../ui/legacy/legacy.js'; -import type * as Protocol from '../../generated/protocol.js'; -import * as CPUProfile from '../../models/cpu_profile/cpu_profile.js'; - -import {ProfileFlameChartDataProvider} from './CPUProfileFlameChart.js'; - -import {type Formatter, type ProfileDataGridNode} from './ProfileDataGrid.js'; - -import {ProfileEvents, ProfileType, type ProfileHeader} from './ProfileHeader.js'; -import {ProfileView, WritableProfileHeader} from './ProfileView.js'; - -const UIStrings = { - /** - *@description Time of a single activity, as opposed to the total time - */ - selfTime: 'Self Time', - /** - *@description Text for the total time of something - */ - totalTime: 'Total Time', - /** - *@description Text in CPUProfile View of a profiler tool - */ - recordJavascriptCpuProfile: 'Record JavaScript CPU Profile', - /** - *@description Text in CPUProfile View of a profiler tool - */ - stopCpuProfiling: 'Stop CPU profiling', - /** - *@description Text in CPUProfile View of a profiler tool - */ - startCpuProfiling: 'Start CPU profiling', - /** - *@description Text in CPUProfile View of a profiler tool - */ - cpuProfiles: 'CPU PROFILES', - /** - *@description Text in CPUProfile View of a profiler tool, that show how much time a script spend executing a function. - */ - cpuProfilesShow: 'CPU profiles show where the execution time is spent in your page\'s JavaScript functions.', - /** - *@description Text in CPUProfile View of a profiler tool - */ - recording: 'Recording…', - /** - *@description Time in miliseconds - *@example {30.1} PH1 - */ - fms: '{PH1} ms', - /** - *@description Text in CPUProfile View of a profiler tool - *@example {21.33} PH1 - */ - formatPercent: '{PH1} %', - /** - *@description Text for the name of something - */ - name: 'Name', - /** - *@description Text for web URLs - */ - url: 'URL', - /** - *@description Text in CPUProfile View of a profiler tool - */ - aggregatedSelfTime: 'Aggregated self time', - /** - *@description Text in CPUProfile View of a profiler tool - */ - aggregatedTotalTime: 'Aggregated total time', - /** - *@description Text that indicates a JavaScript function in a CPU profile is not optimized. - */ - notOptimized: 'Not optimized', -}; -const str_ = i18n.i18n.registerUIStrings('panels/profiler/CPUProfileView.ts', UIStrings); -const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); -export class CPUProfileView extends ProfileView implements UI.SearchableView.Searchable { - override profileHeader: CPUProfileHeader; - override adjustedTotal: number; - constructor(profileHeader: CPUProfileHeader) { - super(); - this.profileHeader = profileHeader; - this.initialize(new NodeFormatter(this)); - const profile = profileHeader.profileModel(); - this.adjustedTotal = profile.profileHead.total; - this.adjustedTotal -= profile.idleNode ? profile.idleNode.total : 0; - this.setProfile(profile); - } - - override wasShown(): void { - super.wasShown(); - PerfUI.LineLevelProfile.Performance.instance().reset(); - PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile( - this.profileHeader.profileModel(), this.profileHeader.target); - } - - override columnHeader(columnId: string): Common.UIString.LocalizedString { - switch (columnId) { - case 'self': - return i18nString(UIStrings.selfTime); - case 'total': - return i18nString(UIStrings.totalTime); - } - return Common.UIString.LocalizedEmptyString; - } - - override createFlameChartDataProvider(): ProfileFlameChartDataProvider { - return new CPUFlameChartDataProvider(this.profileHeader.profileModel(), this.profileHeader.cpuProfilerModel); - } -} - -export class CPUProfileType extends ProfileType { - recording: boolean; - constructor() { - super(CPUProfileType.TypeId, i18nString(UIStrings.recordJavascriptCpuProfile)); - this.recording = false; - - const targetManager = SDK.TargetManager.TargetManager.instance(); - const profilerModels = targetManager.models(SDK.CPUProfilerModel.CPUProfilerModel); - for (const model of profilerModels) { - for (const message of model.registeredConsoleProfileMessages) { - this.consoleProfileFinished(message); - } - } - - SDK.TargetManager.TargetManager.instance().addModelListener( - SDK.CPUProfilerModel.CPUProfilerModel, SDK.CPUProfilerModel.Events.ConsoleProfileFinished, - event => this.consoleProfileFinished(event.data), this); - } - - override profileBeingRecorded(): ProfileHeader|null { - return super.profileBeingRecorded() as ProfileHeader | null; - } - - override typeName(): string { - return 'CPU'; - } - - override fileExtension(): string { - return '.cpuprofile'; - } - - override get buttonTooltip(): Common.UIString.LocalizedString { - return this.recording ? i18nString(UIStrings.stopCpuProfiling) : i18nString(UIStrings.startCpuProfiling); - } - - override buttonClicked(): boolean { - if (this.recording) { - void this.stopRecordingProfile(); - return false; - } - this.startRecordingProfile(); - return true; - } - - override get treeItemTitle(): Common.UIString.LocalizedString { - return i18nString(UIStrings.cpuProfiles); - } - - override get description(): Common.UIString.LocalizedString { - return i18nString(UIStrings.cpuProfilesShow); - } - - consoleProfileFinished(data: SDK.CPUProfilerModel.ProfileFinishedData): void { - const profile = new CPUProfileHeader(data.cpuProfilerModel, this, data.title); - profile.setProtocolProfile(data.cpuProfile); - this.addProfile(profile); - } - - startRecordingProfile(): void { - const cpuProfilerModel = UI.Context.Context.instance().flavor(SDK.CPUProfilerModel.CPUProfilerModel); - if (this.profileBeingRecorded() || !cpuProfilerModel) { - return; - } - const profile = new CPUProfileHeader(cpuProfilerModel, this); - this.setProfileBeingRecorded(profile as ProfileHeader); - void SDK.TargetManager.TargetManager.instance().suspendAllTargets(); - this.addProfile(profile as ProfileHeader); - profile.updateStatus(i18nString(UIStrings.recording)); - this.recording = true; - void cpuProfilerModel.startRecording(); - Host.userMetrics.actionTaken(Host.UserMetrics.Action.ProfilesCPUProfileTaken); - } - - async stopRecordingProfile(): Promise { - this.recording = false; - const profileBeingRecorded = this.profileBeingRecorded() as CPUProfileHeader; - if (!profileBeingRecorded || !profileBeingRecorded.cpuProfilerModel) { - return; - } - - const profile = await profileBeingRecorded.cpuProfilerModel.stopRecording(); - const recordedProfile = this.profileBeingRecorded() as CPUProfileHeader; - if (recordedProfile) { - if (!profile) { - throw new Error('Expected profile to be non-null'); - } - recordedProfile.setProtocolProfile(profile); - recordedProfile.updateStatus(''); - this.setProfileBeingRecorded(null); - } - - await SDK.TargetManager.TargetManager.instance().resumeAllTargets(); - this.dispatchEventToListeners(ProfileEvents.ProfileComplete, recordedProfile); - } - - override createProfileLoadedFromFile(title: string): ProfileHeader { - return new CPUProfileHeader(null, this, title); - } - - override profileBeingRecordedRemoved(): void { - void this.stopRecordingProfile(); - } - - // eslint-disable-next-line @typescript-eslint/naming-convention - static readonly TypeId = 'CPU'; -} - -export class CPUProfileHeader extends WritableProfileHeader { - cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel|null; - profileModelInternal?: CPUProfile.CPUProfileDataModel.CPUProfileDataModel; - target: SDK.Target.Target|null; - - constructor(cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel|null, type: CPUProfileType, title?: string) { - super(cpuProfilerModel && cpuProfilerModel.debuggerModel(), type, title); - this.cpuProfilerModel = cpuProfilerModel; - this.target = this.cpuProfilerModel && this.cpuProfilerModel.target() || null; - } - - override createView(): ProfileView { - return new CPUProfileView(this); - } - - protocolProfile(): Protocol.Profiler.Profile { - if (!this.protocolProfile()) { - throw new Error('Expected _protocolProfile to be available'); - } - return this.protocolProfile(); - } - - profileModel(): CPUProfile.CPUProfileDataModel.CPUProfileDataModel { - if (!this.profileModelInternal) { - throw new Error('Expected _profileModel to be available'); - } - return this.profileModelInternal; - } - - override setProfile(profile: Protocol.Profiler.Profile): void { - this.profileModelInternal = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(profile); - } -} - -export class NodeFormatter implements Formatter { - readonly profileView: CPUProfileView; - constructor(profileView: CPUProfileView) { - this.profileView = profileView; - } - - formatValue(value: number): string { - return i18nString(UIStrings.fms, {PH1: value.toFixed(1)}); - } - - formatValueAccessibleText(value: number): string { - return this.formatValue(value); - } - - formatPercent(value: number, node: ProfileDataGridNode): string { - if (this.profileView) { - const profile = this.profileView.profile(); - if (profile && node.profileNode !== (profile as CPUProfile.CPUProfileDataModel.CPUProfileDataModel).idleNode) { - return i18nString(UIStrings.formatPercent, {PH1: value.toFixed(2)}); - } - } - return ''; - } - - linkifyNode(node: ProfileDataGridNode): Element|null { - const cpuProfilerModel = this.profileView.profileHeader.cpuProfilerModel; - const target = cpuProfilerModel ? cpuProfilerModel.target() : null; - const options = {className: 'profile-node-file', inlineFrameIndex: 0}; - return this.profileView.linkifier().maybeLinkifyConsoleCallFrame(target, node.profileNode.callFrame, options); - } -} - -export class CPUFlameChartDataProvider extends ProfileFlameChartDataProvider { - readonly cpuProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel; - readonly cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel|null; - entrySelfTimes?: Float32Array; - - constructor( - cpuProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel, - cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel|null) { - super(); - this.cpuProfile = cpuProfile; - this.cpuProfilerModel = cpuProfilerModel; - } - - override minimumBoundary(): number { - return this.cpuProfile.profileStartTime; - } - - override totalTime(): number { - return this.cpuProfile.profileHead.total; - } - - override entryHasDeoptReason(entryIndex: number): boolean { - const node = (this.entryNodes[entryIndex] as CPUProfile.CPUProfileDataModel.CPUProfileNode); - return Boolean(node.deoptReason); - } - - override calculateTimelineData(): PerfUI.FlameChart.FlameChartTimelineData { - const entries: (CPUFlameChartDataProvider.ChartEntry|null)[] = []; - const stack: number[] = []; - let maxDepth = 5; - - function onOpenFrame(): void { - stack.push(entries.length); - // Reserve space for the entry, as they have to be ordered by startTime. - // The entry itself will be put there in onCloseFrame. - entries.push(null); - } - function onCloseFrame( - depth: number, node: CPUProfile.ProfileTreeModel.ProfileNode, startTime: number, totalTime: number, - selfTime: number): void { - const index = (stack.pop() as number); - entries[index] = new CPUFlameChartDataProvider.ChartEntry(depth, totalTime, startTime, selfTime, node); - maxDepth = Math.max(maxDepth, depth); - } - this.cpuProfile.forEachFrame(onOpenFrame, onCloseFrame); - - const entryNodes: CPUProfile.ProfileTreeModel.ProfileNode[] = new Array(entries.length); - const entryLevels = new Uint16Array(entries.length); - const entryTotalTimes = new Float32Array(entries.length); - const entrySelfTimes = new Float32Array(entries.length); - const entryStartTimes = new Float64Array(entries.length); - - for (let i = 0; i < entries.length; ++i) { - const entry = entries[i]; - if (!entry) { - continue; - } - entryNodes[i] = entry.node; - entryLevels[i] = entry.depth; - entryTotalTimes[i] = entry.duration; - entryStartTimes[i] = entry.startTime; - entrySelfTimes[i] = entry.selfTime; - } - - this.maxStackDepthInternal = maxDepth + 1; - this.entryNodes = entryNodes; - this.timelineDataInternal = - PerfUI.FlameChart.FlameChartTimelineData.create({entryLevels, entryTotalTimes, entryStartTimes, groups: null}); - - this.entrySelfTimes = entrySelfTimes; - - return this.timelineDataInternal; - } - - override prepareHighlightedEntryInfo(entryIndex: number): Element|null { - const timelineData = this.timelineDataInternal; - const node = this.entryNodes[entryIndex]; - if (!node) { - return null; - } - - const entryInfo: { - title: string, - value: string, - }[] = []; - function pushEntryInfoRow(title: string, value: string): void { - entryInfo.push({title: title, value: value}); - } - function millisecondsToString(ms: number): string { - if (ms === 0) { - return '0'; - } - if (ms < 1000) { - return i18nString(UIStrings.fms, {PH1: ms.toFixed(1)}); - } - return i18n.TimeUtilities.secondsToString(ms / 1000, true); - } - const name = UI.UIUtils.beautifyFunctionName(node.functionName); - pushEntryInfoRow(i18nString(UIStrings.name), name); - const selfTime = millisecondsToString((this.entrySelfTimes as Float32Array)[entryIndex]); - const totalTime = - millisecondsToString((timelineData as PerfUI.FlameChart.FlameChartTimelineData).entryTotalTimes[entryIndex]); - pushEntryInfoRow(i18nString(UIStrings.selfTime), selfTime); - pushEntryInfoRow(i18nString(UIStrings.totalTime), totalTime); - const linkifier = new Components.Linkifier.Linkifier(); - const link = - linkifier.maybeLinkifyConsoleCallFrame(this.cpuProfilerModel && this.cpuProfilerModel.target(), node.callFrame); - if (link) { - pushEntryInfoRow(i18nString(UIStrings.url), link.textContent || ''); - } - linkifier.dispose(); - pushEntryInfoRow( - i18nString(UIStrings.aggregatedSelfTime), i18n.TimeUtilities.secondsToString(node.self / 1000, true)); - pushEntryInfoRow( - i18nString(UIStrings.aggregatedTotalTime), i18n.TimeUtilities.secondsToString(node.total / 1000, true)); - const deoptReason = (node as CPUProfile.CPUProfileDataModel.CPUProfileNode).deoptReason; - if (deoptReason) { - pushEntryInfoRow(i18nString(UIStrings.notOptimized), deoptReason); - } - - return ProfileView.buildPopoverTable(entryInfo); - } -} - -export namespace CPUFlameChartDataProvider { - export class ChartEntry { - depth: number; - duration: number; - startTime: number; - selfTime: number; - node: CPUProfile.ProfileTreeModel.ProfileNode; - - constructor( - depth: number, duration: number, startTime: number, selfTime: number, - node: CPUProfile.ProfileTreeModel.ProfileNode) { - this.depth = depth; - this.duration = duration; - this.startTime = startTime; - this.selfTime = selfTime; - this.node = node; - } - } -} diff --git a/front_end/panels/profiler/HeapProfileView.ts b/front_end/panels/profiler/HeapProfileView.ts index ba3f68a855..8fecc61149 100644 --- a/front_end/panels/profiler/HeapProfileView.ts +++ b/front_end/panels/profiler/HeapProfileView.ts @@ -13,9 +13,9 @@ import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Components from '../../ui/legacy/components/utils/utils.js'; import * as UI from '../../ui/legacy/legacy.js'; -import {ProfileFlameChartDataProvider} from './CPUProfileFlameChart.js'; import {Events, HeapTimelineOverview, type IdsRangeChangedEvent, type Samples} from './HeapTimelineOverview.js'; import {type Formatter, type ProfileDataGridNode} from './ProfileDataGrid.js'; +import {ProfileFlameChartDataProvider} from './ProfileFlameChartDataProvider.js'; import {ProfileEvents, type ProfileHeader, ProfileType} from './ProfileHeader.js'; import {ProfileView, WritableProfileHeader} from './ProfileView.js'; diff --git a/front_end/panels/profiler/CPUProfileFlameChart.ts b/front_end/panels/profiler/ProfileFlameChartDataProvider.ts similarity index 99% rename from front_end/panels/profiler/CPUProfileFlameChart.ts rename to front_end/panels/profiler/ProfileFlameChartDataProvider.ts index 2986caf5da..a8f49d3c8a 100644 --- a/front_end/panels/profiler/CPUProfileFlameChart.ts +++ b/front_end/panels/profiler/ProfileFlameChartDataProvider.ts @@ -139,7 +139,7 @@ export class ProfileFlameChartDataProvider implements PerfUI.FlameChart.FlameCha } } -export class CPUProfileFlameChart extends +export class ProfileFlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) implements UI.SearchableView.Searchable { readonly searchableView: UI.SearchableView.SearchableView; diff --git a/front_end/panels/profiler/ProfileTypeRegistry.ts b/front_end/panels/profiler/ProfileTypeRegistry.ts index b5902e425b..487468d4e6 100644 --- a/front_end/panels/profiler/ProfileTypeRegistry.ts +++ b/front_end/panels/profiler/ProfileTypeRegistry.ts @@ -2,17 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {CPUProfileType} from './CPUProfileView.js'; import {SamplingHeapProfileType} from './HeapProfileView.js'; import {HeapSnapshotProfileType, TrackingHeapSnapshotProfileType} from './HeapSnapshotView.js'; export class ProfileTypeRegistry { - cpuProfileType: CPUProfileType; heapSnapshotProfileType: HeapSnapshotProfileType; samplingHeapProfileType: SamplingHeapProfileType; trackingHeapSnapshotProfileType: TrackingHeapSnapshotProfileType; constructor() { - this.cpuProfileType = new CPUProfileType(); this.heapSnapshotProfileType = new HeapSnapshotProfileType(); this.samplingHeapProfileType = new SamplingHeapProfileType(); this.trackingHeapSnapshotProfileType = new TrackingHeapSnapshotProfileType(); diff --git a/front_end/panels/profiler/ProfileView.ts b/front_end/panels/profiler/ProfileView.ts index 13171cbd25..a5f366930b 100644 --- a/front_end/panels/profiler/ProfileView.ts +++ b/front_end/panels/profiler/ProfileView.ts @@ -16,8 +16,8 @@ import * as Components from '../../ui/legacy/components/utils/utils.js'; import * as UI from '../../ui/legacy/legacy.js'; import {BottomUpProfileDataGridTree} from './BottomUpProfileDataGrid.js'; -import {CPUProfileFlameChart, type ProfileFlameChartDataProvider} from './CPUProfileFlameChart.js'; import {type Formatter, type ProfileDataGridNode, ProfileDataGridTree} from './ProfileDataGrid.js'; +import {ProfileFlameChart, type ProfileFlameChartDataProvider} from './ProfileFlameChartDataProvider.js'; import {type DataDisplayDelegate, ProfileHeader, type ProfileType} from './ProfileHeader.js'; import {ProfileSidebarTreeElement} from './ProfileSidebarTreeElement.js'; import {TopDownProfileDataGridTree} from './TopDownProfileDataGrid.js'; @@ -121,9 +121,9 @@ export class ProfileView extends UI.View.SimpleView implements UI.SearchableView topDownProfileDataGridTree?: TopDownProfileDataGridTree|null; currentSearchResultIndex?: number; dataProvider?: ProfileFlameChartDataProvider; - flameChart?: CPUProfileFlameChart; - visibleView?: CPUProfileFlameChart|DataGrid.DataGrid.DataGridWidget; - searchableElement?: ProfileDataGridTree|CPUProfileFlameChart; + flameChart?: ProfileFlameChart; + visibleView?: ProfileFlameChart|DataGrid.DataGrid.DataGridWidget; + searchableElement?: ProfileDataGridTree|ProfileFlameChart; profileDataGridTree?: ProfileDataGridTree; constructor() { super(i18nString(UIStrings.profile)); @@ -405,7 +405,7 @@ export class ProfileView extends UI.View.SimpleView implements UI.SearchableView return; } this.dataProvider = this.createFlameChartDataProvider(); - this.flameChart = new CPUProfileFlameChart(this.searchableViewInternal, this.dataProvider); + this.flameChart = new ProfileFlameChart(this.searchableViewInternal, this.dataProvider); this.flameChart.addEventListener(PerfUI.FlameChart.Events.EntryInvoked, event => { void this.onEntryInvoked(event); }); diff --git a/front_end/panels/profiler/ProfilesPanel.ts b/front_end/panels/profiler/ProfilesPanel.ts index 5a2d573f95..45785401e8 100644 --- a/front_end/panels/profiler/ProfilesPanel.ts +++ b/front_end/panels/profiler/ProfilesPanel.ts @@ -28,7 +28,6 @@ */ import * as Common from '../../core/common/common.js'; -import * as Host from '../../core/host/host.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; @@ -48,7 +47,6 @@ import {Events as ProfileLauncherEvents, ProfileLauncherView} from './ProfileLau import {ProfileSidebarTreeElement} from './ProfileSidebarTreeElement.js'; import profilesPanelStyles from './profilesPanel.css.js'; import profilesSidebarTreeStyles from './profilesSidebarTree.css.js'; -import {instance} from './ProfileTypeRegistry.js'; const UIStrings = { /** @@ -74,19 +72,6 @@ const UIStrings = { *@description Text in Profiles Panel of a profiler tool */ profiles: 'Profiles', - /** - *@description Text in the JS Profiler panel to show warning to user that JS profiler will be deprecated. - */ - deprecationWarnMsg: - 'This panel will be deprecated in the upcoming version. Use the Performance panel to record JavaScript CPU profiles.', - /** - *@description Text of a button in the JS Profiler panel to let user give feedback. - */ - feedback: 'Feedback', - /** - *@description Text of a button in the JS Profiler panel to let user go to Performance panel. - */ - goToPerformancePanel: 'Go to Performance Panel', }; const str_ = i18n.i18n.registerUIStrings('panels/profiler/ProfilesPanel.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); @@ -682,84 +667,6 @@ export class ProfilesSidebarTreeElement extends UI.TreeOutline.TreeElement { } } -let jsProfilerPanelInstance: JSProfilerPanel; - -export class JSProfilerPanel extends ProfilesPanel implements UI.ActionRegistration.ActionDelegate { - constructor() { - const registry = instance; - super('js-profiler', [registry.cpuProfileType], 'profiler.js-toggle-recording'); - this.splitWidget().mainWidget()?.setMinimumSize(350, 0); - this.#showDeprecationInfobar(); - } - - static instance(opts: { - forceNew: boolean|null, - } = {forceNew: null}): JSProfilerPanel { - const {forceNew} = opts; - if (!jsProfilerPanelInstance || forceNew) { - jsProfilerPanelInstance = new JSProfilerPanel(); - } - return jsProfilerPanelInstance; - } - - #showDeprecationInfobar(): void { - function openFeedbackLink(): void { - Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab( - 'https://crbug.com/1354548' as Platform.DevToolsPath.UrlString); - } - - async function openPerformancePanel(): Promise { - await UI.InspectorView.InspectorView.instance().showPanel('timeline'); - } - - const infobar = new UI.Infobar.Infobar( - UI.Infobar.Type.Warning, - /* text */ i18nString(UIStrings.deprecationWarnMsg), /* actions? */ - [ - { - text: i18nString(UIStrings.feedback), - highlight: false, - delegate: openFeedbackLink, - dismiss: false, - jslogContext: 'feedback', - }, - { - text: i18nString(UIStrings.goToPerformancePanel), - highlight: true, - delegate: openPerformancePanel, - dismiss: false, - jslogContext: 'go-to-performance-panel', - }, - ], - /* disableSetting? */ undefined, - /* isCloseable TODO(crbug.com/1354548) Remove the prop from infobar with JS Profiler deprecation */ false, - 'panel-deprecated', - ); - infobar.setParentView(this); - this.splitWidget().mainWidget()?.element.prepend(infobar.element); - } - - override wasShown(): void { - super.wasShown(); - UI.Context.Context.instance().setFlavor(JSProfilerPanel, this); - } - - override willHide(): void { - UI.Context.Context.instance().setFlavor(JSProfilerPanel, null); - super.willHide(); - } - - handleAction(_context: UI.Context.Context, _actionId: string): boolean { - const panel = UI.Context.Context.instance().flavor(JSProfilerPanel); - if (panel instanceof JSProfilerPanel) { - panel.toggleRecord(); - } else { - throw new Error('non-null JSProfilerPanel expected!'); - } - return true; - } -} - export class ActionDelegate implements UI.ActionRegistration.ActionDelegate { handleAction(context: UI.Context.Context, actionId: string): boolean { switch (actionId) { diff --git a/front_end/panels/profiler/profiler.ts b/front_end/panels/profiler/profiler.ts index 4720315f74..7922c05a6c 100644 --- a/front_end/panels/profiler/profiler.ts +++ b/front_end/panels/profiler/profiler.ts @@ -4,8 +4,6 @@ import * as BottomUpProfileDataGrid from './BottomUpProfileDataGrid.js'; import * as ChildrenProvider from './ChildrenProvider.js'; -import * as CPUProfileFlameChart from './CPUProfileFlameChart.js'; -import * as CPUProfileView from './CPUProfileView.js'; import * as HeapProfilerPanel from './HeapProfilerPanel.js'; import * as HeapProfileView from './HeapProfileView.js'; import * as HeapSnapshotDataGrids from './HeapSnapshotDataGrids.js'; @@ -16,6 +14,7 @@ import * as HeapTimelineOverview from './HeapTimelineOverview.js'; import * as IsolateSelector from './IsolateSelector.js'; import * as LiveHeapProfileView from './LiveHeapProfileView.js'; import * as ProfileDataGrid from './ProfileDataGrid.js'; +import * as ProfileFlameChart from './ProfileFlameChartDataProvider.js'; import * as ProfileHeader from './ProfileHeader.js'; import * as ProfileLauncherView from './ProfileLauncherView.js'; import * as ProfileSidebarTreeElement from './ProfileSidebarTreeElement.js'; @@ -27,8 +26,6 @@ import * as TopDownProfileDataGrid from './TopDownProfileDataGrid.js'; export { BottomUpProfileDataGrid, ChildrenProvider, - CPUProfileFlameChart, - CPUProfileView, HeapProfilerPanel, HeapProfileView, HeapSnapshotDataGrids, @@ -39,6 +36,7 @@ export { IsolateSelector, LiveHeapProfileView, ProfileDataGrid, + ProfileFlameChart, ProfileHeader, ProfileLauncherView, ProfileSidebarTreeElement, diff --git a/front_end/panels/timeline/BUILD.gn b/front_end/panels/timeline/BUILD.gn index 816460a60f..8ddc75718b 100644 --- a/front_end/panels/timeline/BUILD.gn +++ b/front_end/panels/timeline/BUILD.gn @@ -147,7 +147,7 @@ devtools_entrypoint("bundle") { "../../testing/*", "../../ui/components/docs/performance_panel/*", "../input/*", - "../js_profiler/*", + "../js_timeline/*", "../lighthouse/*", "../recorder/*", "./track_appenders:unittests", diff --git a/front_end/panels/timeline/timeline-meta.ts b/front_end/panels/timeline/timeline-meta.ts index adc194e4c5..ae030edc89 100644 --- a/front_end/panels/timeline/timeline-meta.ts +++ b/front_end/panels/timeline/timeline-meta.ts @@ -73,14 +73,6 @@ async function loadTimelineModule(): Promise { return loadedTimelineModule; } -// The profiler module is imported here because the js profiler tab is implemented -// in the profiler module. Since the tab doesn't belong to all apps that extend -// the shell app, it cannot be registered in profiler's meta file, as profiler is -// part of the shell app, and thus all of the extensions registered in profiler -// belong to all apps that extend from shell. -// Instead, we register the extensions for the js profiler tab in panels/timeline/ and -// js_profiler/ so that the tab is available only in the apps it belongs to. - function maybeRetrieveContextTypes(getClassCallBack: (timelineModule: typeof Timeline) => T[]): T[] { if (loadedTimelineModule === undefined) { return [];