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