diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index a77c8bae5b376ce05f291d0cb804be807762d84c..81cd3c3ea2c982428e80752fc04a75e5403a2180 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -1420,6 +1420,17 @@ export class SysCallBoxJumpParam { isJumpPage: boolean | undefined; } +export class PerfSampleBoxJumpParam { + traceId: string | undefined | null; + leftNs: number = 0; + rightNs: number = 0; + isJumpPage: boolean | undefined; + pid: number | undefined; + tid: number | undefined; + count: number = 0; + tsArr: number[] = []; +} + export class SliceBoxJumpParam { traceId: string | undefined | null; leftNs: number = 0; diff --git a/ide/src/trace/bean/FrameChartStruct.ts b/ide/src/trace/bean/FrameChartStruct.ts index de1eeb94f33fb1119a9175451d17092ea664ce23..052b84e2b684c80518c70890d3c6a4218c83a6c1 100644 --- a/ide/src/trace/bean/FrameChartStruct.ts +++ b/ide/src/trace/bean/FrameChartStruct.ts @@ -37,6 +37,7 @@ export class ChartStruct extends BaseStruct { static hoverFuncStruct: ChartStruct | undefined; static selectFuncStruct: ChartStruct | undefined; static lastSelectFuncStruct: ChartStruct | undefined; + static tempSelectStruct: ChartStruct | undefined; isDraw = false; // 是否绘制,太小的不绘制 depth: number = 0; symbol: string = ''; diff --git a/ide/src/trace/bean/PerfProfile.ts b/ide/src/trace/bean/PerfProfile.ts index d35a7eeb2ae24528cfe4f3c5a5f2470c1b8f989a..f7561bff8937bfb10880acc92533a8993e1dae72 100644 --- a/ide/src/trace/bean/PerfProfile.ts +++ b/ide/src/trace/bean/PerfProfile.ts @@ -121,6 +121,9 @@ export class PerfStack { fileId: number = 0; type: number = 0; vaddrInFile: number = 0; + sourceId: number | undefined; + sourceFile: string | undefined; + lineNumber: number | undefined; } export class PerfCmdLine { diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index 8255fec26dfd78bec4a67c691e2cdfe45773fedf..35d663846fb16823b8709a81b49edfd91d2eee9e 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -674,6 +674,20 @@ export class FrameChart extends BaseElement { this.floatHint!.innerHTML = this.hintContent; this.floatHint!.style.display = 'block'; this.floatHint!.style.zIndex = '9999999'; + const countSpan = this.floatHint!.querySelector('.count'); + if (countSpan) { + //@ts-ignore + countSpan.onclick = (e) => { + this.dispatchEvent( + new CustomEvent('td-click', { + detail: ChartStruct.tempSelectStruct, + composed: true, + }) + ); + // @ts-ignore + e.stopPropagation(); + }; + } let tipArea = this.tabPaneFilter?.getBoundingClientRect().top! - this.canvas.getBoundingClientRect().top - @@ -857,6 +871,7 @@ export class FrameChart extends BaseElement { if (ChartStruct.hoverFuncStruct && ChartStruct.hoverFuncStruct !== ChartStruct.selectFuncStruct) { ChartStruct.lastSelectFuncStruct = ChartStruct.selectFuncStruct; ChartStruct.selectFuncStruct = ChartStruct.hoverFuncStruct; + ChartStruct.tempSelectStruct = undefined; this.isClickMode = ChartStruct.selectFuncStruct !== this.rootNode; this.rect.width = this.canvas!.clientWidth; // 重置缩放 @@ -875,8 +890,13 @@ export class FrameChart extends BaseElement { }) ); } + this.hideTip(); + } else { + // mouse right button + if (ChartStruct.hoverFuncStruct) { + ChartStruct.tempSelectStruct = ChartStruct.hoverFuncStruct; + } } - this.hideTip(); } private hideTip(): void { @@ -928,7 +948,7 @@ export class FrameChart extends BaseElement { Lib: ${hoverNode?.lib}
Addr: ${hoverNode?.addr}
${sourceHint} - ${label}: ${count}`; + ${label}: ${count}`; break; } if (this._mode !== ChartMode.Byte) { @@ -984,14 +1004,20 @@ export class FrameChart extends BaseElement { const searchResult = this.searchDataByCoord(this.currentData!, this.canvasX, this.canvasY); if (searchResult && (searchResult.isDraw || searchResult.depth === 0)) { ChartStruct.hoverFuncStruct = searchResult; + if (ChartStruct.hoverFuncStruct !== ChartStruct.tempSelectStruct) { + ChartStruct.tempSelectStruct = undefined; + } // 悬浮的node未改变,不需要更新悬浮框文字信息,不绘图 if (searchResult !== lastNode) { this.updateTipContent(); this.calculateChartData(); } - this.showTip(); + if (ChartStruct.tempSelectStruct === undefined) { + this.showTip(); + } } else { this.hideTip(); + ChartStruct.tempSelectStruct = undefined; ChartStruct.hoverFuncStruct = undefined; } } @@ -1022,7 +1048,6 @@ export class FrameChart extends BaseElement { this.canvas = this.shadowRoot!.querySelector('#canvas')!; this.canvasContext = this.canvas.getContext('2d')!; this.floatHint = this.shadowRoot?.querySelector('#float_hint'); - this.canvas!.oncontextmenu = (): boolean => { return false; }; @@ -1041,10 +1066,11 @@ export class FrameChart extends BaseElement { }; this.canvas!.onmouseleave = (): void => { - this.isFocusing = false; - this.hideTip(); + if (!ChartStruct.tempSelectStruct) { + this.isFocusing = false; + this.hideTip(); + } }; - document.addEventListener('keydown', (e) => { if (!this.isFocusing) { return; @@ -1095,6 +1121,10 @@ export class FrameChart extends BaseElement { .bold{ font-weight: bold; } + .count { + text-decoration: underline; + cursor: pointer + } .text{ max-width:350px; word-break: break-all; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index 386717a37024d20a5c6968bc0d5ccfa3687b2c9a..5a20b88e859eafb17705310524e1cf0c9a1f420c 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -20,7 +20,8 @@ import { BoxJumpParam, SelectionParam, SysCallBoxJumpParam, - SliceBoxJumpParam + SliceBoxJumpParam, + PerfSampleBoxJumpParam } from '../../../bean/BoxSelection'; import { type TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection'; import { type TabPaneFlag } from '../timer-shaft/TabPaneFlag'; @@ -117,6 +118,7 @@ import { info, error } from '../../../../log/Log'; import { XpowerThreadCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; import { TabPaneSysCallChild } from '../sheet/process/TabPaneSysCallChild'; +import { TabPanePerfSampleChild } from '../sheet/hiperf/TabPerfSampleChild'; @element('trace-sheet') @@ -314,6 +316,10 @@ export class TraceSheet extends BaseElement { this.getComponentByID('box-thread-syscall')?.addEventListener('td-click', (evt: unknown) => { this.tdSysCallClickHandler(evt); }); + // @ts-ignore + this.getComponentByID('box-perf-profile')?.addEventListener('td-click', (evt: unknown) => { + this.tdPerfSampleClickHandler(evt); + }); } private perfAnalysisListener(evt: MouseEvent): void { @@ -804,21 +810,21 @@ export class TraceSheet extends BaseElement { let blob: Blob | null = file.slice(writeSize, writeSize + sliceLen); let buffer: ArrayBuffer | null = await blob.arrayBuffer(); let data: Uint8Array | null = new Uint8Array(buffer); - - const dataObject = { + const dataObject = { file_name: fileName, buffer_index: bufferIndex, buffer_size: sliceLen, total_size: file.size, - is_last: writeSize + sliceLen >= file.size, - buffer: Array.from(data), + is_last: writeSize + sliceLen >= file.size }; - - const dataString = JSON.stringify(dataObject); + const jsonStr = `${dataString.length}|${dataString}`; const textEncoder = new TextEncoder(); - const encodedData = textEncoder.encode(dataString); - wsInstance!.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_SAVE_CMD, encodedData); + const jsonData = textEncoder.encode(jsonStr); + let mergeData: Uint8Array = new Uint8Array(jsonData.length + data.length); + mergeData.set(jsonData); + mergeData.set(data, jsonData.length); + wsInstance!.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_SAVE_CMD, mergeData); writeSize += sliceLen; // 等待服务器端确认当前分片的 ACK await waitForAck(); @@ -912,14 +918,14 @@ export class TraceSheet extends BaseElement { -
+
-
+