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 queryBootTime, 19 queryHeapGroupByEvent, 20 queryNativeHookProcess, 21 queryNativeHookStatisticsCount, 22 queryNativeMemoryRealTime, 23} from '../../database/SqlLite.js'; 24import { TraceRow } from '../trace/base/TraceRow.js'; 25import { info } from '../../../log/Log.js'; 26import { procedurePool } from '../../database/Procedure.js'; 27import { NativeEventHeap } from '../../bean/NativeHook.js'; 28import { HeapRender, HeapStruct } from '../../database/ui-worker/ProcedureWorkerHeap.js'; 29import { Utils } from '../trace/base/Utils.js'; 30import { renders } from '../../database/ui-worker/ProcedureWorker.js'; 31import { EmptyRender } from '../../database/ui-worker/ProcedureWorkerCPU.js'; 32 33export class SpNativeMemoryChart { 34 static EVENT_HEAP: Array<NativeEventHeap> = []; 35 static REAL_TIME_DIF: number = 0; 36 private trace: SpSystemTrace; 37 38 constructor(trace: SpSystemTrace) { 39 this.trace = trace; 40 } 41 42 initChart = async () => { 43 let time = new Date().getTime(); 44 let nativeMemoryType = 'native_hook'; 45 let nmsCount = await queryNativeHookStatisticsCount(); 46 if (nmsCount && nmsCount[0] && (nmsCount[0] as any).num > 0) { 47 nativeMemoryType = 'native_hook_statistic'; 48 } 49 let nativeProcess = await queryNativeHookProcess(nativeMemoryType); 50 info('NativeHook Process data size is: ', nativeProcess!.length); 51 if (nativeProcess.length == 0) { 52 return; 53 } 54 await this.initNativeMemory(); 55 SpNativeMemoryChart.EVENT_HEAP = await queryHeapGroupByEvent(nativeMemoryType); 56 let nativeRow = TraceRow.skeleton(); 57 let process = ''; 58 if (nativeProcess.length > 0) { 59 process = ` ${nativeProcess[0].pid}`; 60 } 61 nativeRow.rowId = `native-memory`; 62 nativeRow.index = 0; 63 nativeRow.rowType = TraceRow.ROW_TYPE_NATIVE_MEMORY; 64 nativeRow.drawType = 0; 65 nativeRow.style.height = '40px'; 66 nativeRow.rowParentId = ''; 67 nativeRow.folder = true; 68 nativeRow.name = `Native Memory` + process; 69 nativeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 70 nativeRow.selectChangeHandler = this.trace.selectChangeHandler; 71 nativeRow.rowSetting = 'enable'; 72 nativeRow.rowSettingPopoverDirection = 'bottomLeft'; 73 nativeRow.rowSettingList = [ 74 { 75 key: '0', 76 title: 'Current Bytes', 77 checked: true, 78 }, 79 { 80 key: '1', 81 title: 'Native Memory Density' 82 } 83 ] 84 nativeRow.onRowSettingChangeHandler = (value) => { 85 nativeRow.childrenList.forEach((row) => (row.drawType = parseInt(value[0]))); 86 this.trace.favoriteRowsEL?.querySelectorAll<TraceRow<any>>(`trace-row[row-type='heap']`).forEach((it) => { 87 it.drawType = parseInt(value[0]); 88 }); 89 this.trace.refreshCanvas(false); 90 } 91 nativeRow.supplier = () => new Promise<Array<any>>((resolve) => resolve([])); 92 nativeRow.onThreadHandler = (useCache) => { 93 nativeRow.canvasSave(this.trace.canvasPanelCtx!); 94 if (nativeRow.expansion) { 95 this.trace.canvasPanelCtx?.clearRect(0, 0, nativeRow.frame.width, nativeRow.frame.height); 96 } else { 97 (renders['empty'] as EmptyRender).renderMainThread( 98 { 99 context: this.trace.canvasPanelCtx, 100 useCache: useCache, 101 type: ``, 102 }, 103 nativeRow 104 ); 105 } 106 nativeRow.canvasRestore(this.trace.canvasPanelCtx!); 107 }; 108 this.trace.rowsEL?.appendChild(nativeRow); 109 /** 110 * 添加heap信息 111 */ 112 let native_memory = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM']; 113 for (let i = 0; i < native_memory.length; i++) { 114 let nm = native_memory[i]; 115 let allHeapRow = TraceRow.skeleton<HeapStruct>(); 116 allHeapRow.index = i; 117 allHeapRow.rowParentId = `native-memory`; 118 allHeapRow.rowHidden = !nativeRow.expansion; 119 allHeapRow.style.height = '40px'; 120 allHeapRow.name = nm; 121 allHeapRow.rowId = nm; 122 allHeapRow.drawType = 0; 123 allHeapRow.isHover = true; 124 allHeapRow.folder = false; 125 allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP; 126 allHeapRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 127 allHeapRow.selectChangeHandler = this.trace.selectChangeHandler; 128 allHeapRow.setAttribute('heap-type', nativeMemoryType); 129 allHeapRow.setAttribute('children', ''); 130 allHeapRow.focusHandler = () => { 131 let tip = ''; 132 if (HeapStruct.hoverHeapStruct) { 133 if (allHeapRow.drawType === 1) { 134 tip = `<span>${HeapStruct.hoverHeapStruct.density}</span>`; 135 } else { 136 tip = `<span>${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}</span>`; 137 } 138 } 139 this.trace?.displayTip(allHeapRow, HeapStruct.hoverHeapStruct, tip); 140 }; 141 allHeapRow.supplier = () => { 142 return nativeMemoryType === 'native_hook' 143 ? this.getNativeMemoryDataByChartType(i, allHeapRow.drawType) 144 : this.getNativeMemoryStatisticByChartType(i - 1); 145 }; 146 allHeapRow.onThreadHandler = (useCache) => { 147 let context = allHeapRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 148 allHeapRow.canvasSave(context); 149 (renders['heap'] as HeapRender).renderMainThread( 150 { 151 context: context, 152 useCache: useCache, 153 type: `heap`, 154 }, 155 allHeapRow 156 ); 157 allHeapRow.canvasRestore(context); 158 }; 159 nativeRow.addChildTraceRow(allHeapRow); 160 } 161 let durTime = new Date().getTime() - time; 162 info('The time to load the Native Memory data is: ', durTime); 163 }; 164 165 getNativeMemoryStatisticByChartType = async (chartType: number): Promise<Array<HeapStruct>> => { 166 let nmStatisticArray: Array<HeapStruct> = []; 167 await new Promise<Array<HeapStruct>>((resolve, reject) => { 168 procedurePool.submitWithName( 169 'logic1', 170 'native-memory-queryNativeHookStatistic', 171 { type: chartType, totalNS: TraceRow.range?.totalNS! }, 172 undefined, 173 (res: any) => { 174 nmStatisticArray = nmStatisticArray.concat(res.data); 175 res.data = null; 176 if (res.tag == 'end') { 177 resolve(nmStatisticArray); 178 } 179 } 180 ); 181 }); 182 return nmStatisticArray; 183 }; 184 185 getNativeMemoryDataByChartType = async (nativeMemoryType: number, chartType: number): Promise<Array<HeapStruct>> => { 186 let args = new Map<string, any>(); 187 args.set('nativeMemoryType', nativeMemoryType); 188 args.set('chartType', chartType); 189 args.set('totalNS', TraceRow.range?.totalNS!); 190 args.set('actionType', 'memory-chart'); 191 let nmArray: Array<HeapStruct> = []; 192 await new Promise<Array<HeapStruct>>((resolve, reject) => { 193 procedurePool.submitWithName('logic1', 'native-memory-chart-action', args, undefined, (res: any) => { 194 nmArray = nmArray.concat(res.data); 195 res.data = null; 196 if (res.tag == 'end') { 197 resolve(nmArray); 198 } 199 }); 200 }); 201 return nmArray; 202 }; 203 204 initNativeMemory = async () => { 205 let time = new Date().getTime(); 206 let isRealtime = false; 207 let realTimeDif = 0; 208 SpNativeMemoryChart.REAL_TIME_DIF = 0; 209 let queryTime = await queryNativeMemoryRealTime(); 210 let bootTime = await queryBootTime(); 211 if (queryTime.length > 0) { 212 isRealtime = queryTime[0].clock_name == 'realtime'; 213 } 214 if (bootTime.length > 0 && isRealtime) { 215 realTimeDif = queryTime[0].ts - bootTime[0].ts; 216 SpNativeMemoryChart.REAL_TIME_DIF = realTimeDif; 217 } 218 await new Promise<any>((resolve, reject) => { 219 procedurePool.submitWithName( 220 'logic1', 221 'native-memory-init', 222 { isRealtime, realTimeDif, dataDict: SpSystemTrace.DATA_DICT }, 223 undefined, 224 (res: any) => { 225 resolve(res); 226 } 227 ); 228 }); 229 let durTime = new Date().getTime() - time; 230 info('The time to init the native memory data is: ', durTime); 231 }; 232} 233