1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ci 16fb726d48Sopenharmony_ciimport { SpSystemTrace } from '../SpSystemTrace'; 17fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow'; 18fb726d48Sopenharmony_ciimport { info } from '../../../log/Log'; 19fb726d48Sopenharmony_ciimport { procedurePool } from '../../database/Procedure'; 20fb726d48Sopenharmony_ciimport { type NativeEventHeap } from '../../bean/NativeHook'; 21fb726d48Sopenharmony_ciimport { HeapRender, HeapStruct } from '../../database/ui-worker/ProcedureWorkerHeap'; 22fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils'; 23fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker'; 24fb726d48Sopenharmony_ciimport { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 25fb726d48Sopenharmony_ciimport { type BaseStruct } from '../../bean/BaseStruct'; 26fb726d48Sopenharmony_ciimport { 27fb726d48Sopenharmony_ci nativeMemoryChartDataCacheSender, 28fb726d48Sopenharmony_ci nativeMemoryChartDataSender, 29fb726d48Sopenharmony_ci} from '../../database/data-trafic/NativeMemoryDataSender'; 30fb726d48Sopenharmony_ciimport { queryNativeHookProcess, queryNativeHookStatisticsCount } from '../../database/sql/NativeHook.sql'; 31fb726d48Sopenharmony_ciimport { queryHeapGroupByEvent } from '../../database/sql/SqlLite.sql'; 32fb726d48Sopenharmony_ciimport { queryNativeMemoryRealTime } from '../../database/sql/Memory.sql'; 33fb726d48Sopenharmony_ciimport { queryBootTime } from '../../database/sql/Clock.sql'; 34fb726d48Sopenharmony_ciimport { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; 35fb726d48Sopenharmony_ci 36fb726d48Sopenharmony_ciexport class SpNativeMemoryChart { 37fb726d48Sopenharmony_ci static EVENT_HEAP: Array<NativeEventHeap> = []; 38fb726d48Sopenharmony_ci static REAL_TIME_DIF: number = 0; 39fb726d48Sopenharmony_ci private trace: SpSystemTrace; 40fb726d48Sopenharmony_ci 41fb726d48Sopenharmony_ci constructor(trace: SpSystemTrace) { 42fb726d48Sopenharmony_ci this.trace = trace; 43fb726d48Sopenharmony_ci } 44fb726d48Sopenharmony_ci 45fb726d48Sopenharmony_ci folderThreadHandler(row: TraceRow<BaseStruct>): void { 46fb726d48Sopenharmony_ci row.onThreadHandler = (useCache): void => { 47fb726d48Sopenharmony_ci row.canvasSave(this.trace.canvasPanelCtx!); 48fb726d48Sopenharmony_ci if (row.expansion) { 49fb726d48Sopenharmony_ci // @ts-ignore 50fb726d48Sopenharmony_ci this.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); 51fb726d48Sopenharmony_ci } else { 52fb726d48Sopenharmony_ci (renders.empty as EmptyRender).renderMainThread( 53fb726d48Sopenharmony_ci { 54fb726d48Sopenharmony_ci context: this.trace.canvasPanelCtx, 55fb726d48Sopenharmony_ci useCache: useCache, 56fb726d48Sopenharmony_ci type: '', 57fb726d48Sopenharmony_ci }, 58fb726d48Sopenharmony_ci row 59fb726d48Sopenharmony_ci ); 60fb726d48Sopenharmony_ci } 61fb726d48Sopenharmony_ci row.canvasRestore(this.trace.canvasPanelCtx!, this.trace); 62fb726d48Sopenharmony_ci }; 63fb726d48Sopenharmony_ci } 64fb726d48Sopenharmony_ci 65fb726d48Sopenharmony_ci chartThreadHandler(row: TraceRow<HeapStruct>): void { 66fb726d48Sopenharmony_ci row.onThreadHandler = (useCache): void => { 67fb726d48Sopenharmony_ci let context: CanvasRenderingContext2D; 68fb726d48Sopenharmony_ci if (row.currentContext) { 69fb726d48Sopenharmony_ci context = row.currentContext; 70fb726d48Sopenharmony_ci } else { 71fb726d48Sopenharmony_ci context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 72fb726d48Sopenharmony_ci } 73fb726d48Sopenharmony_ci row.canvasSave(context); 74fb726d48Sopenharmony_ci (renders.heap as HeapRender).renderMainThread( 75fb726d48Sopenharmony_ci { 76fb726d48Sopenharmony_ci context: context, 77fb726d48Sopenharmony_ci useCache: useCache, 78fb726d48Sopenharmony_ci type: 'heap', 79fb726d48Sopenharmony_ci }, 80fb726d48Sopenharmony_ci row 81fb726d48Sopenharmony_ci ); 82fb726d48Sopenharmony_ci row.canvasRestore(context, this.trace); 83fb726d48Sopenharmony_ci }; 84fb726d48Sopenharmony_ci } 85fb726d48Sopenharmony_ci 86fb726d48Sopenharmony_ci initNativeMemoryFolder(process: number, ipid: number): TraceRow<BaseStruct> { 87fb726d48Sopenharmony_ci const nativeRow = TraceRow.skeleton(); 88fb726d48Sopenharmony_ci nativeRow.rowId = `native-memory ${process} ${ipid}`; 89fb726d48Sopenharmony_ci nativeRow.index = 0; 90fb726d48Sopenharmony_ci nativeRow.rowType = TraceRow.ROW_TYPE_NATIVE_MEMORY; 91fb726d48Sopenharmony_ci nativeRow.drawType = 0; 92fb726d48Sopenharmony_ci nativeRow.style.height = '40px'; 93fb726d48Sopenharmony_ci nativeRow.rowParentId = ''; 94fb726d48Sopenharmony_ci nativeRow.folder = true; 95fb726d48Sopenharmony_ci nativeRow.addTemplateTypes('NativeMemory', 'Memory'); 96fb726d48Sopenharmony_ci nativeRow.name = `Native Memory (${process})`; 97fb726d48Sopenharmony_ci nativeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 98fb726d48Sopenharmony_ci nativeRow.selectChangeHandler = this.trace.selectChangeHandler; 99fb726d48Sopenharmony_ci nativeRow.addRowSettingPop(); 100fb726d48Sopenharmony_ci nativeRow.rowSetting = 'enable'; 101fb726d48Sopenharmony_ci nativeRow.rowSettingPopoverDirection = 'bottomLeft'; 102fb726d48Sopenharmony_ci nativeRow.rowSettingList = [ 103fb726d48Sopenharmony_ci { 104fb726d48Sopenharmony_ci key: '0', 105fb726d48Sopenharmony_ci title: 'Current Bytes', 106fb726d48Sopenharmony_ci checked: true, 107fb726d48Sopenharmony_ci }, 108fb726d48Sopenharmony_ci { 109fb726d48Sopenharmony_ci key: '1', 110fb726d48Sopenharmony_ci title: 'Native Memory Density', 111fb726d48Sopenharmony_ci }, 112fb726d48Sopenharmony_ci ]; 113fb726d48Sopenharmony_ci nativeRow.onRowSettingChangeHandler = (value): void => { 114fb726d48Sopenharmony_ci nativeRow.childrenList.forEach((row) => (row.drawType = parseInt(value[0]))); 115fb726d48Sopenharmony_ci this.trace 116fb726d48Sopenharmony_ci .getCollectRows((row) => row.rowType === 'heap') 117fb726d48Sopenharmony_ci .forEach((it) => { 118fb726d48Sopenharmony_ci it.drawType = parseInt(value[0]); 119fb726d48Sopenharmony_ci }); 120fb726d48Sopenharmony_ci this.trace.refreshCanvas(false); 121fb726d48Sopenharmony_ci }; 122fb726d48Sopenharmony_ci nativeRow.supplier = (): Promise<BaseStruct[]> => new Promise<Array<BaseStruct>>((resolve) => resolve([])); 123fb726d48Sopenharmony_ci this.folderThreadHandler(nativeRow); 124fb726d48Sopenharmony_ci this.trace.rowsEL?.appendChild(nativeRow); 125fb726d48Sopenharmony_ci return nativeRow; 126fb726d48Sopenharmony_ci } 127fb726d48Sopenharmony_ci 128fb726d48Sopenharmony_ci initAllocMapChart(folder: TraceRow<BaseStruct>, type: string, process: { pid: number; ipid: number }): void { 129fb726d48Sopenharmony_ci const chartList = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM']; 130fb726d48Sopenharmony_ci for (let i = 0; i < chartList.length; i++) { 131fb726d48Sopenharmony_ci const nm = chartList[i]; 132fb726d48Sopenharmony_ci const allHeapRow = TraceRow.skeleton<HeapStruct>(); 133fb726d48Sopenharmony_ci allHeapRow.index = i; 134fb726d48Sopenharmony_ci allHeapRow.rowParentId = `native-memory ${process.pid} ${process.ipid}`; 135fb726d48Sopenharmony_ci allHeapRow.rowHidden = !folder.expansion; 136fb726d48Sopenharmony_ci allHeapRow.style.height = '40px'; 137fb726d48Sopenharmony_ci allHeapRow.name = nm; 138fb726d48Sopenharmony_ci allHeapRow.rowId = nm; 139fb726d48Sopenharmony_ci allHeapRow.drawType = 0; 140fb726d48Sopenharmony_ci allHeapRow.isHover = true; 141fb726d48Sopenharmony_ci allHeapRow.folder = false; 142fb726d48Sopenharmony_ci allHeapRow.rowType = TraceRow.ROW_TYPE_HEAP; 143fb726d48Sopenharmony_ci allHeapRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 144fb726d48Sopenharmony_ci allHeapRow.selectChangeHandler = this.trace.selectChangeHandler; 145fb726d48Sopenharmony_ci allHeapRow.setAttribute('heap-type', type); 146fb726d48Sopenharmony_ci allHeapRow.setAttribute('children', ''); 147fb726d48Sopenharmony_ci allHeapRow.focusHandler = (): void => { 148fb726d48Sopenharmony_ci let tip = ''; 149fb726d48Sopenharmony_ci if (HeapStruct.hoverHeapStruct) { 150fb726d48Sopenharmony_ci if (allHeapRow.drawType === 1) { 151fb726d48Sopenharmony_ci tip = `<span>${HeapStruct.hoverHeapStruct.density}</span>`; 152fb726d48Sopenharmony_ci } else { 153fb726d48Sopenharmony_ci tip = `<span>${Utils.getByteWithUnit(HeapStruct.hoverHeapStruct.heapsize!)}</span>`; 154fb726d48Sopenharmony_ci } 155fb726d48Sopenharmony_ci } 156fb726d48Sopenharmony_ci this.trace?.displayTip(allHeapRow, HeapStruct.hoverHeapStruct, tip); 157fb726d48Sopenharmony_ci }; 158fb726d48Sopenharmony_ci allHeapRow.findHoverStruct = (): void => { 159fb726d48Sopenharmony_ci HeapStruct.hoverHeapStruct = allHeapRow.getHoverStruct(); 160fb726d48Sopenharmony_ci }; //@ts-ignore 161fb726d48Sopenharmony_ci allHeapRow.supplierFrame = (): Promise<unknown> => 162fb726d48Sopenharmony_ci nativeMemoryChartDataSender(allHeapRow, { 163fb726d48Sopenharmony_ci eventType: i, 164fb726d48Sopenharmony_ci ipid: process.ipid, 165fb726d48Sopenharmony_ci model: type, 166fb726d48Sopenharmony_ci drawType: allHeapRow.drawType, 167fb726d48Sopenharmony_ci }); 168fb726d48Sopenharmony_ci this.chartThreadHandler(allHeapRow); 169fb726d48Sopenharmony_ci folder.addChildTraceRow(allHeapRow); 170fb726d48Sopenharmony_ci } 171fb726d48Sopenharmony_ci } 172fb726d48Sopenharmony_ci 173fb726d48Sopenharmony_ci initChart = async (): Promise<void> => { 174fb726d48Sopenharmony_ci let time = new Date().getTime(); 175fb726d48Sopenharmony_ci let nativeMemoryType = 'native_hook'; 176fb726d48Sopenharmony_ci let nmsCount = await queryNativeHookStatisticsCount(); 177fb726d48Sopenharmony_ci if (nmsCount && nmsCount[0] && nmsCount[0].num > 0) { 178fb726d48Sopenharmony_ci nativeMemoryType = 'native_hook_statistic'; 179fb726d48Sopenharmony_ci } 180fb726d48Sopenharmony_ci let nativeProcess = await queryNativeHookProcess(nativeMemoryType); 181fb726d48Sopenharmony_ci info('NativeHook Process data size is: ', nativeProcess!.length); 182fb726d48Sopenharmony_ci if (nativeProcess.length === 0) { 183fb726d48Sopenharmony_ci return; 184fb726d48Sopenharmony_ci } 185fb726d48Sopenharmony_ci // 有native_memory进程,统计nativehook插件 186fb726d48Sopenharmony_ci let requestBody = { 187fb726d48Sopenharmony_ci eventData: { 188fb726d48Sopenharmony_ci plugin: ['nativehook'] 189fb726d48Sopenharmony_ci } 190fb726d48Sopenharmony_ci }; 191fb726d48Sopenharmony_ci SpStatisticsHttpUtil.recordPluginUsage(requestBody); 192fb726d48Sopenharmony_ci await this.initNativeMemory(); 193fb726d48Sopenharmony_ci await nativeMemoryChartDataCacheSender( 194fb726d48Sopenharmony_ci nativeProcess.map((it) => it.ipid), 195fb726d48Sopenharmony_ci nativeMemoryType 196fb726d48Sopenharmony_ci ); 197fb726d48Sopenharmony_ci SpNativeMemoryChart.EVENT_HEAP = await queryHeapGroupByEvent(nativeMemoryType); 198fb726d48Sopenharmony_ci for (const process of nativeProcess) { 199fb726d48Sopenharmony_ci const nativeRow = this.initNativeMemoryFolder(process.pid, process.ipid); 200fb726d48Sopenharmony_ci this.initAllocMapChart(nativeRow, nativeMemoryType, process); 201fb726d48Sopenharmony_ci } 202fb726d48Sopenharmony_ci let durTime = new Date().getTime() - time; 203fb726d48Sopenharmony_ci info('The time to load the Native Memory data is: ', durTime); 204fb726d48Sopenharmony_ci }; 205fb726d48Sopenharmony_ci 206fb726d48Sopenharmony_ci initNativeMemory = async (): Promise<void> => { 207fb726d48Sopenharmony_ci let time = new Date().getTime(); 208fb726d48Sopenharmony_ci let isRealtime = false; 209fb726d48Sopenharmony_ci let realTimeDif = 0; 210fb726d48Sopenharmony_ci SpNativeMemoryChart.REAL_TIME_DIF = 0; 211fb726d48Sopenharmony_ci let queryTime = await queryNativeMemoryRealTime(); 212fb726d48Sopenharmony_ci let bootTime = await queryBootTime(); 213fb726d48Sopenharmony_ci if (queryTime.length > 0) { 214fb726d48Sopenharmony_ci //@ts-ignore 215fb726d48Sopenharmony_ci isRealtime = queryTime[0].clock_name === 'realtime'; 216fb726d48Sopenharmony_ci } 217fb726d48Sopenharmony_ci if (bootTime.length > 0 && isRealtime) { 218fb726d48Sopenharmony_ci //@ts-ignore 219fb726d48Sopenharmony_ci realTimeDif = queryTime[0].ts - bootTime[0].ts; 220fb726d48Sopenharmony_ci SpNativeMemoryChart.REAL_TIME_DIF = realTimeDif; 221fb726d48Sopenharmony_ci } 222fb726d48Sopenharmony_ci await new Promise<unknown>((resolve) => { 223fb726d48Sopenharmony_ci procedurePool.submitWithName( 224fb726d48Sopenharmony_ci 'logic0', 225fb726d48Sopenharmony_ci 'native-memory-init', 226fb726d48Sopenharmony_ci { isRealtime, realTimeDif }, 227fb726d48Sopenharmony_ci undefined, 228fb726d48Sopenharmony_ci (res: unknown) => { 229fb726d48Sopenharmony_ci resolve(res); 230fb726d48Sopenharmony_ci } 231fb726d48Sopenharmony_ci ); 232fb726d48Sopenharmony_ci }); 233fb726d48Sopenharmony_ci let durTime = new Date().getTime() - time; 234fb726d48Sopenharmony_ci info('The time to init the native memory data is: ', durTime); 235fb726d48Sopenharmony_ci }; 236fb726d48Sopenharmony_ci} 237