| // 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); |
| } |
| } |
| } |