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 { procedurePool } from '../../database/Procedure'; 20import { CpuRender, CpuStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 21import { renders } from '../../database/ui-worker/ProcedureWorker'; 22import { Utils } from '../trace/base/Utils'; 23import { cpuDataSender } from '../../database/data-trafic/CpuDataSender'; 24import { queryCpuCount, queryCpuMax, queryCpuSchedSlice } from '../../database/sql/Cpu.sql'; 25 26export class SpCpuChart { 27 private trace: SpSystemTrace; 28 29 constructor(trace: SpSystemTrace) { 30 this.trace = trace; 31 } 32 33 private cpuSupplierFrame(traceRow: TraceRow<CpuStruct>, cpuId: number): void { 34 traceRow.supplierFrame = async (): Promise<CpuStruct[]> => { 35 const res = await cpuDataSender(cpuId, traceRow); 36 const filterList = SpSystemTrace.keyPathList.filter((item) => { 37 return item.cpu === cpuId; 38 }); 39 res.push(...filterList); 40 res.forEach((it, i, arr) => { 41 let p = Utils.PROCESS_MAP.get(it.processId!); 42 let t = Utils.THREAD_MAP.get(it.tid!); 43 let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`); 44 if (slice) { 45 it.end_state = slice.endState; 46 it.priority = slice.priority; 47 } 48 it.processName = p; 49 it.processCmdLine = p; 50 it.name = t; 51 it.type = 'thread'; 52 }); 53 return res; 54 }; 55 } 56 57 private cpuThreadHandler(traceRow: TraceRow<CpuStruct>, i1: number): void { 58 traceRow.onThreadHandler = (useCache: boolean, buf: ArrayBuffer | undefined | null): void => { 59 let context: CanvasRenderingContext2D; 60 if (traceRow.currentContext) { 61 context = traceRow.currentContext; 62 } else { 63 context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 64 } 65 traceRow.canvasSave(context); 66 (renders['cpu-data'] as CpuRender).renderMainThread( 67 { 68 ctx: context, 69 useCache: useCache, 70 type: `cpu-data-${i1}`, 71 translateY: traceRow.translateY, 72 }, 73 traceRow 74 ); 75 traceRow.canvasRestore(context, this.trace); 76 }; 77 } 78 79 async init(cpuDataCount?: Map<number, number>): Promise<void> { 80 let CpuStartTime = new Date().getTime(); 81 let array = await queryCpuMax(); 82 let cpuCountResult = await queryCpuCount(); 83 if (cpuCountResult && cpuCountResult.length > 0 && cpuCountResult[0]) { 84 // @ts-ignore 85 (window as unknown).cpuCount = cpuCountResult[0].cpuCount; 86 } else { 87 // @ts-ignore 88 (window as unknown).cpuCount = 0; 89 } 90 let cpuSchedSlice = await queryCpuSchedSlice(); 91 this.initSchedSliceData(cpuSchedSlice); 92 info('Cpu trace row data size is: ', array.length); 93 if (array && array.length > 0 && array[0]) { 94 //@ts-ignore 95 let cpuMax = array[0].cpu; 96 CpuStruct.cpuCount = cpuMax + 1; 97 for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { 98 if (cpuDataCount && (cpuDataCount.get(i1) || 0) > 0) { 99 const cpuId = i1; 100 let traceRow = TraceRow.skeleton<CpuStruct>(); 101 traceRow.rowId = `${cpuId}`; 102 traceRow.rowType = TraceRow.ROW_TYPE_CPU; 103 traceRow.rowParentId = ''; 104 traceRow.style.height = '30px'; 105 traceRow.name = `Cpu ${cpuId}`; 106 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 107 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 108 this.cpuSupplierFrame(traceRow, cpuId); 109 traceRow.focusHandler = (): void => { 110 this.trace?.displayTip( 111 traceRow, 112 CpuStruct.hoverCpuStruct, 113 `<span>P:${CpuStruct.hoverCpuStruct?.processName || 'Process'} [${ 114 CpuStruct.hoverCpuStruct?.processId 115 }]</span><span>T:${CpuStruct.hoverCpuStruct?.name} [${CpuStruct.hoverCpuStruct?.tid}] [Prio:${ 116 CpuStruct.hoverCpuStruct?.priority || 0 117 }]</span>` 118 ); 119 }; 120 traceRow.findHoverStruct = (): void => { 121 CpuStruct.hoverCpuStruct = traceRow.getHoverStruct(); 122 }; 123 this.cpuThreadHandler(traceRow, i1); 124 this.trace.rowsEL?.appendChild(traceRow); 125 } 126 } 127 } 128 let CpuDurTime = new Date().getTime() - CpuStartTime; 129 info('The time to load the Cpu data is: ', CpuDurTime); 130 } 131 132 initProcessThreadStateData = async (progress: Function): Promise<void> => { 133 let time = new Date().getTime(); 134 progress('StateProcessThread', 93); 135 procedurePool.submitWithName('logic0', 'spt-init', {}, undefined, (res: unknown) => {}); 136 let durTime = new Date().getTime() - time; 137 info('The time to load the first ProcessThreadState data is: ', durTime); 138 }; 139 140 initCpuIdle0Data = async (progress: Function): Promise<void> => { 141 let time = new Date().getTime(); 142 progress('CPU Idle', 94); 143 procedurePool.submitWithName( 144 'logic0', 145 'scheduling-getCpuIdle0', 146 { 147 // @ts-ignore 148 endTs: (window as unknown).recordEndNS, // @ts-ignore 149 total: (window as unknown).totalNS, 150 }, 151 undefined, 152 (res: unknown) => {} 153 ); 154 let durTime = new Date().getTime() - time; 155 info('The time to load the first CPU Idle0 data is: ', durTime); 156 }; 157 158 initSchedSliceData(arr: unknown[]): void { 159 Utils.SCHED_SLICE_MAP.clear(); 160 arr.forEach((value) => { 161 // @ts-ignore 162 Utils.SCHED_SLICE_MAP.set(`${value.itid}-${value.ts}`, { endState: value.endState, priority: value.priority }); 163 }); 164 } 165 166 initSchedulingPTData = async (progress: Function): Promise<void> => { 167 let time = new Date().getTime(); 168 progress('CPU Idle', 94); 169 procedurePool.submitWithName('logic0', 'scheduling-getProcessAndThread', {}, undefined, (res: unknown) => {}); 170 let durTime = new Date().getTime() - time; 171 info('The time to load the first CPU Idle0 data is: ', durTime); 172 }; 173 174 initSchedulingFreqData = async (progress: Function): Promise<void> => { 175 let time = new Date().getTime(); 176 progress('CPU Scheduling Freq', 94); 177 procedurePool.submitWithName('logic0', 'scheduling-initFreqData', {}, undefined, (res: unknown) => {}); 178 let durTime = new Date().getTime() - time; 179 info('The time to load the first CPU Idle0 data is: ', durTime); 180 }; 181} 182