Skip to content

Commit

Permalink
ui: clean up raf_scheduler.ts and perf.ts
Browse files Browse the repository at this point in the history
- Improve naming and semantic of code in RafScheduler.
- Remove coupling between the Perf debugging UI and RafScheduler.
- Remove global state in perf.ts
- Just use performance.now() unconditionally. The existing comment
  that says that it is slow is a lie.

Bug: 379040490
Change-Id: Iae793df8d83d712720bb7d24c89db3c00eb56f22
  • Loading branch information
primiano committed Nov 14, 2024
1 parent 819d1a7 commit cf95cb6
Show file tree
Hide file tree
Showing 22 changed files with 386 additions and 372 deletions.
2 changes: 1 addition & 1 deletion ui/src/common/track_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,6 @@ export class TimelineFetcher<Data> implements Disposable {
const {start, end} = this.latestTimespan;
const resolution = this.latestResolution;
this.data_ = await this.doFetch(start, end, resolution);
raf.scheduleRedraw();
raf.scheduleCanvasRedraw();
}
}
17 changes: 4 additions & 13 deletions ui/src/core/app_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {AnalyticsInternal, initAnalytics} from './analytics_impl';
import {createProxy, getOrCreate} from '../base/utils';
import {PageManagerImpl} from './page_manager';
import {PageHandler} from '../public/page';
import {setPerfHooks} from './perf';
import {PerfManager} from './perf_manager';
import {ServiceWorkerController} from '../frontend/service_worker_controller';
import {FeatureFlagManager, FlagSettings} from '../public/feature_flag';
import {featureFlags} from './feature_flags';
Expand All @@ -59,6 +59,7 @@ export class AppContext {
readonly pageMgr = new PageManagerImpl();
readonly sidebarMgr: SidebarManagerImpl;
readonly pluginMgr: PluginManagerImpl;
readonly perfMgr = new PerfManager();
readonly analytics: AnalyticsInternal;
readonly serviceWorkerController: ServiceWorkerController;
httpRpc = {
Expand All @@ -67,7 +68,6 @@ export class AppContext {
};
initialRouteArgs: RouteArgs;
isLoadingTrace = false; // Set when calling openTrace().
perfDebugging = false; // Enables performance debugging of tracks/panels.
readonly initArgs: AppInitArgs;
readonly embeddedMode: boolean;
readonly testingMode: boolean;
Expand Down Expand Up @@ -296,17 +296,8 @@ export class AppImpl implements App {
return this.appCtx.extraSqlPackages;
}

get perfDebugging(): boolean {
return this.appCtx.perfDebugging;
}

setPerfDebuggingEnabled(enabled: boolean) {
this.appCtx.perfDebugging = enabled;
setPerfHooks(
() => this.perfDebugging,
() => this.setPerfDebuggingEnabled(!this.perfDebugging),
);
raf.scheduleFullRedraw();
get perfDebugging(): PerfManager {
return this.appCtx.perfMgr;
}

get serviceWorkerController(): ServiceWorkerController {
Expand Down
135 changes: 0 additions & 135 deletions ui/src/core/perf.ts

This file was deleted.

145 changes: 145 additions & 0 deletions ui/src/core/perf_manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import m from 'mithril';
import {raf} from './raf_scheduler';
import {PerfStats, PerfStatsContainer, runningStatStr} from './perf_stats';

export class PerfManager {
private _enabled = false;
readonly containers: PerfStatsContainer[] = [];

get enabled(): boolean {
return this._enabled;
}

set enabled(enabled: boolean) {
this._enabled = enabled;
raf.setPerfStatsEnabled(true);
this.containers.forEach((c) => c.setPerfStatsEnabled(enabled));
}

addContainer(container: PerfStatsContainer): Disposable {
this.containers.push(container);
return {
[Symbol.dispose]: () => {
const i = this.containers.indexOf(container);
this.containers.splice(i, 1);
},
};
}

renderPerfStats(): m.Children {
if (!this._enabled) return;
// The rendering of the perf stats UI is atypical. The main issue is that we
// want to redraw the mithril component even if there is no full DOM redraw
// happening (and we don't want to force redraws as a side effect). So we
// return here just a container and handle its rendering ourselves.
const perfMgr = this;
let removed = false;
return m('.perf-stats', {
oncreate(vnode: m.VnodeDOM) {
const animationFrame = (dom: Element) => {
if (removed) return;
m.render(dom, m(PerfStatsUi, {perfMgr}));
requestAnimationFrame(() => animationFrame(dom));
};
animationFrame(vnode.dom);
},
onremove() {
removed = true;
},
});
}
}

// The mithril component that draws the contents of the perf stats box.

interface PerfStatsUiAttrs {
perfMgr: PerfManager;
}

class PerfStatsUi implements m.ClassComponent<PerfStatsUiAttrs> {
view({attrs}: m.Vnode<PerfStatsUiAttrs>) {
return m(
'.perf-stats',
{},
m('section', this.renderRafSchedulerStats()),
m(
'button.close-button',
{
onclick: () => (attrs.perfMgr.enabled = false),
},
m('i.material-icons', 'close'),
),
attrs.perfMgr.containers.map((c, i) =>
m('section', m('div', `Panel Container ${i + 1}`), c.renderPerfStats()),
),
);
}

renderRafSchedulerStats() {
return m(
'div',
m('div', [
m(
'button',
{onclick: () => raf.scheduleCanvasRedraw()},
'Do Canvas Redraw',
),
' | ',
m(
'button',
{onclick: () => raf.scheduleFullRedraw()},
'Do Full Redraw',
),
]),
m('div', 'Raf Timing ' + '(Total may not add up due to imprecision)'),
m(
'table',
this.statTableHeader(),
this.statTableRow('Actions', raf.perfStats.rafActions),
this.statTableRow('Dom', raf.perfStats.rafDom),
this.statTableRow('Canvas', raf.perfStats.rafCanvas),
this.statTableRow('Total', raf.perfStats.rafTotal),
),
m(
'div',
'Dom redraw: ' +
`Count: ${raf.perfStats.domRedraw.count} | ` +
runningStatStr(raf.perfStats.domRedraw),
),
);
}

statTableHeader() {
return m(
'tr',
m('th', ''),
m('th', 'Last (ms)'),
m('th', 'Avg (ms)'),
m('th', 'Avg-10 (ms)'),
);
}

statTableRow(title: string, stat: PerfStats) {
return m(
'tr',
m('td', title),
m('td', stat.last.toFixed(2)),
m('td', stat.mean.toFixed(2)),
m('td', stat.bufferMean.toFixed(2)),
);
}
}
Loading

0 comments on commit cf95cb6

Please sign in to comment.