blob: 73605e07b48e1efde1b999582a1503c76be22c83 [file]
// Copyright (C) 2021 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 type {PerfettoPlugin} from '../../public/plugin';
import type {Trace} from '../../public/trace';
import {TrackNode} from '../../public/workspace';
import {NUM, NUM_NULL, STR_NULL} from '../../trace_processor/query_result';
import {CpuFreqTrack} from './cpu_freq_track';
import {Anchor} from '../../widgets/anchor';
import {Icons} from '../../base/semantic_icons';
import {Cpu} from '../../components/cpu';
import {getMachineCount} from '../../public/utils';
export default class implements PerfettoPlugin {
static readonly id = 'dev.perfetto.CpuFreq';
async onTraceLoad(ctx: Trace): Promise<void> {
const {engine} = ctx;
const numMachines = await getMachineCount(engine);
// Find the list of CPU frequency track ids and their corresponding CPU idle
// track ids if they exist
const tracksResult = await engine.query(`
SELECT
track.id AS freqTrackId,
t2.id AS idleTrackId,
cpu.ucpu AS ucpu,
track.machine_id AS machineId,
machine.name AS machineName,
machine.label_index AS machineLabelIndex,
track.cpu AS cpu
FROM cpu_counter_track track
JOIN cpu
ON track.cpu = cpu.cpu
AND track.machine_id = cpu.machine_id
LEFT JOIN cpu_counter_track t2
ON track.cpu = t2.cpu
AND track.machine_id = t2.machine_id
AND t2.type = 'cpu_idle'
LEFT JOIN machine
ON machine.id = track.machine_id
WHERE
track.type = 'cpu_frequency'
ORDER BY ucpu
`);
// Find the maximum CPU frequency across all CPUs to set the graph scale
const maxCpuFreqResult = await engine.query(`
SELECT
IFNULL(MAX(value), 0) AS freq
FROM counter c
JOIN cpu_counter_track t ON c.track_id = t.id
JOIN _counter_track_summary s ON t.id = s.id
WHERE t.type = 'cpu_frequency';
`);
const maxCpuFreq = maxCpuFreqResult.firstRow({freq: NUM}).freq;
const group = new TrackNode({
name: 'CPU Frequency',
sortOrder: -40,
isSummary: true,
collapsed: false,
});
for (
const it = tracksResult.iter({
freqTrackId: NUM,
machineId: NUM,
machineName: STR_NULL,
machineLabelIndex: NUM_NULL,
cpu: NUM,
ucpu: NUM,
idleTrackId: NUM_NULL,
});
it.valid();
it.next()
) {
const {
freqTrackId,
idleTrackId,
machineId,
machineName,
machineLabelIndex,
cpu,
ucpu,
} = it;
const uri = `/cpu_freq_cpu${ucpu}`;
ctx.tracks.registerTrack({
uri,
tags: {
cpu: ucpu,
},
renderer: new CpuFreqTrack(
{
// Coloring based Cpu number, same for all machines.
cpu,
maximumValue: maxCpuFreq,
freqTrackId,
idleTrackId: idleTrackId ?? undefined,
},
ctx,
),
description: () => {
return m('', [
`Shows the CPU frequency ${cpu.toString()} over time.`,
m('br'),
m(
Anchor,
{
href: 'https://perfetto.dev/docs/data-sources/cpu-freq',
target: '_blank',
icon: Icons.ExternalLink,
},
'Documentation',
),
]);
},
});
const trackNode = new TrackNode({
uri,
name: `CPU ${new Cpu(ucpu, cpu, machineId, machineName ?? undefined, machineLabelIndex ?? undefined, numMachines).toString()} Frequency`,
});
group.addChildInOrder(trackNode);
}
if (group.children.length > 0) {
ctx.defaultWorkspace.addChildInOrder(group);
}
}
}