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'; 17import { info } from '../../../log/Log'; 18import { TraceRow } from '../trace/base/TraceRow'; 19import { ColorUtils } from '../trace/base/ColorUtils'; 20import { CpuFreqLimitRender, CpuFreqLimitsStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; 21import { renders } from '../../database/ui-worker/ProcedureWorker'; 22import { CpuFreqStruct, FreqRender } from '../../database/ui-worker/ProcedureWorkerFreq'; 23import { CpuStateRender, CpuStateStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuState'; 24import { FolderSupplier, FolderThreadHandler } from './SpChartManager'; 25import { Utils } from '../trace/base/Utils'; 26import { cpuFreqDataSender } from '../../database/data-trafic/cpu/CpuFreqDataSender'; 27import { cpuStateSender } from '../../database/data-trafic/cpu/CpuStateSender'; 28import { cpuFreqLimitSender } from '../../database/data-trafic/cpu/CpuFreqLimitDataSender'; 29import { 30 getCpuLimitFreqId, 31 getCpuLimitFreqMax, 32 queryCpuFreq, 33 queryCpuMaxFreq, 34 queryCpuStateFilter 35} from "../../database/sql/Cpu.sql"; 36export class SpFreqChart { 37 private trace: SpSystemTrace; 38 private folderRow: TraceRow<any> | undefined; 39 private folderRowState: TraceRow<any> | undefined; 40 private folderRowLimit: TraceRow<any> | undefined; 41 42 constructor(trace: SpSystemTrace) { 43 this.trace = trace; 44 } 45 46 async init() { 47 let freqList = await queryCpuFreq(); 48 let cpuStateFilterIds = await queryCpuStateFilter(); 49 let cpuFreqLimits = await getCpuLimitFreqId(); 50 let cpuFreqLimitsMax = await getCpuLimitFreqMax(cpuFreqLimits.map((limit) => limit.maxFilterId).join(',')); 51 if (freqList.length > 0) { 52 this.folderRow = TraceRow.skeleton(); 53 this.folderRow.rowId = 'Cpu Frequency'; 54 this.folderRow.rowParentId = ''; 55 this.folderRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_ALL; 56 this.folderRow.style.height = '40px'; 57 this.folderRow.style.width = '100%'; 58 this.folderRow.name = 'Cpu Frequency'; 59 this.folderRow.folder = true; 60 this.folderRow.rowHidden = this.folderRow!.expansion; 61 this.folderRow.setAttribute('children', ''); 62 this.folderRow.supplier = FolderSupplier(); 63 this.folderRow.onThreadHandler = FolderThreadHandler(this.folderRow, this.trace); 64 this.trace.rowsEL?.appendChild(this.folderRow); 65 66 info('Cpu Freq data size is: ', freqList!.length); 67 let freqMaxList = await queryCpuMaxFreq(); 68 CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; 69 let maxFreqObj = Utils.getFrequencyWithUnit(freqMaxList[0].maxFreq); 70 CpuFreqStruct.maxFreq = maxFreqObj.maxFreq; 71 CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName; 72 this.trace.stateRowsId = cpuStateFilterIds; 73 for (let i = 0; i < freqList.length; i++) { 74 const it = freqList[i]; 75 let traceRow = TraceRow.skeleton<CpuFreqStruct>(); 76 traceRow.rowId = `${it.filterId}`; 77 traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ; 78 traceRow.rowParentId = ''; 79 traceRow.style.height = '40px'; 80 traceRow.name = `Cpu ${it.cpu} Frequency`; 81 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 82 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 83 traceRow.supplierFrame = () => { 84 return cpuFreqDataSender(it.cpu, traceRow); //queryCpuFreqData 85 }; 86 traceRow.focusHandler = (ev) => { 87 this.trace?.displayTip( 88 traceRow, 89 CpuFreqStruct.hoverCpuFreqStruct, 90 `<span>${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct?.value!)} kHz</span>` 91 ); 92 }; 93 traceRow.findHoverStruct = () => { 94 CpuFreqStruct.hoverCpuFreqStruct = traceRow.getHoverStruct(true,false, 'value'); 95 }; 96 traceRow.onThreadHandler = (useCache) => { 97 let context: CanvasRenderingContext2D; 98 if (traceRow.currentContext) { 99 context = traceRow.currentContext; 100 } else { 101 context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 102 } 103 traceRow.canvasSave(context); 104 (renders['freq'] as FreqRender).renderMainThread( 105 { 106 context: context, 107 useCache: useCache, 108 type: `freq${it.cpu}`, 109 }, 110 traceRow 111 ); 112 traceRow.canvasRestore(context, this.trace); 113 }; 114 this.trace.rowsEL?.appendChild(traceRow); 115 this.folderRow!.addChildTraceRow(traceRow); 116 } 117 } 118 if (cpuStateFilterIds.length > 0) { 119 this.folderRowState = TraceRow.skeleton(); 120 this.folderRowState.rowId = 'Cpu State'; 121 this.folderRowState.rowType = TraceRow.ROW_TYPE_CPU_STATE_ALL; 122 this.folderRowState.style.height = '40px'; 123 this.folderRowState.folder = true; 124 this.folderRowState.style.width = '100%'; 125 this.folderRowState.rowParentId = ''; 126 this.folderRowState.name = 'Cpu State'; 127 this.folderRowState.rowHidden = this.folderRowState!.expansion; 128 this.folderRowState.setAttribute('children', ''); 129 this.folderRowState.supplier = FolderSupplier(); 130 this.folderRowState.onThreadHandler = FolderThreadHandler(this.folderRowState, this.trace); 131 this.trace.rowsEL?.appendChild(this.folderRowState); 132 133 for (let it of cpuStateFilterIds) { 134 let cpuStateRow = TraceRow.skeleton<CpuStateStruct>(); 135 cpuStateRow.rowId = `${it.filterId}`; 136 cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE; 137 cpuStateRow.rowParentId = ''; 138 cpuStateRow.style.height = '40px'; 139 cpuStateRow.name = `Cpu ${it.cpu} State`; 140 cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 141 cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler; 142 cpuStateRow.isHover = true; 143 cpuStateRow.supplierFrame = () => { 144 return cpuStateSender(it.filterId, cpuStateRow).then((rs) => { 145 rs.forEach((t) => { 146 t.cpu = it.cpu; 147 }); 148 return rs; 149 }); 150 }; 151 cpuStateRow.focusHandler = (ev) => { 152 this.trace.displayTip( 153 cpuStateRow, 154 CpuStateStruct.hoverStateStruct, 155 `<span>State: ${CpuStateStruct.hoverStateStruct?.value}</span>` 156 ); 157 }; 158 cpuStateRow.findHoverStruct = () => { 159 CpuStateStruct.hoverStateStruct = cpuStateRow.getHoverStruct(); 160 }; 161 cpuStateRow.onThreadHandler = (useCache: boolean) => { 162 let context: CanvasRenderingContext2D; 163 if (cpuStateRow.currentContext) { 164 context = cpuStateRow.currentContext; 165 } else { 166 context = cpuStateRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 167 } 168 cpuStateRow.canvasSave(context); 169 (renders['cpu-state'] as CpuStateRender).renderMainThread( 170 { 171 cpuStateContext: context, 172 useCache: useCache, 173 type: `cpu-state-${it.cpu}`, 174 cpu: it.cpu, 175 }, 176 cpuStateRow 177 ); 178 cpuStateRow.canvasRestore(context, this.trace); 179 }; 180 this.folderRowState!.addChildTraceRow(cpuStateRow); 181 } 182 } 183 if (cpuFreqLimits.length > 0) { 184 this.folderRowLimit = TraceRow.skeleton(); 185 this.folderRowLimit.rowId = 'Cpu Freq Limit'; 186 this.folderRowLimit.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMITALL; 187 this.folderRowLimit.style.height = '40px'; 188 this.folderRowLimit.rowParentId = ''; 189 this.folderRowLimit.folder = true; 190 this.folderRowLimit.name = 'Cpu Freq Limit'; 191 this.folderRowLimit.rowHidden = this.folderRowLimit!.expansion; 192 this.folderRowLimit.setAttribute('children', ''); 193 this.folderRowLimit.supplier = FolderSupplier(); 194 this.folderRowLimit.onThreadHandler = FolderThreadHandler(this.folderRowLimit, this.trace); 195 this.trace.rowsEL?.appendChild(this.folderRowLimit); 196 197 for (let limit of cpuFreqLimits) { 198 let findMax = Utils.getFrequencyWithUnit( 199 cpuFreqLimitsMax.find((maxLimit) => { 200 return maxLimit.filterId == limit.maxFilterId; 201 })?.maxValue || 0 202 ); 203 let cpuFreqLimitRow = TraceRow.skeleton<CpuFreqLimitsStruct>(); 204 cpuFreqLimitRow.rowId = `${limit.cpu}`; 205 cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT; 206 cpuFreqLimitRow.rowParentId = ''; 207 cpuFreqLimitRow.style.height = '40px'; 208 cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit`; 209 cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 210 cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; 211 cpuFreqLimitRow.setAttribute('maxFilterId', `${limit.maxFilterId}`); 212 cpuFreqLimitRow.setAttribute('minFilterId', `${limit.minFilterId}`); 213 cpuFreqLimitRow.setAttribute('cpu', `${limit.cpu}`); 214 cpuFreqLimitRow.isHover = true; 215 cpuFreqLimitRow.supplierFrame = () => { 216 return cpuFreqLimitSender(limit.maxFilterId, limit.minFilterId, limit.cpu, cpuFreqLimitRow).then((res) => { 217 res.forEach((item) => { 218 item.cpu = limit.cpu; 219 }); 220 return res; 221 }); 222 }; 223 cpuFreqLimitRow.focusHandler = (ev) => { 224 this.trace.displayTip( 225 cpuFreqLimitRow, 226 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct, 227 `<span>Max Freq: ${ColorUtils.formatNumberComma( 228 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.max || 0 229 )} kHz</span><span>Min Freq: ${ColorUtils.formatNumberComma( 230 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.min || 0 231 )} kHz</span>` 232 ); 233 }; 234 cpuFreqLimitRow.findHoverStruct = () => { 235 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = cpuFreqLimitRow.getHoverStruct(); 236 }; 237 cpuFreqLimitRow.onThreadHandler = (useCache: boolean) => { 238 let context: CanvasRenderingContext2D; 239 if (cpuFreqLimitRow.currentContext) { 240 context = cpuFreqLimitRow.currentContext; 241 } else { 242 context = cpuFreqLimitRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 243 } 244 cpuFreqLimitRow.canvasSave(context); 245 (renders['cpu-limit-freq'] as CpuFreqLimitRender).renderMainThread( 246 { 247 context: context, 248 useCache: useCache, 249 type: `cpu-limit-freq-${limit.cpu}`, 250 cpu: limit.cpu, 251 maxFreq: findMax?.maxFreq || 0, 252 maxFreqName: findMax?.maxFreqName || '', 253 }, 254 cpuFreqLimitRow 255 ); 256 cpuFreqLimitRow.canvasRestore(context, this.trace); 257 }; 258 this.folderRowLimit!.addChildTraceRow(cpuFreqLimitRow); 259 } 260 } 261 } 262} 263 264export class CpuFreqRowLimit { 265 cpu: number = 0; 266 maxFilterId: number = 0; 267 minFilterId: number = 0; 268} 269