1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { SpSystemTrace } from '../SpSystemTrace.js'; 17import { 18 getCpuLimitFreq, 19 getCpuLimitFreqId, 20 getCpuLimitFreqMax, 21 queryCpuFreq, 22 queryCpuFreqData, 23 queryCpuMaxFreq, 24 queryCpuState, 25 queryCpuStateFilter, 26} from '../../database/SqlLite.js'; 27import { info } from '../../../log/Log.js'; 28import { TraceRow } from '../trace/base/TraceRow.js'; 29import { procedurePool } from '../../database/Procedure.js'; 30import { ColorUtils } from '../trace/base/ColorUtils.js'; 31import { CpuFreqLimitRender, CpuFreqLimitsStruct } from '../../database/ui-worker/ProcedureWorkerCpuFreqLimits.js'; 32import { renders } from '../../database/ui-worker/ProcedureWorker.js'; 33import { CpuFreqStruct, FreqRender } from '../../database/ui-worker/ProcedureWorkerFreq.js'; 34import { CpuStateRender, CpuStateStruct } from '../../database/ui-worker/ProcedureWorkerCpuState.js'; 35import { Utils } from '../trace/base/Utils.js'; 36 37export class SpFreqChart { 38 private trace: SpSystemTrace; 39 40 constructor(trace: SpSystemTrace) { 41 this.trace = trace; 42 } 43 44 async init() { 45 let cpuFreqStartTime = new Date().getTime(); 46 let freqList = await queryCpuFreq(); 47 let cpuStateFilterIds = await queryCpuStateFilter(); 48 let cpuFreqLimits = await getCpuLimitFreqId(); 49 let cpuFreqLimitsMax = await getCpuLimitFreqMax( 50 cpuFreqLimits 51 .map((limit) => { 52 return limit.maxFilterId; 53 }) 54 .join(',') 55 ); 56 info('Cpu Freq data size is: ', freqList!.length); 57 let freqMaxList = await queryCpuMaxFreq(); 58 CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; 59 let maxFreqObj = Utils.getFrequencyWithUnit(freqMaxList[0].maxFreq); 60 CpuFreqStruct.maxFreq = maxFreqObj.maxFreq; 61 CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName; 62 for (let i = 0; i < freqList.length; i++) { 63 const it = freqList[i]; 64 let traceRow = TraceRow.skeleton<CpuFreqStruct>(); 65 traceRow.rowId = `${it.filterId}`; 66 traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ; 67 traceRow.rowParentId = ''; 68 traceRow.style.height = '40px'; 69 traceRow.name = `Cpu ${it.cpu} Frequency`; 70 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 71 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 72 traceRow.supplier = () => queryCpuFreqData(it.cpu); 73 traceRow.focusHandler = (ev) => { 74 this.trace?.displayTip( 75 traceRow, 76 CpuFreqStruct.hoverCpuFreqStruct, 77 `<span>${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct?.value!)} kHz</span>` 78 ); 79 }; 80 traceRow.onThreadHandler = (useCache) => { 81 let context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 82 traceRow.canvasSave(context); 83 (renders['freq'] as FreqRender).renderMainThread( 84 { 85 context: context, 86 useCache: useCache, 87 type: `freq${it.cpu}`, 88 }, 89 traceRow 90 ); 91 traceRow.canvasRestore(context); 92 }; 93 this.trace.rowsEL?.appendChild(traceRow); 94 } 95 let heights = [4, 12, 21, 30]; 96 for (let it of cpuStateFilterIds) { 97 let cpuStateRow = TraceRow.skeleton<CpuStateStruct>(); 98 cpuStateRow.rowId = `${it.filterId}`; 99 cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE; 100 cpuStateRow.rowParentId = ''; 101 cpuStateRow.style.height = '40px'; 102 cpuStateRow.name = `Cpu ${it.cpu} State`; 103 cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 104 cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler; 105 cpuStateRow.isHover = true; 106 cpuStateRow.supplier = () => 107 queryCpuState(it.filterId).then((res) => { 108 res.forEach((r) => { 109 r.height = heights[it.value]; 110 r.cpu = it.cpu; 111 }); 112 return res; 113 }); 114 cpuStateRow.focusHandler = (ev) => { 115 this.trace.displayTip( 116 cpuStateRow, 117 CpuStateStruct.hoverStateStruct, 118 `<span>State: ${CpuStateStruct.hoverStateStruct?.value}</span>` 119 ); 120 }; 121 cpuStateRow.onThreadHandler = (useCache: boolean) => { 122 let context = cpuStateRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 123 cpuStateRow.canvasSave(context); 124 (renders['cpu-state'] as CpuStateRender).renderMainThread( 125 { 126 cpuStateContext: context, 127 useCache: useCache, 128 type: `cpu-state-${it.cpu}`, 129 cpu: it.cpu, 130 }, 131 cpuStateRow 132 ); 133 cpuStateRow.canvasRestore(context); 134 }; 135 this.trace.rowsEL?.appendChild(cpuStateRow); 136 } 137 let durTime = new Date().getTime() - cpuFreqStartTime; 138 info('The time to load the CpuFreq data is: ', durTime); 139 for (let limit of cpuFreqLimits) { 140 let findMax = Utils.getFrequencyWithUnit( 141 cpuFreqLimitsMax.find((maxLimit) => { 142 return maxLimit.filterId == limit.maxFilterId; 143 })?.maxValue || 0 144 ); 145 let cpuFreqLimitRow = TraceRow.skeleton<CpuFreqLimitsStruct>(); 146 cpuFreqLimitRow.rowId = `${limit.cpu}`; 147 cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT; 148 cpuFreqLimitRow.rowParentId = ''; 149 cpuFreqLimitRow.style.height = '40px'; 150 cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit`; 151 cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 152 cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; 153 cpuFreqLimitRow.isHover = true; 154 cpuFreqLimitRow.supplier = () => getCpuLimitFreq(limit.maxFilterId, limit.minFilterId, limit.cpu); 155 cpuFreqLimitRow.focusHandler = (ev) => { 156 this.trace.displayTip( 157 cpuFreqLimitRow, 158 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct, 159 `<span>Max Freq: ${ColorUtils.formatNumberComma( 160 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.max || 0 161 )} kHz</span><span>Min Freq: ${ColorUtils.formatNumberComma( 162 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.min || 0 163 )} kHz</span>` 164 ); 165 }; 166 cpuFreqLimitRow.onThreadHandler = (useCache: boolean) => { 167 let context = cpuFreqLimitRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 168 cpuFreqLimitRow.canvasSave(context); 169 (renders['cpu-limit-freq'] as CpuFreqLimitRender).renderMainThread( 170 { 171 context: context, 172 useCache: useCache, 173 type: `cpu-limit-freq-${limit.cpu}`, 174 cpu: limit.cpu, 175 maxFreq: findMax?.maxFreq || 0, 176 maxFreqName: findMax?.maxFreqName || '', 177 }, 178 cpuFreqLimitRow 179 ); 180 cpuFreqLimitRow.canvasRestore(context); 181 }; 182 this.trace.rowsEL?.appendChild(cpuFreqLimitRow); 183 } 184 } 185} 186 187export class CpuFreqRowLimit { 188 cpu: number = 0; 189 maxFilterId: number = 0; 190 minFilterId: number = 0; 191} 192