From a4dec6b63b4e094b0242a120cd45c80e4da70473 Mon Sep 17 00:00:00 2001 From: zhangzepeng Date: Mon, 30 Oct 2023 14:17:53 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E2=80=99fix:=E4=BF=AE=E5=A4=8Dhilog?= =?UTF-8?q?=E7=9A=84Table=E5=9C=A8=E7=82=B9=E5=87=BB=E6=97=B6=E5=8D=A1?= =?UTF-8?q?=E6=AD=BB=E7=9A=84=E9=97=AE=E9=A2=98=E2=80=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangzepeng --- ide/src/base-ui/table/lit-table.ts | 1 - ide/src/trace/bean/perfStruct.ts | 55 --- ide/src/trace/component/SpSystemTrace.ts | 71 ++-- ide/src/trace/component/chart/SpHiPerf.ts | 169 -------- .../trace/component/trace/base/TraceRow.ts | 3 +- .../component/trace/base/TraceSheetConfig.ts | 19 - .../trace/component/trace/search/Search.ts | 19 +- .../component/trace/sheet/TabPaneFilter.ts | 55 ++- .../trace/sheet/cpu/TabPaneFrequencySample.ts | 3 - .../sheet/frequsage/TabPaneFreqDataCut.ts | 394 ------------------ .../trace/sheet/frequsage/TabPaneFreqUsage.ts | 181 -------- .../trace/sheet/hilog/TabPaneHiLogs.ts | 2 +- .../trace/sheet/hiperf/TabPerfBinaryTree.ts | 233 ----------- .../trace/sheet/hiperf/TabPerfProfile.ts | 70 ++-- ide/src/trace/database/SqlLite.ts | 103 +---- .../ProcedureLogicWorkerCommon.ts | 22 - .../logic-worker/ProcedureLogicWorkerPerf.ts | 191 +-------- .../database/ui-worker/ProcedureWorker.ts | 2 - .../ProcedureWorkerHiPerfCallChart.ts | 202 --------- 19 files changed, 107 insertions(+), 1688 deletions(-) delete mode 100644 ide/src/trace/bean/perfStruct.ts delete mode 100644 ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts delete mode 100644 ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts delete mode 100644 ide/src/trace/component/trace/sheet/hiperf/TabPerfBinaryTree.ts delete mode 100644 ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCallChart.ts diff --git a/ide/src/base-ui/table/lit-table.ts b/ide/src/base-ui/table/lit-table.ts index 4b46b866..0070821a 100644 --- a/ide/src/base-ui/table/lit-table.ts +++ b/ide/src/base-ui/table/lit-table.ts @@ -247,7 +247,6 @@ export class LitTable extends HTMLElement { transition: opacity 0.2s; outline: none; position: relative; - overflow: hidden; } .button-icon:active { background: var(--dark-background1,#f5f5f5) diff --git a/ide/src/trace/bean/perfStruct.ts b/ide/src/trace/bean/perfStruct.ts deleted file mode 100644 index 80345f1c..00000000 --- a/ide/src/trace/bean/perfStruct.ts +++ /dev/null @@ -1,55 +0,0 @@ -const ROW_TYPE = 'hiperf'; - - -export class perfFireChartStruct { - thread_id:number; - name: string; - depth: number; - selfTime: number; - totalTime: number; - id: number; - - constructor( - id: number, - name: string, - depth: number, - selfTime: number, - totalTime: number, - thread_id:number, - ) { - this.id = id; - this.name = name; - this.depth = depth; - this.selfTime = selfTime; - this.totalTime = totalTime; - this.thread_id = thread_id; - } -} - -// 绘图所需树结构模板 -export class hiPerfchartFrame extends perfFireChartStruct { - startTime: number; - endTime: number; - children: Array; - isSelect: boolean = false; - line: number = 0; - column: number = 0; - thread_id: number=0; - - constructor( - id: number, - name: string, - startTime: number, - endTime: number, - totalTime: number, - depth: number, - thread_id:number, - ) { - super(id, name, depth, 0, totalTime,thread_id); - this.id = id; - this.startTime = startTime; - this.endTime = endTime; - this.thread_id = thread_id; - this.children = new Array(); - } -} \ No newline at end of file diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index 4c25011f..cea324a2 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -103,7 +103,6 @@ import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample.js' import { LitSearch } from './trace/search/Search.js'; import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag.js'; import { LitTabpane } from '../../base-ui/tabs/lit-tabpane.js'; -import { HiPerfCallChartStruct } from '../database/ui-worker/ProcedureWorkerHiPerfCallChart.js'; function dpr() { return window.devicePixelRatio || 1; @@ -734,8 +733,8 @@ export class SpSystemTrace extends BaseElement { let isIntersect = (filterFunc: FuncStruct, rangeData: RangeSelectStruct) => Math.max(filterFunc.startTs! + filterFunc.dur!, rangeData!.endNS || 0) - - Math.min(filterFunc.startTs!, rangeData!.startNS || 0) < - filterFunc.dur! + (rangeData!.endNS || 0) - (rangeData!.startNS || 0) && + Math.min(filterFunc.startTs!, rangeData!.startNS || 0) < + filterFunc.dur! + (rangeData!.endNS || 0) - (rangeData!.startNS || 0) && filterFunc.funName!.indexOf('H:Task ') >= 0; let taskData = it.dataList.filter((taskData: FuncStruct) => { taskData!.tid = parseInt(it.rowId!); @@ -1091,7 +1090,7 @@ export class SpSystemTrace extends BaseElement { } else if (it.rowType == TraceRow.ROW_TYPE_JANK) { let isIntersect = (filterJank: JanksStruct, rangeData: RangeSelectStruct) => Math.max(filterJank.ts! + filterJank.dur!, rangeData!.endNS || 0) - - Math.min(filterJank.ts!, rangeData!.startNS || 0) < + Math.min(filterJank.ts!, rangeData!.startNS || 0) < filterJank.dur! + (rangeData!.endNS || 0) - (rangeData!.startNS || 0); if (it.name == 'Actual Timeline') { selection.jankFramesData = []; @@ -1174,7 +1173,7 @@ export class SpSystemTrace extends BaseElement { } else if (it.rowType == TraceRow.ROW_TYPE_FRAME_ANIMATION) { let isIntersect = (animationStruct: FrameAnimationStruct, selectStruct: RangeSelectStruct) => Math.max(animationStruct.startTs! + animationStruct.dur!, selectStruct!.endNS || 0) - - Math.min(animationStruct.startTs!, selectStruct!.startNS || 0) < + Math.min(animationStruct.startTs!, selectStruct!.startNS || 0) < animationStruct.dur! + (selectStruct!.endNS || 0) - (selectStruct!.startNS || 0); let frameAnimationList = it.dataList.filter((frameAnimationBean: FrameAnimationStruct) => { return isIntersect(frameAnimationBean, TraceRow.rangeSelectObject!); @@ -1348,7 +1347,7 @@ export class SpSystemTrace extends BaseElement { window.subscribe(window.SmartEvent.UI.SliceMark, (data) => { this.sliceMarkEventHandler(data); }); - window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => { }); + window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => {}); window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => { this.refreshCanvas(false); }); @@ -1720,10 +1719,10 @@ export class SpSystemTrace extends BaseElement { ev.stopPropagation(); return; } - this.isMouseLeftDown = true; if (ev.ctrlKey) { ev.preventDefault(); - this.style.cursor = 'move'; + this.style.cursor = 'move'; + this.isMouseLeftDown = true; this.mouseCurrentPosition = ev.clientX; return; } @@ -1776,12 +1775,11 @@ export class SpSystemTrace extends BaseElement { ev.stopPropagation(); return; } - - this.isMouseLeftDown = false; if (ev.ctrlKey) { ev.preventDefault(); this.offsetMouse = 0; - this.mouseCurrentPosition = 0; + this.mouseCurrentPosition = 0; + this.isMouseLeftDown = false; this.style.cursor = 'default'; return; } @@ -1802,7 +1800,7 @@ export class SpSystemTrace extends BaseElement { // 如果没有找到帽子,则绘制一个旗子 let time = Math.round( (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / this.timerShaftEL!.canvas!.offsetWidth + - TraceRow.range?.startNS! + TraceRow.range?.startNS! ); this.timerShaftEL!.sportRuler!.drawTriangle(time, 'squre'); } @@ -1979,13 +1977,13 @@ export class SpSystemTrace extends BaseElement { this.timerShaftEL?.setSlicesMark( FrameAnimationStruct.selectFrameAnimationStruct.startTs || 0, (FrameAnimationStruct.selectFrameAnimationStruct.startTs || 0) + - (FrameAnimationStruct.selectFrameAnimationStruct.dur || 0) + (FrameAnimationStruct.selectFrameAnimationStruct.dur || 0) ); } else if (JsCpuProfilerStruct.selectJsCpuProfilerStruct) { this.timerShaftEL?.setSlicesMark( JsCpuProfilerStruct.selectJsCpuProfilerStruct.startTime || 0, (JsCpuProfilerStruct.selectJsCpuProfilerStruct.startTime || 0) + - (JsCpuProfilerStruct.selectJsCpuProfilerStruct.totalTime || 0) + (JsCpuProfilerStruct.selectJsCpuProfilerStruct.totalTime || 0) ); } else { this.slicestime = this.timerShaftEL?.setSlicesMark(); @@ -2474,11 +2472,6 @@ export class SpSystemTrace extends BaseElement { JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== null && JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== undefined, ], - [TraceRow.ROW_TYPE_PERF_CALLCHART, - ()=> - HiPerfCallChartStruct.hoverPerfCallCutStruct !==null && - HiPerfCallChartStruct.hoverPerfCallCutStruct !== undefined, - ], [ TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY, () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, @@ -2538,22 +2531,16 @@ export class SpSystemTrace extends BaseElement { this.selectStructNull(); // 判断点击的线程是否在唤醒树内 let timeoutJudge = setTimeout(() => { - if (SpSystemTrace.wakeupList.length && CpuStruct.selectCpuStruct) { - let checkHandlerKey:boolean = true; - let saveSelectCpuStruct:any = JSON.parse(sessionStorage.getItem('saveselectcpustruct')!) + if (SpSystemTrace.wakeupList.length && CpuStruct.wakeupBean) { + let checkHandlerKey = true; for (const item of SpSystemTrace.wakeupList) { - if (item.ts === CpuStruct.selectCpuStruct.startTime && item.dur === CpuStruct.selectCpuStruct.dur) { + if (item.ts === CpuStruct.wakeupBean.ts && item.wakeupTime === CpuStruct.wakeupBean.wakeupTime) { checkHandlerKey = false; if (SpSystemTrace.wakeupList[0].schedulingDesc) { - SpSystemTrace.wakeupList.unshift(saveSelectCpuStruct) + SpSystemTrace.wakeupList.unshift(JSON.parse(sessionStorage.getItem('saveselectcpustruct')!)); } this.refreshCanvas(true); break; - }else if (saveSelectCpuStruct.startTime === CpuStruct.selectCpuStruct.startTime && saveSelectCpuStruct.dur === CpuStruct.selectCpuStruct.dur) { - // 如果点击的是第一层,保持唤醒树不变 - checkHandlerKey = false; - this.refreshCanvas(true) - break; } } // 点击线程在唤醒树内 @@ -2570,7 +2557,7 @@ export class SpSystemTrace extends BaseElement { this.refreshCanvas(true); } clearTimeout(timeoutJudge); - }, 10); + }, 500); let threadClickHandler: any; let threadClickPreviousHandler: any; let threadClickNextHandler: any; @@ -3947,17 +3934,13 @@ export class SpSystemTrace extends BaseElement { } } } else { - if(currentIndex==-1) { - findIndex=0 - }else{ - findIndex = structs.findIndex((it, idx) => { - return ( - idx > currentIndex && - it.startTime! >= TraceRow.range!.startNS && - it.startTime! + it.dur! <= TraceRow.range!.endNS - ); - }); - } + findIndex = structs.findIndex((it, idx) => { + return ( + idx > currentIndex && + it.startTime! >= TraceRow.range!.startNS && + it.startTime! + it.dur! <= TraceRow.range!.endNS + ); + }); } let findEntry: any; if (findIndex >= 0) { @@ -4254,8 +4237,8 @@ export class SpSystemTrace extends BaseElement { HeapDataInterface.getInstance().clearData(); procedurePool.clearCache(); Utils.clearData(); - procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => { }); - procedurePool.submitWithName('logic1', 'clear', {}, undefined, (res: any) => { }); + procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => {}); + procedurePool.submitWithName('logic1', 'clear', {}, undefined, (res: any) => {}); } init = async (param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) => { @@ -4412,7 +4395,7 @@ export class SpSystemTrace extends BaseElement { } if (this.tipEL) { this.tipEL.innerHTML = html; - if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER ||row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART) { + if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER) { this.tipEL.style.maxWidth = row.clientWidth / 3 + 'px'; this.tipEL.style.wordBreak = ' break-all'; this.tipEL.style.height = 'unset'; diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index 312fb102..6058aee8 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -28,7 +28,6 @@ import { import { Utils } from '../trace/base/Utils.js'; import { PerfThread } from '../../bean/PerfProfile.js'; import { HiperfCpuRender, HiPerfCpuStruct } from '../../database/ui-worker/ProcedureWorkerHiPerfCPU.js'; -import { HiperfCallChartRender, HiPerfCallChartStruct } from '../../database/ui-worker/ProcedureWorkerHiPerfCallChart.js'; import { HiperfThreadRender, HiPerfThreadStruct } from '../../database/ui-worker/ProcedureWorkerHiPerfThread.js'; import { HiperfProcessRender, HiPerfProcessStruct } from '../../database/ui-worker/ProcedureWorkerHiPerfProcess.js'; import { info } from '../../../log/Log.js'; @@ -38,8 +37,6 @@ import { renders } from '../../database/ui-worker/ProcedureWorker.js'; import { EmptyRender } from '../../database/ui-worker/ProcedureWorkerCPU.js'; import { type HiPerfReportStruct } from '../../database/ui-worker/ProcedureWorkerHiPerfReport.js'; import { SpChartManager } from './SpChartManager.js'; -import { procedurePool } from '../../database/Procedure.js'; -import { hiPerfchartFrame } from '../../bean/perfStruct.js'; export interface ResultData { existA: boolean | null | undefined; @@ -61,10 +58,6 @@ export class SpHiPerf { private group: any; private rowList: TraceRow[] | undefined; private eventTypeList: Array<{ id: number; report_value: string }> = []; - private allCombineDataMap = new Map(); - - public perfCallDataList: any = []; - public threadDataList: any = []; constructor(trace: SpSystemTrace) { this.trace = trace; @@ -77,14 +70,10 @@ export class SpHiPerf { this.eventTypeList = await queryHiPerfEventList(); info('PerfThread Data size is: ', this.perfThreads!.length); this.group = Utils.groupBy(this.perfThreads || [], 'pid'); - Reflect.ownKeys(this.group).forEach((v, i) => { - this.threadDataList.push((this.group[v] as Array).filter((item: any) => { return item.pid === item.tid })[0]) - }) this.cpuData = await queryHiPerfCpuMergeData2(); this.maxCpuId = this.cpuData.length > 0 ? this.cpuData[0].cpu_id : -Infinity; if (this.cpuData.length > 0) { await this.initFolder(); - await this.initCallChart() await this.initCpuMerge(); await this.initCpu(); await this.initProcess(); @@ -202,39 +191,6 @@ export class SpHiPerf { this.rowList?.push(cpuMergeRow); } - // callchart泳道 - async initCallChart() { - let perfCallCutRow = TraceRow.skeleton(); - perfCallCutRow.rowId = `HiPerf-callchart`; - perfCallCutRow.index = 0; - perfCallCutRow.rowType = TraceRow.ROW_TYPE_PERF_CALLCHART; - perfCallCutRow.rowParentId = 'HiPerf'; - perfCallCutRow.rowHidden = !this.rowFolder.expansion; - perfCallCutRow.folder = false; - perfCallCutRow.name = 'callchart'; - perfCallCutRow.setAttribute('children', ''); - perfCallCutRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - perfCallCutRow.selectChangeHandler = this.trace.selectChangeHandler; - this.rowFolder.addChildTraceRow(perfCallCutRow); - perfCallCutRow.focusHandler = (): void => { - this.trace?.displayTip( - perfCallCutRow!, - HiPerfCallChartStruct.hoverPerfCallCutStruct, - `Name: - ${HiPerfCallChartStruct.hoverPerfCallCutStruct?.name || ''}
- Self Time: - ${HiPerfCallChartStruct.hoverPerfCallCutStruct?.totalTime || ''}
- Event Type: - ${HiPerfCallChartStruct.hoverPerfCallCutStruct?.totalTime || ''}
` - ); - }; - this.rowList?.push(perfCallCutRow); - perfCallCutRow.findHoverStruct = () => { - HiPerfCallChartStruct.hoverPerfCallCutStruct = perfCallCutRow.getHoverStruct(); - }; - await this.setCallTotalRow(perfCallCutRow, this.cpuData, this.threadDataList); - } - async initCpu() { for (let i = 0; i <= this.maxCpuId; i++) { let perfCpuRow = TraceRow.skeleton(); @@ -379,131 +335,6 @@ export class SpHiPerf { }); } - // callchart级联单选按钮 - async setCallTotalRow(row: any, cpuData: any = Array, threadData: any = Array) { - row.addTemplateTypes('Hiperf-callchart'); - row.rowSetting = 'enable'; - row.rowSettingList = [ - { - key: "cpu", - title: 'cpu', - children: [ - ...cpuData.reverse().map( - ( - it: any - ): { - key: string; - title: string; - } => { - return { - key: `${it.cpu_id}c`, - title: `cpu${it.cpu_id}`, - }; - } - ), - ] - }, - { - key: "thread", - title: 'thread', - children: [ - ...threadData.map( - (it: any): { - key: string; - title: string; - } => { - return { - key: `${it.tid}t`, - title: `${it.threadName || 'thread'}[${it.tid}] ` - } - } - ) - ] - } - - ]; - row.onRowSettingChangeHandler = (setting: any): void => { - if (setting && setting.length > 0) { - // 0:cpu,1:thread - this.initHiPerfChartData(setting[0].indexOf('c') > -1 ? 0 : 1, Number(setting[0].indexOf('c') > -1 ? - setting[0].substring(0, setting[0].indexOf('c')) : setting[0].substring(0, setting[0].indexOf('t'))), row); - row.name = `callchart[${setting[0].indexOf('c') > -1 ? 'cpu' : 'thread'}${setting[0].substring(0, setting[0].length - 1)}]`; - } - row.clearCanvas(); - row.onThreadHandler = (useCache: any) => { - row.dataList = this.perfCallDataList; - let context: CanvasRenderingContext2D; - if (row.currentContext) { - context = row.currentContext; - } else { - context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - row.canvasSave(context); - (renders['Hiperf-callchart'] as HiperfCallChartRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `Hiperf-callchart`, - }, - row - ); - row.canvasRestore(context); - }; - }; - } - - /* - * callchart请求数据 - */ - async initHiPerfChartData(type: number, id: number, perfCpuRow: any) { - await procedurePool.submitWithName( - 'logic0', - 'perf-fire', - [ - type, id - ], - undefined, - (res: Array) => { - let allCombineData: Array = []; - this.getAllCombineData(res, allCombineData); - this.allCombineDataMap = new Map(); - for (let data of allCombineData) { - this.allCombineDataMap.set(data.id, data); - } - // let max = Math.max(...allCombineData.map((it) => it.depth || 0)) + 1; - let max = 0; - for (let i = 0; i < allCombineData.length; i++) { - if (allCombineData[i].depth > max) { - max = allCombineData[i].depth - } else { - - } - i++; - } - let maxHeight = max * 20; - perfCpuRow!.style.height = `${maxHeight}px`; - perfCpuRow.supplier = (): Promise> => - new Promise>((resolve) => resolve(allCombineData)); - this.perfCallDataList = allCombineData - } - ) - } - - getAllCombineData( - combineData: Array, - allCombineData: Array - ): void { - for (let data of combineData) { - if (data.name != 'name') { - allCombineData.push(data); - } - if (data.children && data.children.length > 0) { - this.getAllCombineData(data.children, allCombineData); - } - } - } - - updateChartData() { this.rowList?.forEach((it) => { it.dataList = []; diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 0bde914f..5852e647 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -55,7 +55,6 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_NATIVE_MEMORY = 'native-memory'; static ROW_TYPE_HIPERF = 'hiperf'; static ROW_TYPE_DELIVER_INPUT_EVENT = 'DeliverInputEvent'; - static ROW_TYPE_PERF_CALLCHART = 'Hiperf-callchart'; static ROW_TYPE_HIPERF_CPU = 'hiperf-cpu'; static ROW_TYPE_HIPERF_PROCESS = 'hiperf-process'; static ROW_TYPE_HIPERF_THREAD = 'hiperf-thread'; @@ -679,7 +678,7 @@ export class TraceRow extends HTMLElement { this.funcExpand = true; this.nameEL!.onclick = () => { - if (this.rowType === TraceRow.ROW_TYPE_FUNC || TraceRow.ROW_TYPE_PERF_CALLCHART) { + if (this.rowType === TraceRow.ROW_TYPE_FUNC) { if (this.funcExpand) { this.funcMaxHeight = this.clientHeight; this.style.height = '20px'; diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index e636bc56..dcd8b04b 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -118,9 +118,6 @@ import { TabPaneHiLogSummary } from '../sheet/hilog/TabPaneHiLogSummary.js'; import { TabPaneSchedPriority } from '../sheet/cpu/TabPaneSchedPriority.js'; import { TabPaneGpuResourceVmTracker } from '../sheet/vmtracker/TabPaneGpuResourceVmTracker.js'; import { TabPaneGpuGraph } from '../sheet/gpu/TabPaneGraph.js'; -import { TabPaneFreqUsage } from '../sheet/frequsage/TabPaneFreqUsage.js'; -import { TabPaneFreqDataCut } from '../sheet/frequsage/TabPaneFreqDataCut.js'; -import { TabpanePerfBinaryTree } from '../sheet/hiperf/TabPerfBinaryTree.js'; export let tabConfig: any = { 'current-selection': { @@ -628,21 +625,5 @@ export let tabConfig: any = { title: 'M Selection', type: TabPaneCurrent, require: (param: SelectionParam) => param.isCurrentPane, - }, - 'tabpane-frequsage': { - title: 'Freq Usage', - type: TabPaneFreqUsage, - require: (param: SelectionParam) => param.threadIds.length > 0 && param.threadIds.length < 2, - }, - 'tabpane-freqdatacut': { - title: 'Freq DataCut', - type: TabPaneFreqDataCut, - require: (param: SelectionParam) => param.threadIds.length > 0 && param.threadIds.length < 2, - }, }, //current selection - 'box-perf-Binary': { - title: 'BinaryTree', - type: TabpanePerfBinaryTree, - require: (param: SelectionParam) => param.perfSampleIds.length > 0, - }, }; diff --git a/ide/src/trace/component/trace/search/Search.ts b/ide/src/trace/component/trace/search/Search.ts index 24454769..9f7fd245 100644 --- a/ide/src/trace/component/trace/search/Search.ts +++ b/ide/src/trace/component/trace/search/Search.ts @@ -34,7 +34,6 @@ export class LitSearch extends BaseElement { private searchELList: Array = []; //定义翻页index private retarget_index: number = 0; - private _retarge_index: HTMLInputElement | null | undefined; get list(): Array { return this._list; @@ -226,7 +225,7 @@ export class LitSearch extends BaseElement { this.indexEL = this.shadowRoot!.querySelector('#index'); this.searchHistoryListEL = this.shadowRoot!.querySelector('.search-history-list'); - this._retarge_index = this.shadowRoot!.querySelector("input[name='retarge_index']"); + let _retarge_index = this.shadowRoot!.querySelector("input[name='retarge_index']") let _root = this.shadowRoot!.querySelector(".root") let _prompt = this.shadowRoot!.querySelector("#prompt") @@ -238,11 +237,8 @@ export class LitSearch extends BaseElement { }); this.search!.addEventListener('change', (event) => { this.index = -1; - this._retarge_index!.value = "" }); this.search!.addEventListener('keyup', (e: KeyboardEvent) => { - this._retarge_index!.value = "" - this.index = -1; this.searchKeyupListener(e); }); this.shadowRoot?.querySelector('#arrow-left')?.addEventListener('click', (e) => { @@ -267,7 +263,7 @@ export class LitSearch extends BaseElement { // 添加翻页监听事件 this.shadowRoot?.querySelector("input[name='retarge_index']")?.addEventListener('keyup', (e: any) => { if (e.keyCode == 13) { - this.retarget_index = Number(this._retarge_index!.value) + this.retarget_index = Number(_retarge_index!.value) if (this.retarget_index <= this._list.length && this.retarget_index != 0) { this.dispatchEvent( new CustomEvent('retarget-data', { @@ -285,7 +281,7 @@ export class LitSearch extends BaseElement { setTimeout(() => { _prompt!.style.display = 'none'; _root!.style.display = 'flex'; - this._retarge_index!.value = "" + _retarge_index!.value = "" }, 2000) } @@ -416,7 +412,7 @@ export class LitSearch extends BaseElement { @@ -450,13 +446,8 @@ export class LitSearch extends BaseElement { searchInfoOption.textContent = historyInfo.searchContent; searchInfoOption.addEventListener('click', () => { if (searchInfoOption.textContent) { - let flag=this.search!.value this.search!.value = searchInfoOption.textContent; this.valueChangeHandler?.(this.search!.value); - if(flag!=searchInfoOption.textContent) { - this._retarge_index!.value = "" - this.index=-1 - } } }); searchContainer.append(searchInfoOption); diff --git a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts index 0ecd256f..b98b500d 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts @@ -58,6 +58,7 @@ export class TabPaneFilter extends BaseElement { private cutList: Array | undefined; private libraryList: Array | undefined; + private transferChecked: string | undefined; filterData(type: string, data: object = {}) { return { @@ -102,6 +103,7 @@ export class TabPaneFilter extends BaseElement { this.markButtonEL = this.shadowRoot?.querySelector('#mark'); this.iconEL = this.shadowRoot?.querySelector('#icon'); this.statisticsName = this.shadowRoot?.querySelector('.statistics-name'); + let transferEL = this.shadowRoot?.querySelector('.transfer-text'); this.iconEL!.onclick = (e) => { if (this.iconEL!.name == 'statistics') { this.iconEL!.name = 'menu'; @@ -118,12 +120,16 @@ export class TabPaneFilter extends BaseElement { if (this.getFilter) { this.getFilter(this.filterData('icon')); } - if (this.getAttribute('perf') == 'perf') { + if(this.getAttribute('perf') == 'perf') { this.disabledTransfer(true); } } }; + transferEL!.onclick = () => { + this.getTransferList(); + }; + this.markButtonEL!.onclick = (e) => { if (this.getFilter) { this.getFilter(this.filterData('mark', { mark: true })); @@ -431,35 +437,36 @@ export class TabPaneFilter extends BaseElement { initializeTreeTransfer() { let radioList = this.shadowRoot!.querySelectorAll('.radio'); let divElement = this.shadowRoot!.querySelectorAll('.tree-radio'); - radioList![radioList.length - 1].checked = true; + + if (this.transferChecked && this.transferChecked !== 'count') { + radioList![Number(this.transferChecked)].checked = true; + } else if (this.transferChecked && this.transferChecked == 'count') { + radioList![radioList.length - 1].checked = true; + } divElement!.forEach((divEl, idx) => { divEl.addEventListener('click', () => { - let filterData = this.getFilterTreeData(); - if (filterData.callTree[0] === true || filterData.callTree[1] === true) { - let row = this.shadowRoot!.querySelectorAll('.tree-check lit-check-box'); - row[0].checked = false; - row[1].checked = false; - } - if (filterData.callTreeConstraints.checked === true) { - let check = this.shadowRoot!.querySelector('#constraints-check'); - let inputs = this.shadowRoot!.querySelectorAll('.constraints-input'); - check!.checked = false; - inputs[0].value = '0'; - inputs[1].value = '∞'; - } - this.filterInputEL!.value = '' - + this.transferChecked = radioList![idx].value; radioList![idx].checked = true; if (this.getCallTransfer) { this.getCallTransfer({ - eventTypeId: radioList![idx].value - }) + value: radioList![idx].value, + }); } }); }); } + refreshTreeTransfer() { + let radioList = this.shadowRoot!.querySelectorAll('.radio'); + if (this.transferChecked && this.transferChecked !== 'count') { + radioList![Number(this.transferChecked)].checked = false; + } else if (this.transferChecked && this.transferChecked == 'count') { + radioList![radioList.length - 1].checked = false; + } + this.transferChecked = ''; + } + initializeTreeConstraints() { let inputs = this.shadowRoot!.querySelectorAll('.constraints-input'); let check = this.shadowRoot!.querySelector('#constraints-check'); @@ -505,8 +512,9 @@ export class TabPaneFilter extends BaseElement { let html = ``; this.cutList!.forEach((a, b) => { html += `
- +
${a.name}
`; }); @@ -538,8 +546,9 @@ export class TabPaneFilter extends BaseElement { let html = ``; this.libraryList!.forEach((a, b) => { html += `
- +
${a.name}
`; }); diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts index 0fc72add..37c0e69f 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts @@ -49,7 +49,6 @@ export class TabPaneFrequencySample extends BaseElement { private busyTimeLoadingHide: boolean = false; private freqBusyDataList: Array = []; private worker: Worker | undefined; - private freqResult: Array = []; set data(frequencySampleValue: SelectionParam | any) { if (frequencySampleValue == this.selectionParam) { @@ -160,7 +159,6 @@ export class TabPaneFrequencySample extends BaseElement { frqSampleParam.rightNs + frqSampleParam.recordStartNs, frqSampleParam.cpuFreqFilterIds ) - this.freqResult = result; frqSampleParam.cpuFreqFilterIds.forEach((a: number) => { this.getInitTime( result.filter((f) => f.filterId == a), @@ -254,7 +252,6 @@ export class TabPaneFrequencySample extends BaseElement { //点击按钮控制busyTime显示与否 handleClick(key: string, type: boolean) { let res = new Array(); - if (this.freqResult.length == 0) return; //当busyTime的值计算完毕后进入if判断 if (this.busyTimeLoadingHide) { this.busyTimeLoadingHide = false; diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts deleted file mode 100644 index 55bd1b18..00000000 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table'; -import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; -import '../../../StackBar.js' -import { getTabRunningPercent, querySearchFuncData, queryCpuFreqUsageData, queryCpuFreqFilterId } from '../../../../database/SqlLite.js'; -import { Utils } from '../../base/Utils.js'; -import { log } from '../../../../../log/Log.js'; -import { resizeObserver } from '../SheetUtils.js'; - -@element('tabpane-freqdatacut') -export class TabPaneFreqDataCut extends BaseElement { - private threadStatesTbl: LitTable | null | undefined; - private threadStatesTblSource: Array = []; - private currentSelectionParam: SelectionParam | any; - private threadStatesDIV: Element | null | undefined; - private initData: Array = []; - - set data(threadStatesParam: SelectionParam | any) { - if (this.currentSelectionParam === threadStatesParam) { - return; - } - this.currentSelectionParam = threadStatesParam; - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - let divRoot1: any = this.shadowRoot?.querySelector('#dataCutThreadId'); - divRoot1.value = ''; - let divRoot2: any = this.shadowRoot?.querySelector('#dataCutThreadFunc'); - divRoot2.value = ''; - getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => { - queryCpuFreqFilterId().then(r => { - let IdMap = new Map(); - let queryId = new Array(); - for (let i = 0; i < r.length; i++) { - queryId.push(r[i].id); - IdMap.set(r[i].id, r[i].cpu); - } - queryCpuFreqUsageData(queryId).then((res) => { - if (result != null && result.length > 0) { - log('getTabRunningPercent result size : ' + result.length); - let sum = 0; - let dealArr = new Array(); - for (let i of res) { - dealArr.push({ 'startNS': i.startNS + threadStatesParam.recordStartNs, 'dur': i.dur, 'value': i.value, 'cpu': IdMap.get(i.filter_id) }); - } - let targetList = new Array(); - let cpuArr = new Array(); - let finalResultArr = new Array(); - finalResultArr.push({ 'thread': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': '100.00', 'state': 'Running', children: new Array() }); - for (let e of result) { - if (threadStatesParam.processIds.includes(e.pid) && e.state == 'Running') { - let process = Utils.PROCESS_MAP.get(e.pid); - let thread = Utils.THREAD_MAP.get(e.tid); - e.process = process == null || process.length == 0 ? '[NULL]' : process; - e.thread = thread == null || thread.length == 0 ? '[NULL]' : thread; - e.stateJX = e.state; - e.state = Utils.getEndState(e.stateJX); - sum += e.dur; - targetList.push(e); - if (!cpuArr.includes(e.cpu)) { - cpuArr.push(e.cpu); - finalResultArr[0].thread = finalResultArr[0].thread == '' ? e.tid + '_' + e.thread : finalResultArr[0].thread; - finalResultArr[0].children.push({ 'thread': e.tid + '_' + e.thread, 'count': 0, 'cpu': e.cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - } - } - } - // 用来存放数据切割之前的汇总数据 - let resultList = new Array(); - // 通过循环获取每个running状态线程的相关信息,此处或许可以进行算法优化 - const tsMutiple = 1000000000; - for (let i = 0; i < targetList.length; i++) { - for (let j = 0; j < dealArr.length; j++) { - if (targetList[i].cpu == dealArr[j].cpu) { - if (targetList[i].ts > dealArr[j].startNS) { - if (targetList[i].ts < (dealArr[j].startNS + dealArr[j].dur)) { - if (targetList[i].dur < (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * targetList[i].dur) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': targetList[i].dur, 'percent': targetList[i].dur / sum * 100, 'state': 'Running', 'ts': targetList[i].ts / tsMutiple }); - break; - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts), 'percent': (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) / sum * 100, 'state': 'Running', 'ts': targetList[i].ts / tsMutiple }); - } - } - } else { - if ((targetList[i].ts + targetList[i].dur) > dealArr[j].startNS) { - if ((targetList[i].dur + targetList[i].ts - dealArr[j].startNS) < dealArr[j].dur) { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * (targetList[i].dur + targetList[i].ts - dealArr[j].startNS)) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': (targetList[i].dur + targetList[i].ts - dealArr[j].startNS), 'percent': (targetList[i].dur + targetList[i].ts - dealArr[j].startNS) / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS / tsMutiple }); - break; - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * dealArr[j].dur) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': dealArr[j].dur, 'percent': dealArr[j].dur / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS / tsMutiple }); - } - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': 0, 'cpu': targetList[i].cpu, 'freq': 'unknown', 'dur': targetList[i].dur, 'percent': targetList[i].dur / sum * 100, 'state': 'Running', 'ts': targetList[i].ts / tsMutiple }); - break; - } - } - } - } - } - // 深拷贝,用来进行数据切割操作,避免数据污染 - this.initData = JSON.parse(JSON.stringify(resultList)); - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - this.initData = []; - } - }) - }) - - }); - } - initElements(): void { - this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-percent'); - // 暂时屏蔽列排序功能,后续增加则重写排序方法 - this.threadStatesDIV = this.shadowRoot?.querySelector('#dataCut'); - this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { - this.dataSingleCut(this.threadStatesDIV?.children[0], this.threadStatesDIV?.children[1], this.initData); - }) - this.threadStatesDIV?.children[2].children[1].addEventListener('click', (e) => { - this.dataLoopCut(this.threadStatesDIV?.children[0], this.threadStatesDIV?.children[1], this.initData); - }) - } - connectedCallback() { - super.connectedCallback(); - resizeObserver(this.parentElement!, this.threadStatesTbl!); - } - initHtml(): string { - return ` - -
- - -
- - -
-
- - - - - - - - - - - - - - - - - - - ` - } - dataLoopCut(threadId: any, threadFunc: any, resultList: any) { - let threadIdValue = threadId.value.trim(); - let threadFuncName = threadFunc.value.trim(); - let leftNS = this.currentSelectionParam.leftNs; - let rightNS = this.currentSelectionParam.rightNs; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - if (/^[0-9]*$/.test(threadIdValue)) { - querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then(res => { - let display = JSON.parse(JSON.stringify(resultList)); - let timeDur = this.currentSelectionParam.recordStartNs; - let cutArr = new Array(); - // 根据线程id及方法名获取的数据,处理后用作切割时间依据,时间跨度为整个方法开始时间到末个方法开始时间 - for (let i of res) { - cutArr.push({ 'ts': i.startTime + timeDur }); - } - // 将数据进行切割处理 - let finalArr = new Array(); - let finalResultArr = new Array(); - const tsMutiple = 1000000000; - finalResultArr.push({ 'thread': display[0].thread, 'ts': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - for (let i = 0; i < cutArr.length - 1; i++) { - let displayArr = JSON.parse(JSON.stringify(display)); - for (let j = 0; j < displayArr.length; j++) { - displayArr[j].ts = displayArr[j].ts * tsMutiple; - if (displayArr[j].ts >= cutArr[i].ts) { - if ((displayArr[j].ts + displayArr[j].dur) <= cutArr[i + 1].ts) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * displayArr[j].dur) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': displayArr[j].dur, 'percent': displayArr[j].percent, 'state': 'Running', 'ts': (displayArr[j].ts - timeDur) / tsMutiple, 'id': i }); - } else { - if (cutArr[i + 1].ts - displayArr[j].ts > 0) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (cutArr[i + 1].ts - displayArr[j].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': cutArr[i + 1].ts - displayArr[j].ts, 'percent': displayArr[j].percent * ((cutArr[i + 1].ts - displayArr[j].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (displayArr[j].ts - timeDur) / tsMutiple, 'id': i }); - break; - } - } - } else { - if ((displayArr[j].ts + displayArr[j].dur) > cutArr[i + 1].ts) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (cutArr[i + 1].ts - cutArr[i].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': cutArr[i + 1].ts - cutArr[i].ts, 'percent': displayArr[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'id': i }); - } - if ((displayArr[j].ts + displayArr[j].dur) > cutArr[i].ts && (displayArr[j].ts + displayArr[j].dur) < cutArr[i + 1].ts) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (displayArr[j].dur + displayArr[j].ts - cutArr[i].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': displayArr[j].dur + displayArr[j].ts - cutArr[i].ts, 'percent': displayArr[j].percent * ((displayArr[j].dur + displayArr[j].ts - cutArr[i].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'id': i }); - } - } - } - finalResultArr[0].children.push({ 'thread': displayArr[0].thread, 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array(), 'id': i }); - } - - for (let i = 0; i < finalArr.length; i++) { - for (let j = i + 1; j < finalArr.length; j++) { - if (finalArr[i].cpu === finalArr[j].cpu && finalArr[i].freq === finalArr[j].freq && finalArr[i].id === finalArr[j].id) { - finalArr[i].dur += finalArr[j].dur; - finalArr[i].percent += finalArr[j].percent; - finalArr[i].count += finalArr[j].count; - finalArr.splice(j, 1); - j--; - } - } - finalArr[i].percent = Number((finalArr[i].percent).toFixed(2)); - } - - let newArr1 = JSON.parse(JSON.stringify(finalResultArr[0])); - let newArr2 = JSON.parse(JSON.stringify(finalArr)); - let finalResult = new Array(this.mergeTree(newArr1, newArr2)); - this.threadStatesTblSource = finalResult[0].children.length > 0 ? finalResult : []; - this.threadStatesTbl!.recycleDataSource = finalResult[0].children.length > 0 ? finalResult : []; - }) - } else { - alert('请输入正确的线程ID'); - } - } - dataSingleCut(threadId: any, threadFunc: any, resultList: any) { - let threadIdValue = threadId.value.trim(); - let threadFuncName = threadFunc.value.trim(); - let leftNS = this.currentSelectionParam.leftNs; - let rightNS = this.currentSelectionParam.rightNs; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - if (/^[0-9]*$/.test(threadIdValue)) { - querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then(result => { - let [...target] = JSON.parse(JSON.stringify(resultList)); - let timeDur = this.currentSelectionParam.recordStartNs; - let dealArr = new Array(); - for (let i of result) { - if (i.startTime + timeDur + i.dur < this.currentSelectionParam.rightNs + timeDur) { - dealArr.push({ 'ts': i.startTime + timeDur, 'dur': i.dur }); - } - } - let finalResultArr = new Array(); - finalResultArr.push({ 'thread': target[0].thread, 'ts': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - let resList = new Array(); - const tsMutiple = 1000000000; - for (let i = 0; i < dealArr.length; i++) { - let targetList = JSON.parse(JSON.stringify(target)); - for (let j = 0; j < targetList.length; j++) { - targetList[j].ts = targetList[j].ts * tsMutiple; - if (dealArr[i].ts < targetList[j].ts) { - if (dealArr[i].ts + dealArr[i].dur > targetList[j].ts) { - if (dealArr[i].ts + dealArr[i].dur > targetList[j].ts + targetList[j].dur) { - resList.push({ 'thread': targetList[i].thread, 'ts': (targetList[j].ts - timeDur) / tsMutiple, 'count': (targetList[j].freq * targetList[j].dur) / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': targetList[j].dur, 'percent': targetList[j].percent, 'state': 'Running', 'id': i }); - } else { - resList.push({ 'thread': targetList[j].thread, 'ts': (targetList[j].ts - timeDur) / tsMutiple, 'count': (dealArr[i].ts + dealArr[i].dur - targetList[j].ts) * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': dealArr[i].ts + dealArr[i].dur - targetList[j].ts, 'percent': (dealArr[i].ts + dealArr[i].dur - targetList[j].ts) / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); - break; - } - } - } else { - if (targetList[j].ts + targetList[j].dur > dealArr[i].ts) { - if (targetList[j].ts + targetList[j].dur > dealArr[i].ts + dealArr[i].dur) { - resList.push({ 'thread': targetList[j].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': dealArr[i].dur * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': dealArr[i].dur, 'percent': dealArr[i].dur / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); - break; - } else { - resList.push({ 'thread': targetList[j].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': (targetList[j].ts + targetList[j].dur - dealArr[i].ts) * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': targetList[j].ts + targetList[j].dur - dealArr[i].ts, 'percent': (targetList[j].ts + targetList[j].dur - dealArr[i].ts) / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); - } - } - } - } - finalResultArr[0].children.push({ 'thread': targetList[0].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array(), 'id': i }); - } - // 合并相同周期内的数据 - for (let i = 0; i < resList.length; i++) { - for (let j = i + 1; j < resList.length; j++) { - if (resList[i].cpu === resList[j].cpu && resList[i].freq === resList[j].freq && resList[i].id === resList[j].id) { - resList[i].dur += resList[j].dur; - resList[i].percent += resList[j].percent; - resList[i].count += resList[j].count; - resList.splice(j, 1); - j--; - } - } - resList[i].percent = Number((resList[i].percent).toFixed(2)); - } - - let newArr1 = JSON.parse(JSON.stringify(finalResultArr[0])); - let newArr2 = JSON.parse(JSON.stringify(resList)); - let finalResult = new Array(this.mergeTree(newArr1, newArr2)); - - this.threadStatesTblSource = finalResult[0].children.length > 0 ? finalResult : []; - this.threadStatesTbl!.recycleDataSource = finalResult[0].children.length > 0 ? finalResult : []; - }) - } else { - alert('请输入正确的线程ID'); - } - } - - mergeTree(arr1: any, arr2: any) { - for (let i = 0; i < arr1.children.length; i++) { - // 改成map对象做标记 - let cpuArr = new Array(); - let flagMap = new Map(); - let flag = 0; - for (let j = 0; j < arr2.length; j++) { - if (arr1.children[i].id == arr2[j].id) { - if (!cpuArr.includes(arr2[j].cpu)) { - flagMap.set(arr2[j].cpu, flag); - cpuArr.push(arr2[j].cpu); - arr1.children[i].children.push({ 'thread': arr2[j].thread, 'count': 0, 'cpu': arr2[j].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', 'ts': '', children: new Array(), 'id': arr2[j].id }); - if (arr1.children[i].children[flag].cpu == arr2[j].cpu && arr1.children[i].children[flag].id == arr2[j].id) { - arr1.children[i].children[flag].children.push(arr2[j]); - arr1.children[i].children[flag].dur += arr2[j].dur; - arr1.children[i].children[flag].percent += arr2[j].percent; - arr1.children[i].children[flag].count += arr2[j].count; - arr1.children[i].percent += arr1.children[i].children[flag].percent; - arr1.children[i].children[flag].percent = Number(arr1.children[i].children[flag].percent.toFixed(2)); - arr1.children[i].dur += arr1.children[i].children[flag].dur; - arr1.children[i].count += arr1.children[i].children[flag].count; - flag++; - arr2.splice(j, 1); - j--; - } - } else { - // 利用map做数据处理 - let count = flagMap.get(arr2[j].cpu); - if (arr1.children[i].children[count].cpu == arr2[j].cpu && arr1.children[i].children[count].id == arr2[j].id) { - arr1.children[i].children[count].children.push(arr2[j]); - arr1.children[i].children[count].dur += arr2[j].dur; - arr1.children[i].children[count].percent += arr2[j].percent; - arr1.children[i].children[count].count += arr2[j].count; - arr1.children[i].percent += arr2[j].percent; - arr1.children[i].children[count].percent = Number(arr2[j].percent.toFixed(2)); - arr1.children[i].dur += arr2[j].dur; - arr1.children[i].count += arr2[j].count; - arr2.splice(j, 1); - j--; - } - } - } else { - break; - } - } - arr1.children[i].children.sort((a: any, b: any) => a.cpu - b.cpu); - arr1.percent += arr1.children[i].percent; - arr1.children[i].percent = Number(arr1.children[i].percent.toFixed(2)); - arr1.dur += arr1.children[i].dur; - arr1.count += arr1.children[i].count; - } - arr1.percent = Number(arr1.percent.toFixed(2)); - return arr1; - } -} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts deleted file mode 100644 index 8c75ee2f..00000000 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table'; -import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; -import '../../../StackBar.js' -import { getTabRunningPercent, queryCpuFreqUsageData, queryCpuFreqFilterId } from '../../../../database/SqlLite.js'; -import { Utils } from '../../base/Utils.js'; -import { resizeObserver } from '../SheetUtils.js'; - -@element('tabpane-frequsage') -export class TabPaneFreqUsage extends BaseElement { - private threadStatesTbl: LitTable | null | undefined; - private threadStatesTblSource: Array = []; - private currentSelectionParam: Selection | undefined; - - set data(threadStatesParam: SelectionParam | any) { - if (this.currentSelectionParam === threadStatesParam) { - return; - } - this.currentSelectionParam = threadStatesParam; - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - let tableValue:any = this.threadStatesTbl; - tableValue.value = []; - getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => { - queryCpuFreqFilterId().then(r => { - let IdMap = new Map(); - let queryId = new Array(); - for (let i = 0; i < r.length; i++) { - queryId.push(r[i].id); - IdMap.set(r[i].id, r[i].cpu); - } - queryCpuFreqUsageData(queryId).then((res) => { - if (result != null && result.length > 0) { - let sum = 0; - let dealArr = new Array(); - for (let i of res) { - dealArr.push({ 'startNS': i.startNS + threadStatesParam.recordStartNs, 'dur': i.dur, 'value': i.value, 'cpu': IdMap.get(i.filter_id) }); - } - let targetList = new Array(); - let cpuArr = new Array(); - let finalResultArr = new Array(); - finalResultArr.push({ 'thread': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': '100.00', 'state': 'Running', children: new Array() }); - for (let e of result) { - if (threadStatesParam.processIds.includes(e.pid) && e.state == 'Running') { - let process = Utils.PROCESS_MAP.get(e.pid); - let thread = Utils.THREAD_MAP.get(e.tid); - e.process = process == null || process.length == 0 ? '[NULL]' : process; - e.thread = thread == null || thread.length == 0 ? '[NULL]' : thread; - e.stateJX = e.state; - e.state = Utils.getEndState(e.stateJX); - sum += e.dur; - targetList.push(e); - if (!cpuArr.includes(e.cpu)) { - cpuArr.push(e.cpu); - finalResultArr[0].thread = finalResultArr[0].thread == '' ? e.tid + '_' + e.thread : finalResultArr[0].thread; - finalResultArr[0].children.push({ 'thread': e.tid + '_' + e.thread, 'count': 0, 'cpu': e.cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - } - } - } - let resultList = new Array(); - for (let i = 0; i < targetList.length; i++) { - for (let j = 0; j < dealArr.length; j++) { - if (targetList[i].cpu == dealArr[j].cpu) { - if (targetList[i].ts > dealArr[j].startNS) { - if (targetList[i].ts < (dealArr[j].startNS + dealArr[j].dur)) { - if (targetList[i].dur < (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * targetList[i].dur) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': targetList[i].dur, 'percent': targetList[i].dur / sum * 100, 'state': 'Running', 'ts': targetList[i].ts }); - break; - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts), 'percent': (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) / sum * 100, 'state': 'Running', 'ts': targetList[i].ts }); - } - } - } else { - if ((targetList[i].ts + targetList[i].dur) > dealArr[j].startNS) { - if ((targetList[i].dur + targetList[i].ts - dealArr[j].startNS) < dealArr[j].dur) { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * (targetList[i].dur + targetList[i].ts - dealArr[j].startNS)) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': (targetList[i].dur + targetList[i].ts - dealArr[j].startNS), 'percent': (targetList[i].dur + targetList[i].ts - dealArr[j].startNS) / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS }); - break; - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * dealArr[j].dur) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': dealArr[j].dur, 'percent': dealArr[j].dur / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS }); - } - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': 0, 'cpu': targetList[i].cpu, 'freq': 'unknown', 'dur': targetList[i].dur, 'percent': targetList[i].dur / sum * 100, 'state': 'Running', 'ts': targetList[i].ts }); - break; - } - } - } - } - } - //合并同一线程内,当运行所在cpu和频点相同时,dur及percent进行累加求和,或许可以进行算法优化 - for (let i = 0; i < resultList.length; i++) { - for (let j = i + 1; j < resultList.length; j++) { - if (resultList[i].cpu == resultList[j].cpu && resultList[i].freq == resultList[j].freq) { - resultList[i].dur += resultList[j].dur; - resultList[i].percent += resultList[j].percent; - resultList[i].count += resultList[j].count; - resultList.splice(j, 1); - j--; - } - } - resultList[i].percent = Number((resultList[i].percent).toFixed(2)); - resultList[i].ts = resultList[i].ts - threadStatesParam.recordStartNs; - } - finalResultArr[0].children.sort((a: any, b: any) => a.cpu - b.cpu); - // 转成树结构数据进行展示 - for (let i = 0; i < finalResultArr[0].children.length; i++) { - for (let j = 0; j < resultList.length; j++) { - if (finalResultArr[0].children[i].cpu == resultList[j].cpu) { - finalResultArr[0].children[i].children.push(resultList[j]); - finalResultArr[0].children[i].dur += resultList[j].dur; - finalResultArr[0].children[i].percent += resultList[j].percent; - finalResultArr[0].children[i].count += resultList[j].count; - resultList.splice(j, 1); - j--; - } - } - finalResultArr[0].children[i].percent = finalResultArr[0].children[i].percent.toFixed(2); - finalResultArr[0].dur += finalResultArr[0].children[i].dur; - finalResultArr[0].count += finalResultArr[0].children[i].count; - } - this.threadStatesTblSource = finalResultArr; - this.threadStatesTbl!.recycleDataSource = finalResultArr; - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - } - }); - }); - - }) - } - initElements(): void { - this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-percent'); - } - connectedCallback() { - super.connectedCallback(); - resizeObserver(this.parentElement!, this.threadStatesTbl!); - } - initHtml(): string { - return ` - - - - - - - - - - - - - - - - - - ` - } - -} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts index 7ed87405..65a29ed9 100644 --- a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts +++ b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts @@ -190,7 +190,7 @@ export class TabPaneHiLogs extends BaseElement { } let tableHeight = Number(tbl!.style.height.replace('px', '')) - tableHeadHeight; while (height < tableHeight) { - if (height + firstRowHeight > tableHeight) { + if (firstRowHeight <= 0 || height + firstRowHeight > tableHeight) { break; } height += firstRowHeight; diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfBinaryTree.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfBinaryTree.ts deleted file mode 100644 index 78c8b033..00000000 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfBinaryTree.ts +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { SelectionParam } from '../../../../bean/BoxSelection.js'; -import { procedurePool } from '../../../../database/Procedure.js'; - -@element('tabpane-perf-svg') -export class TabpanePerfBinaryTree extends BaseElement { - private svgElement: SVGSVGElement | undefined; - private binaryTreeDate: any; - private nodeWidth: number = 100; - private nodeHeight: number = 50; - private nodeGap: number | undefined; - private pathOffset: number = 30; - private arrowSize: number = 6; - private searchValue: string = ''; - private currentSelection: SelectionParam | undefined; - - set data(perfProfilerSelection: SelectionParam | any) { - if (perfProfilerSelection === this.currentSelection) { - return; - } - this.searchValue = ''; - this.currentSelection = perfProfilerSelection; - this.nodeGap = 100; - this.getDataByWorker( - [ - { - funcName: 'setSearchValue', - funcArgs: [''], - }, - { - funcName: 'getCurrentDataFromDb', - funcArgs: [perfProfilerSelection], - }, - ], - (results: any[]) => { - // console.log(results,'111'); - this.binaryTreeDate = results; - this.draw(); - } - ); - } - - initElements(): void { - this.svgElement = this.shadowRoot?.querySelector('#binaryTreeSvg') as SVGSVGElement; - - } - - getDataByWorker(args: any[], handler: Function) { - procedurePool.submitWithName('logic0', 'perf-action', args, undefined, (results: any) => { - handler(results); - - }); - } - - private draw(): void { - if (!this.binaryTreeDate) return; - //清空SVG - while (this.svgElement?.firstChild) { - this.svgElement.firstChild.remove(); - } - - //计算树的高度和每层节点数量 - const treeWidth = this.getTreeWidth(this.binaryTreeDate); - const treeHeight = this.getTreeHeight(this.binaryTreeDate); - - //计算根节点的位置 - const rootX = (this.svgElement!.clientWidth - this.nodeWidth) / 2; - // console.log(this.svgElement!.clientWidth,'svg可视宽度'); - - const rootY = this.nodeGap!; - - //绘制根节点 - const rootNode = this.createNode(rootX, rootY, this.binaryTreeDate); - this.svgElement!.appendChild(rootNode); - - //绘制子节点和连线 - this.drawChildren(this.binaryTreeDate, rootX, rootY, treeWidth, treeHeight, 0, 0); - } - - private drawChildren( - nodeData: any, - parentX: number, - parentY: number, - treeWidth: number, - treeHeight: number, - level: number, - index: number - ): void { - if (nodeData.length === 0) return; - - //计算子节点的位置 - const startX = parentX - (treeWidth / 2) + (this.nodeWidth + this.nodeGap!) * index; - const startY = parentY + this.nodeHeight + this.nodeGap!; - - //循环遍历子节点 - for (let i = 0; i < nodeData.length; i++) { - //计算子节点的x坐标 - const childX = startX + (this.nodeWidth + this.nodeGap!) * i; - const childNode = this.createNode(childX, startY, nodeData[i]); - this.svgElement!.appendChild(childNode); - - //绘制连线 - const pathStartX = parentX + this.nodeWidth / 2; - const pathStartY = parentY + this.nodeHeight; - const pathEndX = childX + this.nodeWidth / 2; - const pathEndY = startY; - const pathControlX = (pathStartX + pathEndX) / 2; - const pathControlY = pathStartY + this.pathOffset; - const path = this.createPath(pathStartX, pathStartY, pathControlX, pathControlY, pathEndX, pathEndY); - this.svgElement!.appendChild(path); - - //绘制箭头 - const arrow = this.createArrow(pathEndX, pathEndY); - this.svgElement!.appendChild(arrow); - - // 递归绘制子节点的子节点 - this.drawChildren(nodeData[i].children, childX, startY, treeWidth, treeHeight, level + 1, i); - } - } - - private createNode(x: number, y: number, data: any): SVGElement { - const group = document.createElementNS("http://www.w3.org/2000/svg", "g"); - - const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - rect.setAttribute("x", x.toString()); - rect.setAttribute("y", y.toString()); - rect.setAttribute("width", this.nodeWidth.toString()); - rect.setAttribute("height", this.nodeHeight.toString()); - rect.setAttribute("fill", "#f5c78e"); - rect.setAttribute("stroke", "#000000"); - group.appendChild(rect); - - const foreignObject = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject"); - foreignObject.setAttribute("x", (x + 5).toString()); - foreignObject.setAttribute("y", (y + 5).toString()); - foreignObject.setAttribute("width", (this.nodeWidth - 10).toString()); - foreignObject.setAttribute("height", (this.nodeHeight - 10).toString()); - - const div = document.createElement("div"); - div.style.width = "100%"; - div.style.height = "100%"; - div.style.whiteSpace = "nowrap"; - div.style.textOverflow = "ellipsis"; - div.style.overflow = "hidden"; - div.textContent = `${data.symbol}`; - foreignObject.appendChild(div); - - group.appendChild(foreignObject); - - return group; - } - - - private createPath(x1: number, y1: number, cx: number, cy: number, x2: number, y2: number): SVGElement { - const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); - path.setAttribute("d", `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2 - this.arrowSize}`); - path.setAttribute("fill", "none"); - path.setAttribute("stroke", "#000000"); - - return path; - } - - private createArrow(x: number, y: number): SVGElement { - const arrow = document.createElementNS("http://www.w3.org/2000/svg", "path"); - arrow.setAttribute( - "d", - `M ${x - this.arrowSize / 2},${y - this.arrowSize} L ${x + this.arrowSize / 2},${y - this.arrowSize} L ${x},${y + this.arrowSize / 2} Z` - ); - arrow.setAttribute("fill", "#000000"); - - return arrow; - } - - - private getTreeWidth(nodeData: any): number { - if (nodeData.length === 0) return this.nodeWidth; - - const childrenCount = nodeData.length; - return childrenCount * (this.nodeWidth + this.nodeGap!) - this.nodeGap!; - } - - private getTreeHeight(nodeData: any): number { - if (nodeData.length === 0) return this.nodeHeight; - - let maxHeight = 0; - const childrenCount = nodeData.length; - - for (let i = 0; i < childrenCount; i++) { - //递归计算所有子节点高度 - const childHeight = this.getTreeHeight(nodeData[i]); - if (childHeight > maxHeight) { - maxHeight = childHeight; - - } - } - - return this.nodeHeight + this.nodeGap! + maxHeight; - } - - initHtml(): string { - return ` -
- - -
`; - } -} diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts index 98a48f76..0ce3fbcf 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts @@ -38,7 +38,7 @@ export class TabpanePerfProfile extends BaseElement { private perfProfilerList: LitTable | null | undefined; private perfProfileProgressEL: LitProgressBar | null | undefined; private perfProfilerRightSource: Array = []; - private perfProfilerFilter: TabPaneFilter | null | undefined; + private perfProfilerFilter: TabPaneFilter| null| undefined; private perfProfilerDataSource: any[] = []; private perfProfileSortKey = 'weight'; private perfProfileSortType = 0; @@ -67,57 +67,47 @@ export class TabpanePerfProfile extends BaseElement { this.perfProfilerFilter!.style.display = 'none'; } this.perfProfilerFilter!.disabledTransfer(false, 'perf'); - this.perfProfilerFilter!.getTransferList(); this.perfProfilerFilter!.initializeFilterTree(true, true, true); this.perfProfilerFilter!.filterValue = ''; + this.perfProfilerFilter!.refreshTreeTransfer(); this.perfProfileProgressEL!.loading = true; this.perfProfileLoadingPage.style.visibility = 'visible'; - this.getDataByWorkAndUpDateCanvas(perfProfilerSelection); - } - - getDataByWorkAndUpDateCanvas(perfProfilerSelection: SelectionParam) { const initWidth = this.clientWidth; this.initGetData(perfProfilerSelection, initWidth); - - + this.perfProfilerFilter!.getCallTransferData((data: any) => { - this.initGetData(perfProfilerSelection, initWidth, data.eventTypeId); + perfProfilerSelection.eventTypeId = data.value !== 'count' ? data.value : undefined; + this.initGetData(perfProfilerSelection, initWidth, data); }); } - initGetData(perfProfilerSelection: SelectionParam | any, initWidth: number, eventTypeId?: string): void { - let perfProfileArgs: any[] = []; - if (eventTypeId) { - perfProfileArgs.push({ - funcName: 'setEventTypeId', - funcArgs: [eventTypeId !== 'count' ? eventTypeId : undefined], - }) - } - perfProfileArgs.push( - { - funcName: 'setSearchValue', - funcArgs: [''], - }, - { - funcName: 'getCurrentDataFromDb', - funcArgs: [perfProfilerSelection], - }) + initGetData(perfProfilerSelection: SelectionParam | any, initWidth: number, data?: any): void { + this.getDataByWorker( + [ + { + funcName: 'setSearchValue', + funcArgs: [''], + }, + { + funcName: 'getCurrentDataFromDb', + funcArgs: [perfProfilerSelection], + }, + ], + (results: any[]) => { + this.setPerfProfilerLeftTableData(results); + this.perfProfilerList!.recycleDataSource = []; + if (data && data.value !== 'count') { + this.perfProfileFrameChart!.mode = ChartMode.EventCount; + } else { + this.perfProfileFrameChart!.mode = ChartMode.Count; + } - this.getDataByWorker(perfProfileArgs, (results: any[]) => { - this.setPerfProfilerLeftTableData(results); - this.perfProfilerList!.recycleDataSource = []; - if (eventTypeId && eventTypeId !== 'count') { - this.perfProfileFrameChart!.mode = ChartMode.EventCount; - } else { - this.perfProfileFrameChart!.mode = ChartMode.Count; + this.perfProfileFrameChart?.updateCanvas(true, initWidth); + this.perfProfileFrameChart!.data = this.perfProfilerDataSource; + this.switchFlameChart(); + this.perfProfilerFilter!.icon = 'block'; } - - this.perfProfileFrameChart?.updateCanvas(true, initWidth); - this.perfProfileFrameChart!.data = this.perfProfilerDataSource; - this.switchFlameChart(); - this.perfProfilerFilter!.icon = 'block'; - }) - + ); } getParentTree( diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index c0852e00..0d8e5986 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -296,8 +296,8 @@ export class DbPool { } } }; - thread!.onmessageerror = (e) => { }; - thread!.onerror = (e) => { }; + thread!.onmessageerror = (e) => {}; + thread!.onerror = (e) => {}; thread!.id = i; thread!.busy = false; this.works?.push(thread!); @@ -1271,7 +1271,8 @@ export const queryVirtualMemory = (): Promise> => export const queryVirtualMemoryData = (filterId: number): Promise> => query( 'queryVirtualMemoryData', - `select ts-${(window as any).recordStartNS + `select ts-${ + (window as any).recordStartNS } as startTime,value,filter_id as filterID from sys_mem_measure where filter_id=$filter_id`, { $filter_id: filterId } ); @@ -3838,9 +3839,11 @@ export const queryEbpfSamplesCount = (startTime: number, endTime: number, ipids: select fsCount, vmCount from -(select count(1) as fsCount from file_system_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' +(select count(1) as fsCount from file_system_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ + ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' }) -,(select count(1) as vmCount from paged_memory_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' +,(select count(1) as vmCount from paged_memory_sample s,trace_range t where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ + ipids.length > 0 ? `and s.ipid in (${ipids.join(',')})` : '' }); `, { $startTime: startTime, $endTime: endTime } @@ -5491,93 +5494,3 @@ export const queryTraceType = (): Promise< export const queryTransferList = (): Promise> => query('queryTransferList', `select id, report_value as cmdStr from perf_report where report_type = 'config_name'`); - -export const getTabRunningPercent = (tIds: Array, leftNS: number, rightNS: number): Promise> => - query( - 'getTabRunningPercent', - ` - select - B.pid,B.tid,B.state,B.cpu,B.dur,B.ts - from - thread_state AS B - left join - trace_range AS TR - where - B.tid in (${tIds.join(',')}) - and - B.state='Running' - and - not ((B.ts - TR.start_ts + ifnull(B.dur,0) < ${leftNS}) or (B.ts - TR.start_ts > ${rightNS})) - order by ts - `, - { $leftNS: leftNS, $rightNS: rightNS } - ); - -export const querySearchFuncData = (funcName: string, tIds: number, leftNS: number, rightNS: number): Promise> => - query( - 'querySearchFuncData', - ` - select - c.cookie, - c.id, - c.name as funName, - c.ts - r.start_ts as startTime, - c.dur, - c.depth, - t.tid, - t.name as threadName, - p.pid, - 'func' as type - from - callstack c - left join - thread t - on - c.callid = t.id - left join - process p - on - t.ipid = p.id - left join - trace_range r - where - c.name = '${funcName}' - and - t.tid = ${tIds} - and - not ((startTime < ${leftNS}) or (startTime > ${rightNS})); - `, - { $search: funcName } - ); - -export const queryCpuFreqUsageData = (Ids: Array): Promise> => - query( - 'queryCpuFreqUsageData', - `select - value, - ifnull(dur,tb.end_ts - c.ts) dur, - ts-tb.start_ts as startNS, - filter_id - from - measure c, - trace_range tb - where - c.filter_id in (${Ids.join(',')}) - ` - ); - -export const queryCpuFreqFilterId = (): Promise> => - query( - 'queryCpuFreqFilterId', - ` - select - id, - cpu - from - cpu_measure_filter - where - name='cpufreq' - or - name='cpu_frequency' - ` - ); \ No newline at end of file diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts index 285735be..578e4fee 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts @@ -37,25 +37,6 @@ export class Msg { data: Array = []; } -export class hiperfSymbol { - id: number = 0; - startTime: number = 0; - endTime: number = 0; - cpu_id: number = 0; - depth: number = 0; - children?: Array; - callchain_id: number = 0; - thread_id:number = 0; - name:string=''; - - public clone(): hiperfSymbol { - const cloneSymbol = new hiperfSymbol(); - cloneSymbol.children = new Array(); - cloneSymbol.depth = this.depth; - return cloneSymbol; - } -} - export class MerageBean extends ChartStruct { #parentNode: MerageBean | undefined = undefined; #total = 0; @@ -615,9 +596,6 @@ export class DataCache { public perfCallChainMap: Map = new Map(); public jsCallChain: Array | undefined; public jsSymbolMap = new Map(); - public perfCallFireMap = new Map(); - public perfCallChain: Array | undefined; - public perfSymbolMap = new Map() public static getInstance(): DataCache { if (!this.instance) { diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts index c4b66c10..7418a223 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts @@ -13,9 +13,8 @@ * limitations under the License. */ -import { LogicHandler, ChartStruct, convertJSON, DataCache, PerfCall,hiperfSymbol } from './ProcedureLogicWorkerCommon.js'; +import { LogicHandler, ChartStruct, convertJSON, DataCache, PerfCall } from './ProcedureLogicWorkerCommon.js'; import { PerfBottomUpStruct } from '../../bean/PerfBottomUpStruct.js'; -import { hiPerfchartFrame } from '../../bean/perfStruct.js'; const systemRuleName = '/system/'; const numRuleName = '/max/min/'; @@ -37,11 +36,8 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { currentEventId: string = ''; isAnalysis: boolean = false; isPerfBottomUp: boolean = false; - perfCallData: any[] = []; - eventTypeId: string = ''; private dataCache = DataCache.getInstance(); - private samplesCpu = Array(); handle(data: any): void { this.currentEventId = data.id; @@ -51,28 +47,6 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { this.dataCache.perfCountToMs = data.params.fValue; this.initPerfFiles(); break; - case 'perf-fire': - this.perfCallData = data.params - this.initPerfFire(); - break; - case 'perf-call-chain': - if (!this.dataCache.perfCallChain || this.dataCache.perfCallChain.length === 0) { - this.dataCache.perfCallChain = convertJSON(data.params.list) || []; - this.createCallChain(); - } - this.queryCallData(this.perfCallData); - break; - // 查perf_sample表并处理 - case 'perf-sample-cpu': - // 拿到的sample的数据 - this.samplesCpu = convertJSON(data.params.list) || []; - // 处理sample数据 - self.postMessage({ - id: data.id, - action: data.action, - results: this.combinePerfSampleBycallChainId(this.samplesCpu) - }); - break; case 'perf-queryPerfFiles': let files = convertJSON(data.params.list) || []; files.forEach((file: any) => { @@ -169,29 +143,6 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { ); } - initPerfFire() { - this.clearAll(); - this.queryData( - this.currentEventId, - 'perf-call-chain', - `select name, - depth, - callchain_id from perf_callchain`, - {} - ) - } - - queryCallData(data: any) { - const sql = `SELECT id, - callchain_id, - timestamp_trace - start_ts AS timeTip, - thread_id, - cpu_id - FROM - perf_sample,trace_range where ${data[0] == 0 ? 'cpu_id=' : 'thread_id='}${data[1]}`; - this.queryData(this.currentEventId!, 'perf-sample-cpu', sql, {}); - } - initPerfThreads() { this.queryData( this.currentEventId, @@ -243,7 +194,8 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { let arg = `${cpuFilter}${processFilter}${threadFilter}`.substring(3); filterSql = ` and (${arg})`; } - eventTypeFilter = this.eventTypeId ? ` and s.event_type_id = ${this.eventTypeId}` : ''; + const eventTypeId = selectionParam.eventTypeId; + eventTypeFilter = eventTypeId ? ` and s.event_type_id = ${eventTypeId}` : ''; filterSql += eventTypeFilter; this.queryData( this.currentEventId, @@ -275,125 +227,6 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { ); } - // 将perf_sample表的数据根据callchain_id分组并赋值startTime,endTime等等 - combinePerfSampleBycallChainId(sampleList: Array) { - let arr: any = new Array(); - let num = undefined; - for (let i = 0; i < sampleList.length; i++) { - // 若不是相同的callchain_id,赋值 - if (sampleList[i].callchain_id != num) { - arr.push(new hiPrefSample()); - arr[arr.length - 1].children = new Array(); - arr[arr.length - 1].children[0] = new hiperfSymbol(); - arr[arr.length - 1].depth = -1; - arr[arr.length - 1].name = 'name'; - arr[arr.length - 1].callchain_id = sampleList[i].callchain_id; - arr[arr.length - 1].thread_id = sampleList[i].thread_id; - arr[arr.length - 1].id = sampleList[i].id; - if (i !== 0 && i !== sampleList.length - 1 && sampleList[i].callchain_id !== sampleList[i - 1].callchain_id && sampleList[i].callchain_id !== sampleList[i + 1].callchain_id) { - arr[arr.length - 1].startTime = sampleList[i - 1].timeTip; - } else { - arr[arr.length - 1].startTime = sampleList[i].timeTip - } - } - arr[arr.length - 1].endTime = sampleList[i].timeTip - arr[arr.length - 1].totalTime = arr[arr.length - 1].endTime - arr[arr.length - 1].startTime - num = sampleList[i].callchain_id - } - return this.combineChartData(arr); - // return arr; - } - /** - * 建立callChain每个函数的联系,设置depth跟children - */ - private createCallChain(): void { - const jsSymbolMap = this.dataCache.perfCallFireMap; - for (const item of this.dataCache.perfCallChain!) { - jsSymbolMap.set(item.callchain_id.toString() + item.depth, item); - let parentSymbol = jsSymbolMap.get(item.callchain_id.toString() + (item.depth - 1)); - if (parentSymbol) { - switch (parentSymbol.callchain_id) { - case item.callchain_id: - switch (parentSymbol.depth) { - case item.depth - 1: - parentSymbol.children = new Array(); - parentSymbol.children?.push(item) - break; - } - break; - } - } - } - } - - combineChartData(samples: any): Array { - let combineSample: any = []; - // 遍历sample表查到的数据,并且为其匹配相应的callchain数据 - for (let sample of samples) { - let stackTopSymbol = JSON.parse(JSON.stringify(this.dataCache.perfCallFireMap.get(sample.callchain_id.toString() + '0'))) || new hiperfSymbol(); - stackTopSymbol.startTime = sample.startTime; - stackTopSymbol.endTime = sample.endTime; - stackTopSymbol.totalTime = sample.totalTime; - stackTopSymbol.thread_id = sample.thread_id; - stackTopSymbol.cpu_id = sample.thread_id; - this.setDur(stackTopSymbol) - sample.children = new Array(); - sample.children.push(stackTopSymbol) - // 每一项都和combineSample对比 - if (combineSample.length === 0) { - combineSample.push(sample) - } else { - if (this.perfCallData[0] === 0) { - if (combineSample[combineSample.length - 1].thread_id === sample.thread_id) { - this.combinePerfCallData(combineSample[combineSample.length - 1], sample) - } else { combineSample.push(sample) }; - } else { - if (combineSample[combineSample.length - 1].cpu_id === sample.cpu_id) { - this.combinePerfCallData(combineSample[combineSample.length - 1], sample) - } else { combineSample.push(sample) }; - } - } - } - return combineSample; - } - - // 递归设置dur,startTime,endTime - setDur(data: any) { - if (data.children && data.children.length > 0) { - data.children[0].totalTime = data.totalTime; - data.children[0].startTime = data.startTime; - data.children[0].endTime = data.endTime; - data.children[0].thread_id = data.thread_id; - data.children[0].cpu_id = data.cpu_id; - this.setDur(data.children[0]) - } else { - return - } - } - - // hiperf火焰图合并逻辑 - combinePerfCallData(data1: any, data2: any) { - if (data1.depth === data2.depth && data1.name === data2.name) { - data1.endTime = data2.endTime; - data1.totalTime = data1.endTime - data1.startTime; - if (data1.children && data1.children.length > 0 && data2.children && data2.children.length > 0) { - if (data1.children[data1.children.length - 1].depth === data2.children[0].depth && data1.children[data1.children.length - 1].name !== data2.children[0].name) { - data1.children.push(data2.children[0]) - } else { - this.combinePerfCallData(data1.children[data1.children.length - 1], data2.children[0]); - } - } else if (data2.children && data2.children.length > 0 && (!data1.children || data1.children.length === 0)) { - data1.endTime = data2.endTime; - data1.totalTime = data1.endTime - data1.endTime; - data1.children = new Array(); - data1.children.push(data2.children[0]); - } else { - } - } - else { } - return - } - clearAll() { this.filesData = {}; this.samplesData = {}; @@ -920,9 +753,6 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { case 'splitTree': this.splitPerfTree(this.allProcess, item.funcArgs[0], item.funcArgs[1], item.funcArgs[2]); break; - case 'setEventTypeId': - this.eventTypeId = item.funcArgs[0]; - break; case 'setSearchValue': this.searchValue = item.funcArgs[0]; break; @@ -1357,18 +1187,3 @@ export function timeMsFormat2p(ns: number) { } return perfResult; } - - -class hiPrefSample { - name: string = ""; - depth: number = 0; - callchain_id: number = 0; - totalTime: number = 0; - thread_id: number = 0; - id: number = 0; - startTime: number = 0; - endTime: number = 0; - timeTip: number = 0; - cpu_id: number = 0; - stack?: Array; -} \ No newline at end of file diff --git a/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/ide/src/trace/database/ui-worker/ProcedureWorker.ts index 7ae2190c..bfeef7d2 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorker.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorker.ts @@ -56,7 +56,6 @@ import { FrameSpacingRender } from './ProcedureWorkerFrameSpacing.js'; import { JsCpuProfilerRender } from './ProcedureWorkerCpuProfiler.js'; import { SnapshotRender } from './ProcedureWorkerSnapshot.js'; import { LogRender } from './ProcedureWorkerLog.js'; -import { HiperfCallChartRender } from './ProcedureWorkerHiPerfCallChart.js'; let dataList: any = {}; let dataList2: any = {}; @@ -87,7 +86,6 @@ export let renders: any = { 'HiPerf-Group': new EmptyRender(), monitorGroup: new EmptyRender(), 'HiPerf-Cpu': new HiperfCpuRender(), - 'Hiperf-callchart':new HiperfCallChartRender(), 'HiPerf-Process': new HiperfProcessRender(), 'HiPerf-Thread': new HiperfThreadRender(), 'HiPerf-Report-Event': new HiperfEventRender(), diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCallChart.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCallChart.ts deleted file mode 100644 index 53e0ff6c..00000000 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerHiPerfCallChart.ts +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ColorUtils } from '../../component/trace/base/ColorUtils.js'; -import { - BaseStruct, - type Rect, - ns2x, - drawString, - Render, - isFrameContainPoint -} from './ProcedureWorkerCommon.js'; -import { TraceRow } from '../../component/trace/base/TraceRow.js'; -import { HiPerfThreadStruct } from './ProcedureWorkerHiPerfThread.js'; -import { hiPerfchartFrame } from '../../bean/perfStruct.js'; - -export class HiperfCallChartRender extends Render { - renderMainThread(req: any, row: TraceRow): void { - let list = row.dataList; - let filter = row.dataListCache; - hiperf( - list, - filter, - TraceRow.range!.startNS, - TraceRow.range!.endNS, - TraceRow.range!.totalNS, - row.frame, - req.useCache || !TraceRow.range!.refresh - ); - req.context.beginPath();; - let find = false; - let offset = 5; - for (let re of filter) { - HiPerfCallChartStruct.draw(req.context, re); - if (row.isHover) { - if (re.endTime - re.startTime === 0 || - re.endTime - re.startTime == null || - re.endTime - re.startTime === undefined) { - if (re.frame && - row.hoverX >= re.frame.x - offset && - row.hoverX <= re.frame.x + re.frame.width + offset && - row.hoverY >= re.frame.y && - row.hoverY <= re.frame.y + re.frame.height) { - HiPerfCallChartStruct.hoverPerfCallCutStruct = re; - find = true; - } - } else { - if (re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { - HiPerfCallChartStruct.hoverPerfCallCutStruct = re; - find = true - } - } - } - if (!find && row.isHover) { - HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined - } - } - req.context.closePath(); - } -} - -// 火焰图数据模板 -let padding = 1; -export class HiPerfCallChartStruct extends BaseStruct { - static selectStruct: HiPerfCallChartStruct | undefined; - static hoverPerfCallCutStruct: HiPerfCallChartStruct | undefined; - id: number = 0; - name: string = ''; - startTime: number = 0; - endTime: number = 0; - depth: number = 0; - children!: Array; - isSelect: boolean = false; - totalTime: number = 0; - callchain_id:number = 0; - - static setPerfFrame( - hiPerfNode: any, - startNS: number, - endNS: number, - totalNS: number, - frame: Rect - ): void { - let x1: number, x2: number; - if ((hiPerfNode.startTime || 0) > startNS && (hiPerfNode.startTime || 0) < endNS) { - x1 = ns2x(hiPerfNode.startTime || 0, startNS, endNS, totalNS, frame); - } else { - x1 = 0; - } - if ( - (hiPerfNode.startTime || 0) + (hiPerfNode.totalTime || 0) > startNS && - (hiPerfNode.startTime || 0) + (hiPerfNode.totalTime || 0) < endNS - ) { - x2 = ns2x( - (hiPerfNode.startTime || 0) + (hiPerfNode.totalTime || 0), - startNS, - endNS, - totalNS, - frame - ); - } else { - x2 = frame.width; - } - if (!hiPerfNode.frame) { - hiPerfNode.frame = {}; - } - let getV: number = x2 - x1 < 1 ? 1 : x2 - x1; - hiPerfNode.frame.x = Math.floor(x1); - hiPerfNode.frame.y = hiPerfNode.depth * 20; - hiPerfNode.frame.width = Math.ceil(getV); - hiPerfNode.frame.height = 20; - } - - static draw(ctx: CanvasRenderingContext2D, data: HiPerfCallChartStruct): void { - if (data.frame) { - if (data.endTime - data.startTime === undefined || data.endTime - data.startTime === null) { - } else { - ctx.globalAlpha = 1; - if (data.name === '(program)') { - ctx.fillStyle = '#ccc'; - } else if (data.name === '(idle)') { - ctx.fillStyle = '#f0f0f0'; - } else { - ctx.fillStyle = - ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', 0, ColorUtils.FUNC_COLOR.length)]; - } - let miniHeight = 20; - if (HiPerfCallChartStruct.hoverPerfCallCutStruct && data === HiPerfCallChartStruct.hoverPerfCallCutStruct) { - ctx.globalAlpha = 0.7; - } - ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); - if (data.frame.width > 8) { - ctx.lineWidth = 1; - ctx.fillStyle = '#fff'; - ctx.textBaseline = 'middle'; - drawString(ctx, `${data.name || ''}`, 4, data.frame, data); - } - if (data === HiPerfCallChartStruct.selectStruct) { - ctx.strokeStyle = '#000'; - ctx.lineWidth = 2; - ctx.strokeRect( - data.frame.x + 1, - data.frame.y + 1, - data.frame.width - 2, - miniHeight - padding * 2 - 2 - ); - } - } - } - } -} - -export function hiperf( - list: Array, - filter: Array, - startNS: number, - endNS: number, - totalNS: number, - frame: Rect, - use: boolean -): void { - if (use && filter.length > 0) { - for (let i = 0, len = filter.length; i < len; i++) { - if ((filter[i].startTime || 0) + (filter[i].totalTime || 0) >= startNS && (filter[i].startTime || 0) <= endNS) { - HiPerfCallChartStruct.setPerfFrame(filter[i], startNS, endNS, totalNS, frame); - } else { - filter[i].frame = null; - } - } - return; - } - filter.length = 0; - if (list) { - let groups = list - .filter((it) => (it.startTime ?? 0) + (it.totalTime ?? 0) >= startNS && (it.startTime ?? 0) <= endNS) - .map((it) => { - HiPerfCallChartStruct.setPerfFrame(it, startNS, endNS, totalNS, frame); - return it; - }) - .reduce((pre, current) => { - (pre[`${current.frame.x}-${current.depth}`] = pre[`${current.frame.x}-${current.depth}`] || []).push(current); - return pre; - }, {}); - Reflect.ownKeys(groups).map((kv) => { - // 从小到大排序 - let arr = groups[kv].sort((a: hiPerfchartFrame, b: hiPerfchartFrame) => b.totalTime - a.totalTime); - filter.push(arr[0]); - }); - } -} -- Gitee From 5d10b455d027dc7afaefff7baa34e17e38cf80fd Mon Sep 17 00:00:00 2001 From: zhangzepeng Date: Mon, 30 Oct 2023 14:20:28 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E2=80=99fix=EF=BC=9A=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E6=89=93=E5=BC=80trace=E9=97=AE=E9=A2=98=E2=80=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangzepeng --- ide/src/index.html | 1 + ide/src/trace/SpApplication.ts | 31 +++++++++---------------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/ide/src/index.html b/ide/src/index.html index fc79a7f2..d6707805 100644 --- a/ide/src/index.html +++ b/ide/src/index.html @@ -1,6 +1,7 @@ + Trace Example +
diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts index f25d7df9..6f9b782a 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts @@ -122,6 +122,9 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { this.eventTypeData.shift(this.typeStatisticsData); return; } + if (statisticAnalysisParam.nativeMemoryStatistic.length > 0) { + Utils.getInstance().initResponseTypeList(statisticAnalysisParam); + } // @ts-ignore this.tableType?.shadowRoot?.querySelector('.table').style.height = this.parentElement.clientHeight - 30 + 'px'; // @ts-ignore diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts index 1a47327a..35577c37 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts @@ -17,7 +17,6 @@ import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; import { LitTable } from '../../../../../base-ui/table/lit-table.js'; import { SelectionParam } from '../../../../bean/BoxSelection.js'; import { - queryNativeHookResponseTypes, queryNativeHookStatistics, queryNativeHookStatisticsMalloc, queryNativeHookStatisticsSubType, @@ -51,7 +50,9 @@ export class TabPaneNMStatstics extends BaseElement { SpNativeMemoryChart.EVENT_HEAP.map((heap) => { this.allMax += heap.sumHeapSize; }); - this.initResponseTypeList(nativeStatisticsParam); + if (nativeStatisticsParam.nativeMemory.length > 0) { + Utils.getInstance().initResponseTypeList(nativeStatisticsParam); + } // @ts-ignore this.nativeStatisticsTbl?.shadowRoot.querySelector('.table').style.height = this.parentElement!.clientHeight - 25 + 'px'; @@ -138,24 +139,6 @@ export class TabPaneNMStatstics extends BaseElement { }); } - initResponseTypeList(val: SelectionParam | any) { - let types: Array = []; - if (val.nativeMemory.indexOf('All Heap & Anonymous VM') != -1) { - types.push("'AllocEvent'"); - types.push("'MmapEvent'"); - } else { - if (val.nativeMemory.indexOf('All Heap') != -1) { - types.push("'AllocEvent'"); - } - if (val.nativeMemory.indexOf('All Anonymous VM') != -1) { - types.push("'MmapEvent'"); - } - } - queryNativeHookResponseTypes(val.leftNs, val.rightNs, types).then((res) => { - procedurePool.submitWithName('logic1', 'native-memory-init-responseType', res, undefined, () => {}); - }); - } - setMemoryTypeData(val: SelectionParam, result: Array, arr: Array) { let all: NativeHookStatisticsTableData | null = null; let heap: NativeHookStatisticsTableData | null = null; diff --git a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts index c050252a..7b9bb689 100644 --- a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts +++ b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts @@ -281,24 +281,11 @@ export class TabPaneTaskFrames extends BaseElement { } static getExecuteId(funName: string): string { - let strArray = funName.split(','); - let executeStr = ''; - let executeId = ''; - let endStr = ''; - if (strArray.length >= 2) { - executeStr = strArray[1]; - if (funName.indexOf(ALLOCATION_TASK) >= 0 || funName.indexOf(PERFORM_TASK) >= 0) { - executeId = executeStr.split(':')[1].trim(); - } else if (funName.indexOf(END_TASK) >= 0) { - endStr = executeStr.split(':')[1].trim(); - if (endStr.indexOf('[') >= 0) { - executeId = endStr.substring(0, endStr.indexOf('[')); - } else { - executeId = endStr; - } - } + const executeIdMatch = funName.match(/executeId\s*:\s*(\d+)/i); + if (executeIdMatch && executeIdMatch.length > 1) { + return executeIdMatch[1]; } - return executeId; + return ''; } static getPriorityId(funName: string): number { diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 0d8e5986..13c9f066 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -1691,23 +1691,28 @@ export const queryAllHookData = (rightNs: number): Promise -): Promise> => - query( + types: Array, + isStatistic: boolean +): Promise> => { + const table = isStatistic ? 'native_hook_statistic' : 'native_hook'; + const tsKey = isStatistic ? 'ts' : 'start_ts'; + const type = isStatistic ? 'type' : 'event_type'; + return query( 'queryNativeHookResponseTypes', ` - select - distinct last_lib_id as lastLibId, - data_dict.data as value - from - native_hook A ,trace_range B - left join data_dict on A.last_lib_id = data_dict.id - where - A.start_ts - B.start_ts - between ${leftNs} and ${rightNs} and A.event_type in (${types.join(',')}); - `, + select + distinct last_lib_id as lastLibId, + data_dict.data as value + from + ${table} A ,trace_range B + left join data_dict on A.last_lib_id = data_dict.id + where + A.${tsKey} - B.start_ts + between ${leftNs} and ${rightNs} and A.${type} in (${types.join(',')}); + `, { $leftNs: leftNs, $rightNs: rightNs, $types: types } ); +}; /** * HiPerf */ diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts index 8884cf98..7bb0d61b 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCPU.ts @@ -373,9 +373,7 @@ export class CpuStruct extends BaseStruct { } } if (data.nofinish && width > 4) { - ctx.fillStyle = ColorUtils.funcTextColor( - ColorUtils.colorForTid((data.processId || 0) > 0 ? data.processId || 0 : data.tid || 0) - ); + ctx.fillStyle = '#fff'; let ruptureWidth = 4; let ruptureNode = 8; ctx.moveTo(data.frame.x + data.frame.width - 1, data.frame.y); -- Gitee From c45f475f40c2914227ec0f8aec9bfec537074e38 Mon Sep 17 00:00:00 2001 From: zhangzepeng Date: Mon, 30 Oct 2023 14:28:50 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E2=80=99fix1.=E7=82=B9=E5=87=BB=E7=AC=AC?= =?UTF-8?q?=E4=B8=80=E5=B1=82=E5=94=A4=E9=86=92=E6=A0=91=E6=B6=88=E5=A4=B1?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E6=94=B92.freq=E8=A2=AB=E6=A1=86?= =?UTF-8?q?=E9=80=89=E5=8C=BA=E5=9F=9F=E6=97=A0=E6=95=B0=E6=8D=AE=E6=97=B6?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E6=8C=89=E9=92=AE=E9=A1=B5=E9=9D=A2=E6=98=BE?= =?UTF-8?q?=E7=A4=BAloading=E7=9A=84=E6=83=85=E5=86=B53.=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E6=A1=86=E5=AF=B90=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=81=9A=E9=99=90=E5=88=B6,=E5=8F=AF=E4=BB=A5=E6=97=A0?= =?UTF-8?q?=E9=99=90=E8=BE=93=E5=85=A50=E7=9A=84=E9=97=AE=E9=A2=984.Hiperf?= =?UTF-8?q?=E6=A8=A1=E5=9D=97transfer=E9=80=89=E4=B8=AD=E5=92=8C=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E7=AD=9B=E9=80=89=E8=81=94=E5=8A=A85.hilog=E7=9A=84me?= =?UTF-8?q?ssage=E8=BF=87=E9=95=BF=E6=97=B6=E5=8F=AF=E4=BB=A5=E5=B7=A6?= =?UTF-8?q?=E5=8F=B3=E6=BB=91=E5=8A=A86.=E8=BE=93=E5=85=A5=E6=A1=86?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E8=BE=93=E5=85=A5=EF=BC=8C=E4=B8=8D=E6=8C=89?= =?UTF-8?q?=E5=9B=9E=E8=BD=A6=EF=BC=8C=E8=B7=B3=E8=BD=AC=E9=A1=B5=E6=B8=85?= =?UTF-8?q?=E7=A9=BA=E2=80=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangzepeng --- ide/src/base-ui/select/LitAllocationSelect.ts | 9 +- ide/src/base-ui/select/LitSelect.ts | 2 + ide/src/base-ui/select/LitSelectV.ts | 12 + ide/src/base-ui/slider/LitSlider.ts | 9 + ide/src/base-ui/table/LitPageTable.ts | 6 +- ide/src/base-ui/table/lit-table.ts | 1 + ide/src/index.html | 2 +- ide/src/trace/SpApplication.ts | 50 +-- ide/src/trace/bean/BoxSelection.ts | 1 - ide/src/trace/component/SpSystemTrace.ts | 50 ++- .../trace/component/setting/SpAllocations.ts | 21 + .../trace/component/setting/SpFileSystem.ts | 6 + .../trace/component/setting/SpProbesConfig.ts | 6 + .../trace/component/setting/SpRecordPerf.ts | 7 + .../component/setting/SpRecordSetting.ts | 15 + .../trace/component/trace/base/TraceSheet.ts | 10 - .../component/trace/base/TraceSheetConfig.ts | 14 +- .../trace/component/trace/search/Search.ts | 32 +- .../component/trace/sheet/TabPaneFilter.ts | 14 + .../trace/sheet/cpu/TabPaneFrequencySample.ts | 44 +- .../sheet/frequsage/TabPaneFreqDataCut.ts | 425 ++++++++++++++++++ .../trace/sheet/frequsage/TabPaneFreqUsage.ts | 251 +++++++++++ .../trace/sheet/hilog/TabPaneHiLogSummary.ts | 112 +++-- .../trace/sheet/hilog/TabPaneHiLogs.ts | 88 +--- .../trace/sheet/hiperf/TabPerfProfile.ts | 67 +-- ide/src/trace/database/SqlLite.ts | 90 ++++ .../logic-worker/ProcedureLogicWorkerPerf.ts | 11 +- 27 files changed, 1118 insertions(+), 237 deletions(-) create mode 100644 ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts create mode 100644 ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts diff --git a/ide/src/base-ui/select/LitAllocationSelect.ts b/ide/src/base-ui/select/LitAllocationSelect.ts index 39587dc5..d39a5099 100644 --- a/ide/src/base-ui/select/LitAllocationSelect.ts +++ b/ide/src/base-ui/select/LitAllocationSelect.ts @@ -216,7 +216,14 @@ export class LitAllocationSelect extends BaseElement { `; } - connectedCallback() {} + connectedCallback() { + this.selectAllocationInputEl!.onkeydown = (ev): void => { + // @ts-ignore + if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + ev.preventDefault(); + } + }; + } initData() { this.selectAllocationInputEl = this.shadowRoot!.querySelector('input'); diff --git a/ide/src/base-ui/select/LitSelect.ts b/ide/src/base-ui/select/LitSelect.ts index 28d1dded..ad6e60f1 100644 --- a/ide/src/base-ui/select/LitSelect.ts +++ b/ide/src/base-ui/select/LitSelect.ts @@ -439,6 +439,8 @@ export class LitSelect extends BaseElement { ); } } + } else if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + ev.preventDefault(); } }; } diff --git a/ide/src/base-ui/select/LitSelectV.ts b/ide/src/base-ui/select/LitSelectV.ts index dc032a07..32b2c054 100644 --- a/ide/src/base-ui/select/LitSelectV.ts +++ b/ide/src/base-ui/select/LitSelectV.ts @@ -158,6 +158,18 @@ export class LitSelectV extends BaseElement { this.selectVBody = this.shadowRoot!.querySelector('.body') as HTMLDivElement; this.selectVOptions = this.shadowRoot!.querySelector('.body-opt') as HTMLDivElement; this.selectVIconEl = this.shadowRoot!.querySelector('.icon'); + this.selectVInputEl!.onkeydown = (ev: KeyboardEvent) => { + // @ts-ignore + if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + ev.preventDefault(); + } + }; + this.selectVSearchInputEl!.onkeydown = (ev: KeyboardEvent) => { + // @ts-ignore + if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + ev.preventDefault(); + } + }; this.onclick = (ev: any) => { if (this.focused === false) { this.focused = true; diff --git a/ide/src/base-ui/slider/LitSlider.ts b/ide/src/base-ui/slider/LitSlider.ts index 060e6812..eeb8b428 100644 --- a/ide/src/base-ui/slider/LitSlider.ts +++ b/ide/src/base-ui/slider/LitSlider.ts @@ -268,9 +268,17 @@ export class LitSlider extends BaseElement { // Add a slider for input event listeners this.litSlider?.addEventListener('input', this.inputChangeEvent); this.litSlider?.addEventListener('change', this.inputChangeEvent); + this.litSlider?.addEventListener('keydown', this.inputKeyDownEvent); this.litSliderStyle = this.sliderStyle; } + // @ts-ignore + inputKeyDownEvent = (ev) => { + if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + ev.preventDefault(); + } + }; + inputChangeEvent = (event: any) => { if (this.litSlider) { this.currentValue = parseInt(this.litSlider?.value); @@ -293,6 +301,7 @@ export class LitSlider extends BaseElement { disconnectedCallback() { this.litSlider?.removeEventListener('input', this.inputChangeEvent); this.litSlider?.removeEventListener('change', this.inputChangeEvent); + this.litSlider?.removeEventListener('change', this.inputKeyDownEvent); } adoptedCallback() {} diff --git a/ide/src/base-ui/table/LitPageTable.ts b/ide/src/base-ui/table/LitPageTable.ts index dc147693..93876573 100644 --- a/ide/src/base-ui/table/LitPageTable.ts +++ b/ide/src/base-ui/table/LitPageTable.ts @@ -424,6 +424,10 @@ export class LitPageTable extends BaseElement { :host([hideDownload]) .export{ display: none; } + .td::-webkit-scrollbar { + width: 0; + background-color: transparent; + } @@ -1274,7 +1278,7 @@ export class LitPageTable extends BaseElement { let td: any; td = document.createElement('div'); td.classList.add('td'); - td.style.overflow = 'hidden'; + td.style.overflow = 'scroll hidden'; td.style.textOverflow = 'ellipsis'; td.style.whiteSpace = 'nowrap'; td.dataIndex = dataIndex; diff --git a/ide/src/base-ui/table/lit-table.ts b/ide/src/base-ui/table/lit-table.ts index 0070821a..4b46b866 100644 --- a/ide/src/base-ui/table/lit-table.ts +++ b/ide/src/base-ui/table/lit-table.ts @@ -247,6 +247,7 @@ export class LitTable extends HTMLElement { transition: opacity 0.2s; outline: none; position: relative; + overflow: hidden; } .button-icon:active { background: var(--dark-background1,#f5f5f5) diff --git a/ide/src/index.html b/ide/src/index.html index fc79a7f2..370f725d 100644 --- a/ide/src/index.html +++ b/ide/src/index.html @@ -1,6 +1,6 @@ - + Trace Example +
+ + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + ` + } + dataLoopCut(threadId: any, threadFunc: any, resultList: any) { + let threadIdValue = threadId.value.trim(); + let threadFuncName = threadFunc.value.trim(); + let leftNS = this.currentSelectionParam.leftNs; + let rightNS = this.currentSelectionParam.rightNs; + let tableValue: any = this.threadStatesTbl; + tableValue.value = []; + if (/^[0-9]*$/.test(threadIdValue)) { + querySearchFuncData(threadFuncName, threadIdValue, leftNS, rightNS).then(res => { + let displayArr = JSON.parse(JSON.stringify(resultList)); + let timeDur = this.currentSelectionParam.recordStartNs; + let cutArr = new Array(); + // 根据线程id及方法名获取的数据,处理后用作切割时间依据,时间跨度为整个方法开始时间到末个方法开始时间 + for (let i of res) { + cutArr.push({ 'ts': i.startTime + timeDur }); + } + // 将数据进行切割处理 + let finalArr = new Array(); + let finalResultArr = new Array(); + const tsMutiple = 1000000000; + finalResultArr.push({ 'thread': displayArr[0].thread, 'ts': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + for (let i = 0; i < cutArr.length - 1; i++) { + for (let j = 0; j < displayArr.length; j++) { + displayArr[j].ts = displayArr[j].ts * tsMutiple; + if (displayArr[j].ts >= cutArr[i].ts) { + if ((displayArr[j].ts + displayArr[j].dur) <= cutArr[i + 1].ts) { + finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * displayArr[j].dur) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': displayArr[j].dur, 'percent': displayArr[j].percent, 'state': 'Running', 'ts': (displayArr[j].ts - timeDur) / tsMutiple, 'id': i }); + } else { + if (cutArr[i + 1].ts - displayArr[j].ts > 0) { + finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (cutArr[i + 1].ts - displayArr[j].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': cutArr[i + 1].ts - displayArr[j].ts, 'percent': displayArr[j].percent * ((cutArr[i + 1].ts - displayArr[j].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (displayArr[j].ts - timeDur) / tsMutiple, 'id': i }); + break; + } + } + } else { + if ((displayArr[j].ts + displayArr[j].dur) > cutArr[i + 1].ts) { + finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (cutArr[i + 1].ts - cutArr[i].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': cutArr[i + 1].ts - cutArr[i].ts, 'percent': displayArr[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'id': i }); + } + if ((displayArr[j].ts + displayArr[j].dur) > cutArr[i].ts && (displayArr[j].ts + displayArr[j].dur) < cutArr[i + 1].ts) { + finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (displayArr[j].dur + displayArr[j].ts - cutArr[i].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': displayArr[j].dur + displayArr[j].ts - cutArr[i].ts, 'percent': displayArr[j].percent * ((displayArr[j].dur + displayArr[j].ts - cutArr[i].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'id': i }); + } + } + } + finalResultArr[0].children.push({ 'thread': displayArr[0].thread, 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array(), 'id': i }); + } + + for (let i = 0; i < finalArr.length; i++) { + for (let j = i + 1; j < finalArr.length; j++) { + if (finalArr[i].cpu === finalArr[j].cpu && finalArr[i].freq === finalArr[j].freq && finalArr[i].id === finalArr[j].id) { + finalArr[i].dur += finalArr[j].dur; + finalArr[i].percent += finalArr[j].percent; + finalArr[i].count += finalArr[j].count; + finalArr.splice(j, 1); + j--; + } + } + finalArr[i].percent = Number((finalArr[i].percent).toFixed(2)); + } + + let newArr1 = JSON.parse(JSON.stringify(finalResultArr[0])); + let newArr2 = JSON.parse(JSON.stringify(finalArr)); + let finalResult = new Array(this.mergeTree(newArr1, newArr2)); + this.threadStatesTblSource = finalResult[0].children.length > 0 ? finalResult : []; + this.threadStatesTbl!.recycleDataSource = finalResult[0].children.length > 0 ? finalResult : []; + }) + } else { + alert('请输入正确的线程ID'); + } + } + dataSingleCut(threadId: any, threadFunc: any, resultList: any) { + let threadIdValue = threadId.value.trim(); + let threadFuncName = threadFunc.value.trim(); + let leftNS = this.currentSelectionParam.leftNs; + let rightNS = this.currentSelectionParam.rightNs; + let tableValue: any = this.threadStatesTbl; + tableValue.value = []; + if (/^[0-9]*$/.test(threadIdValue)) { + querySearchFuncData(threadFuncName, threadIdValue, leftNS, rightNS).then(result => { + let [...targetList] = JSON.parse(JSON.stringify(resultList)); + let timeDur = this.currentSelectionParam.recordStartNs; + let dealArr = new Array(); + for (let i of result) { + if (i.startTime + timeDur + i.dur < this.currentSelectionParam.rightNs + timeDur) { + dealArr.push({ 'ts': i.startTime + timeDur, 'dur': i.dur }); + } + } + let finalResultArr = new Array(); + finalResultArr.push({ 'thread': targetList[0].thread, 'ts': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + let resList = new Array(); + const tsMutiple = 1000000000; + for (let i = 0; i < dealArr.length; i++) { + for (let j = 0; j < targetList.length; j++) { + targetList[j].ts = targetList[j].ts * tsMutiple; + if (dealArr[i].ts < targetList[j].ts) { + if (dealArr[i].ts + dealArr[i].dur > targetList[j].ts) { + if (dealArr[i].ts + dealArr[i].dur > targetList[j].ts + targetList[j].dur) { + resList.push({ 'thread': targetList[i].thread, 'ts': (targetList[j].ts - timeDur) / tsMutiple, 'count': (targetList[j].freq * targetList[j].dur) / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': targetList[j].dur, 'percent': targetList[j].percent, 'state': 'Running', 'id': i }); + } else { + resList.push({ 'thread': targetList[j].thread, 'ts': (targetList[j].ts - timeDur) / tsMutiple, 'count': (dealArr[i].ts + dealArr[i].dur - targetList[j].ts) * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': dealArr[i].ts + dealArr[i].dur - targetList[j].ts, 'percent': (dealArr[i].ts + dealArr[i].dur - targetList[j].ts) / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); + break; + } + } + } else { + if (targetList[j].ts + targetList[j].dur > dealArr[i].ts) { + if (targetList[j].ts + targetList[j].dur > dealArr[i].ts + dealArr[i].dur) { + resList.push({ 'thread': targetList[j].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': dealArr[i].dur * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': dealArr[i].dur, 'percent': dealArr[i].dur / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); + break; + } else { + resList.push({ 'thread': targetList[j].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': (targetList[j].ts + targetList[j].dur - dealArr[i].ts) * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': targetList[j].ts + targetList[j].dur - dealArr[i].ts, 'percent': (targetList[j].ts + targetList[j].dur - dealArr[i].ts) / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); + } + } + } + } + finalResultArr[0].children.push({ 'thread': targetList[0].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array(), 'id': i }); + } + // 合并相同周期内的数据 + for (let i = 0; i < resList.length; i++) { + for (let j = i + 1; j < resList.length; j++) { + if (resList[i].cpu === resList[j].cpu && resList[i].freq === resList[j].freq && resList[i].id === resList[j].id) { + resList[i].dur += resList[j].dur; + resList[i].percent += resList[j].percent; + resList[i].count += resList[j].count; + resList.splice(j, 1); + j--; + } + } + resList[i].percent = Number((resList[i].percent).toFixed(2)); + } + + let newArr1 = JSON.parse(JSON.stringify(finalResultArr[0])); + let newArr2 = JSON.parse(JSON.stringify(resList)); + let finalResult = new Array(this.mergeTree(newArr1, newArr2)); + + this.threadStatesTblSource = finalResult[0].children.length > 0 ? finalResult : []; + this.threadStatesTbl!.recycleDataSource = finalResult[0].children.length > 0 ? finalResult : []; + }) + } else { + alert('请输入正确的线程ID'); + } + } + + mergeTree(arr1: any, arr2: any) { + for (let i = 0; i < arr1.children.length; i++) { + // 改成map对象做标记 + let cpuArr = new Array(); + let flagMap = new Map(); + let flag = 0; + for (let j = 0; j < arr2.length; j++) { + if (arr1.children[i].id == arr2[j].id) { + if (!cpuArr.includes(arr2[j].cpu)) { + flagMap.set(arr2[j].cpu, flag); + cpuArr.push(arr2[j].cpu); + arr1.children[i].children.push({ 'thread': arr2[j].thread, 'count': 0, 'cpu': arr2[j].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', 'ts': '', children: new Array(), 'id': arr2[j].id }); + if (arr1.children[i].children[flag].cpu == arr2[j].cpu && arr1.children[i].children[flag].id == arr2[j].id) { + arr1.children[i].children[flag].children.push(arr2[j]); + arr1.children[i].children[flag].dur += arr2[j].dur; + arr1.children[i].children[flag].percent += arr2[j].percent; + arr1.children[i].children[flag].count += arr2[j].count; + arr1.children[i].percent += arr1.children[i].children[flag].percent; + arr1.children[i].children[flag].percent = Number(arr1.children[i].children[flag].percent.toFixed(2)); + arr1.children[i].dur += arr1.children[i].children[flag].dur; + arr1.children[i].count += arr1.children[i].children[flag].count; + flag++; + arr2.splice(j, 1); + j--; + } + } else { + // 利用map做数据处理 + let count = flagMap.get(arr2[j].cpu); + if (arr1.children[i].children[count].cpu == arr2[j].cpu && arr1.children[i].children[count].id == arr2[j].id) { + arr1.children[i].children[count].children.push(arr2[j]); + arr1.children[i].children[count].dur += arr2[j].dur; + arr1.children[i].children[count].percent += arr2[j].percent; + arr1.children[i].children[count].count += arr2[j].count; + arr1.children[i].percent += arr2[j].percent; + arr1.children[i].children[count].percent = Number(arr2[j].percent.toFixed(2)); + arr1.children[i].dur += arr2[j].dur; + arr1.children[i].count += arr2[j].count; + arr2.splice(j, 1); + j--; + } + } + } else { + break; + } + } + arr1.children[i].children.sort((a: any, b: any) => a.cpu - b.cpu); + arr1.percent += arr1.children[i].percent; + arr1.children[i].percent = Number(arr1.children[i].percent.toFixed(2)); + arr1.dur += arr1.children[i].dur; + arr1.count += arr1.children[i].count; + } + arr1.percent = Number(arr1.percent.toFixed(2)); + return arr1; + } +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts new file mode 100644 index 00000000..d0301e1c --- /dev/null +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; +import '../../../StackBar.js'; +import { getTabRunningPercent, queryCpuFreqUsageData, queryCpuFreqFilterId } from '../../../../database/SqlLite.js'; +import { Utils } from '../../base/Utils.js'; +import { resizeObserver } from '../SheetUtils.js'; + +@element('tabpane-frequsage') +export class TabPaneFreqUsage extends BaseElement { + private threadStatesTbl: LitTable | null | undefined; + private threadStatesTblSource: Array = []; + private currentSelectionParam: Selection | undefined; + + set data(threadStatesParam: SelectionParam | any) { + if (this.currentSelectionParam === threadStatesParam) { + return; + } + this.currentSelectionParam = threadStatesParam; + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + let tableValue: any = this.threadStatesTbl; + tableValue.value = []; + getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then( + (result) => { + queryCpuFreqFilterId().then((r) => { + let IdMap = new Map(); + let queryId = new Array(); + for (let i = 0; i < r.length; i++) { + queryId.push(r[i].id); + IdMap.set(r[i].id, r[i].cpu); + } + queryCpuFreqUsageData(queryId).then((res) => { + if (result != null && result.length > 0) { + let sum = 0; + let dealArr = new Array(); + for (let i of res) { + dealArr.push({ + startNS: i.startNS + threadStatesParam.recordStartNs, + dur: i.dur, + value: i.value, + cpu: IdMap.get(i.filter_id), + }); + } + let targetList = new Array(); + let cpuArr = new Array(); + let finalResultArr = new Array(); + finalResultArr.push({ + thread: '', + count: 0, + cpu: '', + freq: '', + dur: 0, + percent: '100.00', + state: 'Running', + children: new Array(), + }); + for (let e of result) { + if (threadStatesParam.processIds.includes(e.pid) && e.state == 'Running') { + let process = Utils.PROCESS_MAP.get(e.pid); + let thread = Utils.THREAD_MAP.get(e.tid); + e.process = process == null || process.length == 0 ? '[NULL]' : process; + e.thread = thread == null || thread.length == 0 ? '[NULL]' : thread; + e.stateJX = e.state; + e.state = Utils.getEndState(e.stateJX); + sum += e.dur; + targetList.push(e); + if (!cpuArr.includes(e.cpu)) { + cpuArr.push(e.cpu); + finalResultArr[0].thread = + finalResultArr[0].thread == '' ? e.tid + '_' + e.thread : finalResultArr[0].thread; + finalResultArr[0].children.push({ + thread: e.tid + '_' + e.thread, + count: 0, + cpu: e.cpu, + freq: '', + dur: 0, + percent: 0, + state: 'Running', + children: new Array(), + }); + } + } + } + let resultList = new Array(); + for (let i = 0; i < targetList.length; i++) { + for (let j = 0; j < dealArr.length; j++) { + if (targetList[i].cpu == dealArr[j].cpu) { + if (targetList[i].ts > dealArr[j].startNS) { + if (targetList[i].ts < dealArr[j].startNS + dealArr[j].dur) { + if (targetList[i].dur < dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) { + resultList.push({ + thread: targetList[i].tid + '_' + targetList[i].thread, + count: (dealArr[j].value * targetList[i].dur) / 1000, + cpu: targetList[i].cpu, + freq: dealArr[j].value, + dur: targetList[i].dur, + percent: (targetList[i].dur / sum) * 100, + state: 'Running', + ts: targetList[i].ts, + }); + break; + } else { + resultList.push({ + thread: targetList[i].tid + '_' + targetList[i].thread, + count: (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) / 1000, + cpu: targetList[i].cpu, + freq: dealArr[j].value, + dur: dealArr[j].startNS + dealArr[j].dur - targetList[i].ts, + percent: ((dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) / sum) * 100, + state: 'Running', + ts: targetList[i].ts, + }); + } + } + } else { + if (targetList[i].ts + targetList[i].dur > dealArr[j].startNS) { + if (targetList[i].dur + targetList[i].ts - dealArr[j].startNS < dealArr[j].dur) { + resultList.push({ + thread: targetList[i].tid + '_' + targetList[i].thread, + count: + (dealArr[j].value * (targetList[i].dur + targetList[i].ts - dealArr[j].startNS)) / 1000, + cpu: targetList[i].cpu, + freq: dealArr[j].value, + dur: targetList[i].dur + targetList[i].ts - dealArr[j].startNS, + percent: ((targetList[i].dur + targetList[i].ts - dealArr[j].startNS) / sum) * 100, + state: 'Running', + ts: dealArr[j].startNS, + }); + break; + } else { + resultList.push({ + thread: targetList[i].tid + '_' + targetList[i].thread, + count: (dealArr[j].value * dealArr[j].dur) / 1000, + cpu: targetList[i].cpu, + freq: dealArr[j].value, + dur: dealArr[j].dur, + percent: (dealArr[j].dur / sum) * 100, + state: 'Running', + ts: dealArr[j].startNS, + }); + } + } else { + resultList.push({ + thread: targetList[i].tid + '_' + targetList[i].thread, + count: 0, + cpu: targetList[i].cpu, + freq: 'unknown', + dur: targetList[i].dur, + percent: (targetList[i].dur / sum) * 100, + state: 'Running', + ts: targetList[i].ts, + }); + break; + } + } + } + } + } + //合并同一线程内,当运行所在cpu和频点相同时,dur及percent进行累加求和,或许可以进行算法优化 + for (let i = 0; i < resultList.length; i++) { + for (let j = i + 1; j < resultList.length; j++) { + if (resultList[i].cpu == resultList[j].cpu && resultList[i].freq == resultList[j].freq) { + resultList[i].dur += resultList[j].dur; + resultList[i].percent += resultList[j].percent; + resultList[i].count += resultList[j].count; + resultList.splice(j, 1); + j--; + } + } + resultList[i].percent = Number(resultList[i].percent.toFixed(2)); + resultList[i].ts = resultList[i].ts - threadStatesParam.recordStartNs; + } + finalResultArr[0].children.sort((a: any, b: any) => a.cpu - b.cpu); + // 转成树结构数据进行展示 + for (let i = 0; i < finalResultArr[0].children.length; i++) { + for (let j = 0; j < resultList.length; j++) { + if (finalResultArr[0].children[i].cpu == resultList[j].cpu) { + finalResultArr[0].children[i].children.push(resultList[j]); + finalResultArr[0].children[i].dur += resultList[j].dur; + finalResultArr[0].children[i].percent += resultList[j].percent; + finalResultArr[0].children[i].count += resultList[j].count; + resultList.splice(j, 1); + j--; + } + } + finalResultArr[0].children[i].percent = finalResultArr[0].children[i].percent.toFixed(2); + finalResultArr[0].dur += finalResultArr[0].children[i].dur; + finalResultArr[0].count += finalResultArr[0].children[i].count; + } + this.threadStatesTblSource = finalResultArr; + this.threadStatesTbl!.recycleDataSource = finalResultArr; + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + } + }); + }); + } + ); + } + initElements(): void { + this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-percent'); + } + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadStatesTbl!); + } + initHtml(): string { + return ` + + + + + + + + + + + + + + + + + + `; + } +} diff --git a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts index 3034a973..be453176 100644 --- a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts +++ b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts @@ -24,7 +24,6 @@ import { LitIcon } from '../../../../../base-ui/icon/LitIcon.js'; export class TabPaneHiLogSummary extends BaseElement { private logSummaryTable: HTMLDivElement | undefined | null; private summaryDownLoadTbl: LitTable | undefined | null; - private parentTabEl: HTMLElement | undefined | null; private systemLogSource: LogStruct[] = []; private logTreeNodes: LogTreeNode[] = []; private expansionDiv: HTMLDivElement | undefined | null; @@ -46,7 +45,7 @@ export class TabPaneHiLogSummary extends BaseElement { this.expansionDownIcon!.name = 'down'; this.logSummaryTable!.innerHTML = ''; this.summaryDownLoadTbl!.recycleDataSource = []; - this.systemLogSource = systemLogDetailParam.hiLogSummary; + this.systemLogSource = systemLogDetailParam.hiLogs; if (this.systemLogSource?.length !== 0 && systemLogDetailParam) { this.refreshRowNodeTable(); } @@ -59,14 +58,20 @@ export class TabPaneHiLogSummary extends BaseElement { this.expansionUpIcon = this.shadowRoot?.querySelector('.expansion-up-icon'); this.expansionDownIcon = this.shadowRoot?.querySelector('.expansion-down-icon'); let summaryTreeLevel: string[] = ['Level', '/Process', '/Tag', '/Message']; - this.shadowRoot?.querySelectorAll('.head-label').forEach((summaryTreeHead) => { - summaryTreeHead.addEventListener('click', () => { + this.shadowRoot?.querySelectorAll('.head-label').forEach((summaryTreeHead): void => { + summaryTreeHead.addEventListener('click', (): void => { this.selectTreeDepth = summaryTreeLevel.indexOf(summaryTreeHead.textContent!); this.expandedNodeList.clear(); this.refreshSelectDepth(this.logTreeNodes); this.refreshRowNodeTable(true); }); }); + this.logSummaryTable!.onscroll = (): void=>{ + let logTreeTableEl = this.shadowRoot?.querySelector('.log-tree-table'); + if (logTreeTableEl) { + logTreeTableEl.scrollTop = this.logSummaryTable?.scrollTop || 0; + } + }; } initHtml(): string { @@ -76,37 +81,55 @@ export class TabPaneHiLogSummary extends BaseElement { display: flex; flex-direction: column; } - .tree-row-tr, .tab-summary-head { + .tab-summary-head { + display: grid; + grid-template-columns: 79% 15%; + height: 30px; + line-height: 30px; + align-items: center; + background-color: white; + } + .tree-row-tr { display: flex; height: 30px; line-height: 30px; align-items: center; background-color: white; + width: 100%; } .tree-row-tr:hover { background-color: #DEEDFF; } - td, .head-label, .head-count { + .head-label, .head-count { white-space: nowrap; overflow: hidden; } .head-label, .head-count { font-weight: bold; } - .count-column-td, .head-count { - margin-left: auto; - margin-right: 40%; - } .row-name-td { white-space: nowrap; - overflow-x: scroll; overflow-y: hidden; display: inline-block; margin-right: 15px; + height: 30px; + } + tr { + height: 30px; } .row-name-td::-webkit-scrollbar { display: none; } + .log-tree-table { + display: grid; + overflow: hidden; + grid-template-rows: repeat(auto-fit, 30px); + position: sticky; + top: 0; + } + .log-tree-table:hover{ + overflow-x: auto; + }
@@ -121,7 +144,7 @@ export class TabPaneHiLogSummary extends BaseElement {
-
+