diff --git a/ide/server/smarperfServer.py b/ide/server/smarperfServer.py index d3d0ffc214351a7e325ee2d39da85091fe314310..e0e977a08abcf1b0e9a66608f5b7df15aed4045b 100644 --- a/ide/server/smarperfServer.py +++ b/ide/server/smarperfServer.py @@ -234,6 +234,7 @@ def get_content_type(file_extension): return 'image/svg+xml' return 'text/plain' + def gen_ssl(cert_file, key_file): serial_number = 123456789 organization = "www.smartperf.com" @@ -247,6 +248,7 @@ def gen_ssl(cert_file, key_file): subprocess.run(["openssl", "x509", "-req", "-days", str(validity_days), "-in", csr_file, "-signkey", key_file, "-out", cert_file, "-set_serial", str(serial_number)]) + class SpServer: def __init__(self, server_address, cert_file_path, keyfile_path): global version diff --git a/ide/src/trace/bean/FrameChartStruct.ts b/ide/src/trace/bean/FrameChartStruct.ts index 507e32d733352e4ba4a007f05c65aeb036110707..8fb13425e5be540b2e04fbc208d8a9c4151914ce 100644 --- a/ide/src/trace/bean/FrameChartStruct.ts +++ b/ide/src/trace/bean/FrameChartStruct.ts @@ -14,10 +14,9 @@ */ import { SpApplication } from '../SpApplication.js'; -import { BaseStruct } from './BaseStruct.js'; import { Rect } from '../component/trace/timer-shaft/Rect.js'; import { warn } from '../../log/Log.js'; -import { drawString } from '../database/ui-worker/ProcedureWorkerCommon.js'; +import { BaseStruct, drawString } from '../database/ui-worker/ProcedureWorkerCommon.js'; const padding: number = 1; const rectHeight = 20; @@ -56,6 +55,7 @@ export class ChartStruct extends BaseStruct { isSearch: boolean = false; isChartSelect: boolean = false; // 是否为点选的调用链 isChartSelectParent: boolean = false; // 用来显示灰色 + tsArray: Array = []; } export enum ChartMode { diff --git a/ide/src/trace/bean/PerfBottomUpStruct.ts b/ide/src/trace/bean/PerfBottomUpStruct.ts index 59f8fdde1a32fb237e0a766cef813f9d5fe8f8ae..ce0a8efef5fd8158db677b646873ea19cc6e462c 100644 --- a/ide/src/trace/bean/PerfBottomUpStruct.ts +++ b/ide/src/trace/bean/PerfBottomUpStruct.ts @@ -26,9 +26,8 @@ export class PerfBottomUpStruct { frameChildren?: Array; isSearch: boolean = false; isSelected: boolean = false; - constructor( - symbolName: string, - ) { + tsArray: Array = []; + constructor(symbolName: string) { this.symbolName = symbolName; this.children = []; } diff --git a/ide/src/trace/bean/PerfProfile.ts b/ide/src/trace/bean/PerfProfile.ts index c2482bfb19c3f4ccd4b5998d2f60b8dda92291ee..2f9dcbedb188c3c577706fd7144d10d459f1a1f3 100644 --- a/ide/src/trace/bean/PerfProfile.ts +++ b/ide/src/trace/bean/PerfProfile.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { ChartStruct } from '../../trace/bean/FrameChartStruct.js'; +import { ChartStruct } from "../bean/FrameChartStruct.js"; export class PerfFile { path: string = ''; diff --git a/ide/src/trace/bean/SearchFuncBean.ts b/ide/src/trace/bean/SearchFuncBean.ts index 38c69f8b9913733d54177b17423b621e6dffe8d2..3419300477407d64c40c60638b71b66599eb0138 100644 --- a/ide/src/trace/bean/SearchFuncBean.ts +++ b/ide/src/trace/bean/SearchFuncBean.ts @@ -13,9 +13,6 @@ * limitations under the License. */ -// @ts-ignore -import exp from 'constants'; - export class SearchFuncBean { depth: number | undefined; // 0 dur: number | undefined; // 570000 @@ -43,4 +40,4 @@ export class SearchSdkBean { name: string | undefined; rowType: string | undefined | null; rowParentId: string | undefined | null; -} +} \ No newline at end of file diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index a69490044417ab359a9ad37a77b9dbc264b32b15..665a0b272013300af42761ba82cb300523e8aa0e 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -96,6 +96,9 @@ import { FileInfo } from '../../js-heap/model/UiStruct.js'; import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot.js'; import { setSelectState, intersectData } from './Utils.js'; import { LogStruct } from '../database/ui-worker/ProcedureWorkerLog.js'; +import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample.js'; +import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample.js'; +import { LitSearch } from './trace/search/Search.js'; function dpr() { return window.devicePixelRatio || 1; @@ -165,7 +168,7 @@ export class SpSystemTrace extends BaseElement { slicestime: SlicesTime | undefined | null = null; public timerShaftEL: TimerShaftElement | null | undefined; private traceSheetEL: TraceSheet | undefined | null; - private rangeSelect!: RangeSelect; + public rangeSelect!: RangeSelect; chartManager: SpChartManager | undefined | null; private loadTraceCompleted: boolean = false; private rangeTraceRow: Array> | undefined = []; @@ -180,6 +183,8 @@ export class SpSystemTrace extends BaseElement { private isSelectClick: boolean = false; private selectionParam: SelectionParam | undefined; private snapshotFiles: FileInfo | null | undefined; + private tabCpuFreq: TabPaneFrequencySample | undefined | null; + private tabCpuState: TabPaneCounterSample | undefined | null; set snapshotFile(data: FileInfo) { this.snapshotFiles = data; @@ -248,6 +253,8 @@ export class SpSystemTrace extends BaseElement { this.canvasFavoritePanel = this.shadowRoot?.querySelector('.panel-canvas-favorite'); this.timerShaftEL = this.shadowRoot?.querySelector('.timer-shaft'); this.favoriteRowsEL = this.shadowRoot?.querySelector('.favorite-rows'); + this.tabCpuFreq = this.traceSheetEL?.shadowRoot?.querySelector('tabpane-frequency-sample'); + this.tabCpuState = this.traceSheetEL?.shadowRoot?.querySelector('tabpane-counter-sample'); this.rangeSelect = new RangeSelect(this); rightButton?.addEventListener('click', (event: any) => { if (SpSystemTrace.btnTimer) { @@ -334,8 +341,27 @@ export class SpSystemTrace extends BaseElement { requestAnimationFrame(() => this.refreshCanvas(true)); }); document?.addEventListener('triangle-flag', (event: any) => { - let temporaryTime = this.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); - if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); + const time = event.detail.time; + const type = event.detail.type; + if (time.length > 1) { + return; + } + if (time === '' && type === 'square') { + let temporaryTime = this.timerShaftEL?.drawTriangle(time, type); + if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); + } + this.clearTriangle(this.timerShaftEL!.sportRuler!.flagList); + // 框选的宽度 + let rangeSelectWidth = TraceRow.rangeSelectObject!.endX! - TraceRow.rangeSelectObject!.startX!; + // 平均一个旗子占的宽度,一个三角旗子大概18px,部分重合也可以看清,所以只要大于15暂时就画旗子 + if (rangeSelectWidth / time.length > 15) { + for (const item of time) { + this.timerShaftEL?.drawTriangle(item, type); + } + } else { + this.timerShaftEL!.sportRuler!.time = time; + this.timerShaftEL!.sportRuler?.draw(); + } }); document?.addEventListener('flag-change', (event: any) => { this.timerShaftEL?.modifyFlagList(event.detail); @@ -660,8 +686,10 @@ 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) && filterFunc.funName!.indexOf('H:Task ') >= 0; + Math.max(filterFunc.startTs! + filterFunc.dur!, rangeData!.endNS || 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!); return isIntersect(taskData, TraceRow.rangeSelectObject!); @@ -994,7 +1022,8 @@ export class SpSystemTrace extends BaseElement { ).length > 0; } 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.max(filterJank.ts! + filterJank.dur!, rangeData!.endNS || 0) - + Math.min(filterJank.ts!, rangeData!.startNS || 0) < filterJank.dur! + (rangeData!.endNS || 0) - (rangeData!.startNS || 0); if (it.name == 'Actual Timeline') { selection.jankFramesData = []; @@ -1028,11 +1057,14 @@ export class SpSystemTrace extends BaseElement { } // 个别文件的sample的最大timestamp小于时间的框选结束时间,不能给maxNodeId赋值 // 所以加上此条件:sample.timestamp === it.dataList[it.dataList.length -1].timestamp - if (sample.timestamp * 1000 >= endNS! || sample.timestamp === it.dataList[it.dataList.length -1].timestamp) { - if (maxNodeId === undefined) { - maxNodeId = sample.lastAssignedId; - } + if ( + sample.timestamp * 1000 >= endNS! || + sample.timestamp === it.dataList[it.dataList.length - 1].timestamp + ) { + if (maxNodeId === undefined) { + maxNodeId = sample.lastAssignedId; } + } } // If the start time range of the selected box is greater than the end time of the sampled data @@ -1118,8 +1150,15 @@ export class SpSystemTrace extends BaseElement { (logStruct.startTs ?? 0) >= TraceRow.rangeSelectObject!.startNS! && (logStruct.startTs ?? 0) <= TraceRow.rangeSelectObject!.endNS! ); - selection.hiLogs.push(...systemLogs); - selection.hiLogSummary.push(...systemLogs); + let batchSize = 10000; + let totalLogs = systemLogs.length; + let currentIndex = 0; + while (currentIndex < totalLogs) { + let batch = systemLogs.slice(currentIndex, currentIndex + batchSize); + selection.hiLogSummary.push(...batch); + selection.hiLogs.push(...batch); + currentIndex += batchSize; + } } if (this.rangeTraceRow!.length !== rows.length) { let event = this.createPointEvent(it); @@ -1262,6 +1301,16 @@ export class SpSystemTrace extends BaseElement { } }); } + // 清除上一次点击调用栈产生的三角旗子 + private clearTriangle(flagList: Array) { + this.timerShaftEL!.sportRuler!.time = []; + for (var i = 0; i < flagList.length; i++) { + if (flagList[i].type === 'triangle') { + flagList.splice(i, 1); + i--; + } + } + } pushPidToSelection(selection: SelectionParam, id: string) { let pid = parseInt(id); @@ -1652,23 +1701,23 @@ export class SpSystemTrace extends BaseElement { let y = ev.offsetY; this.timerShaftEL?.documentOnMouseDown(ev); if ( - this.timerShaftEL!.sportRuler!.frame.contains(x, y) && - x > (TraceRow.rangeSelectObject?.startX || 0) && - x < (TraceRow.rangeSelectObject?.endX || 0) + !( + this.timerShaftEL!.sportRuler!.frame.contains(x, y) && + x > (TraceRow.rangeSelectObject?.startX || 0) && + x < (TraceRow.rangeSelectObject?.endX || 0) + ) ) { - let findSlicestime = this.timerShaftEL!.sportRuler?.findSlicesTime(x, y); // 查找帽子 - if (!findSlicestime) { - // 如果没有找到帽子,则绘制一个三角形的旗子 - let time = Math.round( - (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / this.timerShaftEL!.canvas!.offsetWidth + - TraceRow.range?.startNS! - ); - this.timerShaftEL!.sportRuler!.drawTriangle(time, 'triangle'); - } - } else { this.rangeSelect.mouseDown(ev); this.rangeSelect.drag = true; } + // 如果鼠标摁下事件发生在traceRow范围或时间轴(sportRuler除外)范围内,清除上次点击调用栈产生的所有的三角旗子 + // ev.offsetY:鼠标在SpSystemTrace元素的y轴偏移量 + if ( + ev.offsetY > this.timerShaftEL!.clientHeight || + ev.offsetY < this.timerShaftEL!.clientHeight - this.timerShaftEL!.sportRuler!.frame.height + ) { + this.clearTriangle(this.timerShaftEL!.sportRuler!.flagList); + } } else { this.rangeSelect.drag = false; } @@ -1696,6 +1745,25 @@ export class SpSystemTrace extends BaseElement { this.rangeSelect.isMouseDown = false; if ((window as any).isSheetMove) return; if (this.isMouseInSheet(ev)) return; + if (ev.offsetX > this.timerShaftEL!.canvas!.offsetLeft) { + let x = ev.offsetX - this.timerShaftEL!.canvas!.offsetLeft; + let y = ev.offsetY; + if ( + this.timerShaftEL!.sportRuler!.frame.contains(x, y) && + x > (TraceRow.rangeSelectObject?.startX || 0) && + x < (TraceRow.rangeSelectObject?.endX || 0) + ) { + let findSlicestime = this.timerShaftEL!.sportRuler?.findSlicesTime(x, y); // 查找帽子 + if (!findSlicestime) { + // 如果没有找到帽子,则绘制一个三角形的旗子 + let time = Math.round( + (x * (TraceRow.range?.endNS! - TraceRow.range?.startNS!)) / this.timerShaftEL!.canvas!.offsetWidth + + TraceRow.range?.startNS! + ); + this.timerShaftEL!.sportRuler!.drawTriangle(time, 'triangle'); + } + } + } this.rangeSelect.mouseUp(ev); this.timerShaftEL?.documentOnMouseUp(ev); ev.preventDefault(); @@ -1985,8 +2053,21 @@ export class SpSystemTrace extends BaseElement { return; } this.rangeSelect.mouseMove(rows, ev); + if (this.rangeSelect.rangeTraceRow!.length > 0) { + this.tabCpuFreq!.rangeTraceRow = this.rangeSelect.rangeTraceRow; + this.tabCpuState!.rangeTraceRow = this.rangeSelect.rangeTraceRow; + } if (this.rangeSelect.isMouseDown) { this.refreshCanvas(true); + if (TraceRow.rangeSelectObject) { + let search = document + .querySelector('body > sp-application')! + .shadowRoot!.querySelector('#lit-search'); + if (search && search.searchValue !== '') { + search.clear(); + search.valueChangeHandler?.(''); + } + } } else { if (!this.rowsPaneEL!.containPoint(ev, { left: 248 })) { this.tipEL!.style.display = 'none'; @@ -2367,7 +2448,7 @@ export class SpSystemTrace extends BaseElement { )[0]; let task = () => { if (threadRow) { - let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime); + let findEntry = threadRow!.dataList!.find((dat) => dat.startTime === d.startTime && dat.dur! > 0); if ( findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || findEntry!.startTime! > TraceRow.range!.endNS diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index 016d6d86bfdc888df627a663e458d1c149460db9..051830b7cdf82e25336039a85e53b839662df8c8 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -477,6 +477,7 @@ export class FrameChart extends BaseElement { return node.searchDur > 0; } } + /** * 绘制每个函数色块 * @param node 函数块 @@ -747,8 +748,12 @@ export class FrameChart extends BaseElement { this.rootNode.frame!.width = this.rect.width = this.canvas.clientWidth; // 重新绘图 this.clickRedraw(); + document.dispatchEvent( + new CustomEvent('triangle-flag', { + detail: { time: ChartStruct.selectFuncStruct.tsArray, type: 'triangle' }, + }) + ); } - } else if (e.button === 2) { } this.hideTip(); } diff --git a/ide/src/trace/component/setting/SpWebHdcShell.ts b/ide/src/trace/component/setting/SpWebHdcShell.ts index ae7b55e732b6be6f1c60a70b98cacc558a09ba6e..2d659367f509eab6328e983a94eb31b0822eb980 100644 --- a/ide/src/trace/component/setting/SpWebHdcShell.ts +++ b/ide/src/trace/component/setting/SpWebHdcShell.ts @@ -32,6 +32,10 @@ export class SpWebHdcShell extends BaseElement { private skipFlag: number[] = [7]; private clearFlag: number[] = [27, 91, 50, 74, 27, 91, 72]; private CRLFFlag: number[] = [13, 13, 10]; + private startRealTimeFlag: number[] = [27, 91, 115]; + private endRealTimeFlag: number[] = [27, 91, 117]; + private clearRealTimeFlag: number[] = [27, 91, 72, 27, 91, 74]; + private ctrlCFlag: number[] = [13, 10, 35, 32]; private points: Point | undefined; private forwardFlag: boolean = false; private cursorIndex: number = 3; @@ -44,6 +48,8 @@ export class SpWebHdcShell extends BaseElement { private static MULTI_LINE_FLAG = '<\b'; private static LINE_BREAK_LENGTH = 2; private static LEFT_OFFSET = 48; + private realTimeResult: string | null | undefined = ''; + private startRealTime: boolean = false; public initElements(): void { this.shellCanvas = this.shadowRoot!.querySelector('#shell_cmd'); @@ -220,7 +226,7 @@ export class SpWebHdcShell extends BaseElement { } } } - this.points = { startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY }; + this.points = {startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY}; } reverseSelected(startX: number, startY: number, endX: number, endY: number): void { @@ -254,7 +260,7 @@ export class SpWebHdcShell extends BaseElement { } } } - this.points = { startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY }; + this.points = {startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY}; } private singleLineToMultiLine(shellStr: string, foundationWidth: number, maxWidth: number): string[] { @@ -273,6 +279,7 @@ export class SpWebHdcShell extends BaseElement { } private finalArr: Array = []; + refreshShellPage(scroller: boolean): void { try { if (this.resultStr.length === 0 && this.cursorRow.length === 0) { @@ -282,6 +289,9 @@ export class SpWebHdcShell extends BaseElement { this.shellCanvasCtx!.fillStyle = '#000'; this.shellCanvasCtx!.fillRect(0, 0, this.shellCanvas!.width, this.shellCanvas!.height); let resultStrArr = this.resultStr.split('\r\n'); + if (this.realTimeResult !== '') { + resultStrArr = (this.resultStr + this.realTimeResult).split('\r\n'); + } this.finalArr = []; if (this.shellCanvas!.width > 0) { let maxWidth = this.shellCanvas!.width; @@ -439,25 +449,81 @@ export class SpWebHdcShell extends BaseElement { this.resultStr += result.getDataToString(); } } + this.realTimeResult = ''; + } else if (this.isStartWidthArrayBuffer(arrayA, this.startRealTimeFlag)) { + let lastIndex = this.getLastRestorationIndex(arrayA, this.endRealTimeFlag); + this.realTimeResult = this.removeTextAndColorSequenceStr(this.textDecoder.decode(arrayA.slice(lastIndex, arrayA.length))); + this.startRealTime = true; + } else if (this.isStartWidthArrayBuffer(arrayA, this.clearRealTimeFlag)) { + this.realTimeResult = this.removeTextAndColorSequenceStr(this.textDecoder.decode(arrayA.slice(6, arrayA.length))); + this.startRealTime = true; } else { - if (result.getDataToString().includes(SpWebHdcShell.MULTI_LINE_FLAG)) { - // 获取所有内容,不包括最后一行数据 - this.resultStr = this.resultStr.substring( - 0, - this.resultStr.lastIndexOf('\r\n') + SpWebHdcShell.LINE_BREAK_LENGTH - ); - // 多行情况不能直接拼接返回数据 - this.resultStr += result.getDataToString().substring(result.getDataToString().indexOf('\r')); + if (this.isStartWidthArrayBuffer(arrayA, this.ctrlCFlag)) { + this.resultStr += this.realTimeResult; + this.startRealTime = false; + } + if (this.startRealTime) { + if (result.getDataToString().includes(SpWebHdcShell.MULTI_LINE_FLAG)) { + this.realTimeResult += result.getDataToString().substring(result.getDataToString().indexOf('\r')); + } else { + this.realTimeResult += result.getDataToString(); + } + this.realTimeResult = this.removeTextAndColorSequenceStr(this.realTimeResult!); } else { - this.resultStr += result.getDataToString(); + this.realTimeResult = ''; + if (result.getDataToString().includes(SpWebHdcShell.MULTI_LINE_FLAG)) { + // 获取所有内容,不包括最后一行数据 + this.resultStr = this.resultStr.substring( + 0, + this.resultStr.lastIndexOf('\r\n') + SpWebHdcShell.LINE_BREAK_LENGTH + ); + // 多行情况不能直接拼接返回数据 + this.resultStr += result.getDataToString().substring(result.getDataToString().indexOf('\r')); + } else { + this.resultStr += result.getDataToString(); + } } } } + this.resultStr = this.removeTextAndColorSequenceStr(this.resultStr); this.refreshCurrentRow(); this.refreshShellPage(true); } } + private removeTextAndColorSequenceStr(currentStr: string): string { + return currentStr.replace(new RegExp(/\x1B\[[0-9;]*[a-zA-Z]/g), ''); + } + + private isStartWidthArrayBuffer(sourceArray: Uint8Array, compareArray: number[]): boolean { + for (let index = 0; index < compareArray.length; index++) { + if (sourceArray[index] !== compareArray[index]) { + return false; + } + } + return true; + } + + private getLastRestorationIndex(sourceArray: Uint8Array, compareArray: number[]): number { + let lastIndex = -1; + for (let index = sourceArray.length - 1; index >= 0; index--) { + if (sourceArray[index] === compareArray[0]) { + let isLast = true; + for (let j = 1; j < compareArray.length; j++) { + if (sourceArray[index + j] !== compareArray[j]) { + isLast = false; + break; + } + } + if (isLast) { + lastIndex = index; + break; + } + } + } + return lastIndex + compareArray.length; + } + private shellCanvasAddMouseListener(): void { let startX: number; let startY: number; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index cad5a4b499eb8f46976c51eb4e7fc8173fe11272..9314208221a6780364b8822f3f41cf4d8b9dd4ee 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -78,6 +78,7 @@ import { TabPaneJsCpuStatistics } from '../sheet/ark-ts/TabPaneJsCpuStatistics.j import { TabPaneGpuClickSelectComparison } from '../sheet/gpu/TabPaneGpuClickSelectComparison.js'; import { Utils } from './Utils.js'; import { TabPaneHiLogs } from '../sheet/hilog/TabPaneHiLogs.js'; +import { TabPaneHiLogSummary } from '../sheet/hilog/TabPaneHiLogSummary.js'; @element('trace-sheet') export class TraceSheet extends BaseElement { @@ -601,6 +602,15 @@ export class TraceSheet extends BaseElement { tblHiLog.initTabSheetEl(tblHiLog.parentElement!, this); } } + let tblSummaryPanel = this.shadowRoot?.querySelector('lit-tabpane[id=\'box-hilogs-summary\']'); + if (tblSummaryPanel) { + let tblSummary = tblSummaryPanel.querySelector('tab-hi-log-summary'); + if (tblSummary) { + tblSummary.parentElement!.style.overflow = 'hidden'; + tblSummary.style.overflow = 'hidden'; + tblSummary.initTabSheetEl(tblSummary.parentElement!); + } + } }; rangeSelect(selection: SelectionParam, restore = false): boolean { diff --git a/ide/src/trace/component/trace/sheet/SheetUtils.ts b/ide/src/trace/component/trace/sheet/SheetUtils.ts index 7d7dcc6800ef69d698e3f8ba93ab048d2f8442cd..243bc7e19fc09f761492427cfaa1736f890088d0 100644 --- a/ide/src/trace/component/trace/sheet/SheetUtils.ts +++ b/ide/src/trace/component/trace/sheet/SheetUtils.ts @@ -102,3 +102,66 @@ export class CompareStruct { return new CompareStruct(this.key, value); } } + +export class ParseExpression { + private expression: string; //输入的表达式 + private libTreeMap: Map = new Map(); + constructor(expression: string) { + this.expression = expression.trim(); + } + + /** + * 解析用户输入的表达式 + * @returns string:sql/ null: 非法表达式 + */ + public parse(): Map | null { + // 表达式必须以@开头 + if (!this.expression.startsWith('@')) { + return null; + } + + const expressions: string[] = []; + // 包含- 表示可能有两组表达式 + if (this.expression.includes('-')) { + const multiExpression = this.expression.split('-'); + if (multiExpression.length === 0 || multiExpression.length > 2) { + return null; + } + expressions.push(...multiExpression); + } else { + expressions.push(this.expression); + } + let include = true; + for (let expression of expressions) { + this.paseSingleExpression(expression, include); + include = false; + } + return this.libTreeMap; + } + + private paseSingleExpression(expression: string, includes: boolean): void { + const regex = /\((.*?)\)/; // 匹配括号内的内容 + const match = expression.match(regex); + if (match && match.length > 1) { + expression = match[1]; + + const libs = expression.split(','); // 逗号拆分lib + for (let lib of libs) { + lib = lib.trim(); + const items = lib.split(' '); // 空格拆分函数 + if (items.length > 0) { + const path = items[0]; + items.splice(0, 1); + if (this.libTreeMap.has(path)) { + continue; + } + if (includes) { + this.libTreeMap.set(`+${path}`, items); + } else { + this.libTreeMap.set(`-${path}`, items); + } + } + } + } + } +} diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 68abb32413835d1c440c069149961fb8a64c16a5..436c92a158f00ea80ae60eadc9b523b0f67d60dd 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -44,7 +44,6 @@ import { ColorUtils } from '../base/ColorUtils.js'; import { IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq.js'; import { BinderArgBean } from '../../../bean/BinderArgBean.js'; import { JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank.js'; -import { LitIcon } from '../../../../base-ui/icon/LitIcon.js'; import { Utils } from '../base/Utils.js'; import { SpSystemTrace } from '../../SpSystemTrace.js'; import { AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup.js'; @@ -95,6 +94,7 @@ export function getTimeString(ns: number): string { @element('tabpane-current-selection') export class TabPaneCurrentSelection extends BaseElement { weakUpBean: WakeupBean | null | undefined; + selectWakeupBean: any; private currentSelectionTbl: LitTable | null | undefined; private tableObserver: MutationObserver | undefined; private wakeupListTbl: LitTable | undefined | null; @@ -194,6 +194,15 @@ export class TabPaneCurrentSelection extends BaseElement { }); let canvas = this.initCanvas(); if (bean !== null) { + this.selectWakeupBean = { + process: `${this.transferString(data.processName || 'Process')}(${data.processId})`, + thread: `${this.transferString(data.name || 'Thread')}(${data.tid})`, + cpu: data.cpu, + dur: data.dur, + priority: data.priority, + isSelected: false + }; + this.weakUpBean = bean; if (rightArea !== null && rightArea) { rightArea.style.visibility = 'visible'; @@ -1253,6 +1262,9 @@ export class TabPaneCurrentSelection extends BaseElement { maxPriority = Math.max(maxPriority, wake.priority); return wake; }); + if (this.selectWakeupBean) { + resource.unshift(this.selectWakeupBean); + } resource.forEach(it => { it.isSelected = it.priority === maxPriority || it.dur === maxDuration; }); @@ -1358,7 +1370,7 @@ export class TabPaneCurrentSelection extends BaseElement { - + diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts index 8d0d4ccf23bc9685733f44d753aabed3b6ecc323..82e561643104024eee2b776fe65c285034d173ea 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts @@ -20,6 +20,12 @@ import { getTabPaneCounterSampleData } from '../../../../database/SqlLite.js'; import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar.js'; import { Utils } from '../../base/Utils.js'; import { resizeObserver } from '../SheetUtils.js'; +import { SpSystemTrace } from '../../../SpSystemTrace.js'; +import { dataFilterHandler, drawLines } from '../../../../database/ui-worker/ProcedureWorkerCommon.js'; +import { TraceRow } from '../../base/TraceRow.js'; +import { CpuFreqStruct } from '../../../../database/ui-worker/ProcedureWorkerFreq.js'; +import { CpuState } from '../../../../database/logic-worker/ProcedureLogicWorkerCpuState.js'; +import { CpuStateStruct } from '../../../../database/ui-worker/ProcedureWorkerCpuState.js'; @element('tabpane-counter-sample') export class TabPaneCounterSample extends BaseElement { @@ -33,6 +39,8 @@ export class TabPaneCounterSample extends BaseElement { private counterSampleSource: any[] = []; private counterSortKey: string = 'counter'; private counterSortType: number = 0; + private systemTrace: SpSystemTrace | undefined | null; + private _rangeRow: Array> | undefined | null; set data(counterSampleValue: SelectionParam | any) { if (counterSampleValue == this.selectionParam) { @@ -47,10 +55,17 @@ export class TabPaneCounterSample extends BaseElement { this.queryDataByDB(counterSampleValue); } + set rangeTraceRow(rangeRow: Array> | undefined) { + this._rangeRow = rangeRow; + } + initElements(): void { this.sampleProgressEL = this.shadowRoot!.querySelector('.progressCounter'); this.counterLoadingPage = this.shadowRoot!.querySelector('.loadingCounter'); this.counterSampleTbl = this.shadowRoot!.querySelector('#tb-counter-sample'); + this.systemTrace = document + .querySelector('body > sp-application')! + .shadowRoot!.querySelector('#sp-system-trace'); this.counterSampleTbl!.addEventListener('column-click', (evt) => { // @ts-ignore this.counterSortKey = evt.detail.key; @@ -59,6 +74,52 @@ export class TabPaneCounterSample extends BaseElement { // @ts-ignore this.sortTable(evt.detail.key, evt.detail.sort); }); + + this.counterSampleTbl!.addEventListener('row-click', (evt) => { + // @ts-ignore + let data = evt.detail.data; + let path = new Path2D(); + if (this._rangeRow && this._rangeRow!.length > 0) { + let rangeTraceRow = this._rangeRow!.filter(function (item) { + return item.name.includes('State'); + }); + let cpuStateFilter = []; + for (let row of rangeTraceRow!) { + let context = row.collect ? this.systemTrace!.canvasFavoritePanelCtx! : this.systemTrace!.canvasPanelCtx!; + cpuStateFilter.push(...row.dataListCache); + row.canvasSave(context); + context.clearRect(row.frame.x, row.frame.y, row.frame.width, row.frame.height); + drawLines(context!, TraceRow.range?.xs || [], row.frame.height, this.systemTrace!.timerShaftEL!.lineColor()); + if (row.name.includes('State') && parseInt(row.name.replace(/[^\d]/g, ' ')) === data.cpu) { + CpuFreqStruct.hoverCpuFreqStruct = undefined; + for (let i = 0; i < cpuStateFilter!.length; i++) { + if ( + cpuStateFilter[i].value === data.value && + cpuStateFilter[i].cpu === data.cpu && + Math.max(TraceRow.rangeSelectObject?.startNS!, cpuStateFilter[i].startTs!) < + Math.min(TraceRow.rangeSelectObject?.endNS!, cpuStateFilter[i].startTs! + cpuStateFilter[i].dur!) + ) { + CpuStateStruct.hoverStateStruct = cpuStateFilter[i]; + } + if (cpuStateFilter[i].cpu === data.cpu) { + CpuStateStruct.draw(context, path, cpuStateFilter[i]); + } + } + } else { + for (let i = 0; i < cpuStateFilter!.length; i++) { + if ( + row.name.includes('State') && + cpuStateFilter[i].cpu !== data.cpu && + cpuStateFilter[i].cpu === parseInt(row.name.replace(/[^\d]/g, ' ')) + ) { + CpuStateStruct.draw(context, path, cpuStateFilter[i]); + } + } + } + row.canvasRestore(context); + } + } + }); } connectedCallback() { diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts index 71cf7567f423c49a57be4e4ccfb735f1bcece8eb..ddf5f2212f39cdd6fb6a5bb54cf155d95f9d4080 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts @@ -21,6 +21,15 @@ import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressB import { Utils } from '../../base/Utils.js'; import { ColorUtils } from '../../base/ColorUtils.js'; import { resizeObserver } from '../SheetUtils.js'; +import { CpuFreqStruct } from '../../../../database/ui-worker/ProcedureWorkerFreq.js'; +import { SpSystemTrace } from '../../../SpSystemTrace.js'; +import { TraceRow } from '../../base/TraceRow.js'; +import { + dataFilterHandler, + drawLines, + isFrameContainPoint, +} from '../../../../database/ui-worker/ProcedureWorkerCommon.js'; +import { RangeSelect } from '../../base/RangeSelect.js'; @element('tabpane-frequency-sample') export class TabPaneFrequencySample extends BaseElement { @@ -34,6 +43,8 @@ export class TabPaneFrequencySample extends BaseElement { private frequencySampleSource: any[] = []; private frequencySampleSortKey: string = 'counter'; private frequencySampleSortType: number = 0; + private systemTrace: SpSystemTrace | undefined | null; + private _rangeRow: Array> | undefined | null; set data(frequencySampleValue: SelectionParam | any) { if (frequencySampleValue == this.selectionParam) { @@ -48,10 +59,17 @@ export class TabPaneFrequencySample extends BaseElement { this.queryDataByDB(frequencySampleValue); } + set rangeTraceRow(rangeRow: Array> | undefined) { + this._rangeRow = rangeRow; + } + initElements(): void { this.frequencyProgressEL = this.shadowRoot!.querySelector('.progressFre'); this.frequencyLoadingPage = this.shadowRoot!.querySelector('.loadingFre'); this.frequencySampleTbl = this.shadowRoot!.querySelector('#tb-states'); + this.systemTrace = document + .querySelector('body > sp-application')! + .shadowRoot!.querySelector('#sp-system-trace'); this.frequencySampleTbl!.addEventListener('column-click', (evt) => { // @ts-ignore this.frequencySampleSortKey = evt.detail.key; @@ -60,6 +78,59 @@ export class TabPaneFrequencySample extends BaseElement { // @ts-ignore this.sortTable(evt.detail.key, evt.detail.sort); }); + this.frequencySampleTbl!.addEventListener('row-click', (evt) => { + // @ts-ignore + let data = evt.detail.data; + if (this._rangeRow && this._rangeRow!.length > 0) { + let rangeTraceRow = this._rangeRow!.filter(function (item) { + return item.name.includes('Frequency'); + }); + let freqFilter = []; + for (let row of rangeTraceRow!) { + let context = row.collect ? this.systemTrace!.canvasFavoritePanelCtx! : this.systemTrace!.canvasPanelCtx!; + freqFilter.push(...row.dataListCache); + row.canvasSave(context); + context.clearRect(row.frame.x, row.frame.y, row.frame.width, row.frame.height); + drawLines(context!, TraceRow.range?.xs || [], row.frame.height, this.systemTrace!.timerShaftEL!.lineColor()); + if (row.name.includes('Frequency') && parseInt(row.name.replace(/[^\d]/g, ' ')) === data.cpu) { + CpuFreqStruct.hoverCpuFreqStruct = undefined; + for (let i = 0; i < freqFilter!.length; i++) { + if ( + freqFilter[i].value === data.value && + freqFilter[i].cpu === data.cpu && + Math.max(TraceRow.rangeSelectObject?.startNS!, freqFilter[i].startNS!) < + Math.min(TraceRow.rangeSelectObject?.endNS!, freqFilter[i].startNS! + freqFilter[i].dur!) + ) { + CpuFreqStruct.hoverCpuFreqStruct = freqFilter[i]; + } + if (freqFilter[i].cpu === data.cpu) { + CpuFreqStruct.draw(context, freqFilter[i]); + } + } + } else { + for (let i = 0; i < freqFilter!.length; i++) { + if ( + row.name.includes('Frequency') && + freqFilter[i].cpu !== data.cpu && + freqFilter[i].cpu === parseInt(row.name.replace(/[^\d]/g, ' ')) + ) { + CpuFreqStruct.draw(context, freqFilter[i]); + } + } + } + let s = CpuFreqStruct.maxFreqName; + let textMetrics = context.measureText(s); + context.globalAlpha = 0.8; + context.fillStyle = '#f0f0f0'; + context.fillRect(0, 5, textMetrics.width + 8, 18); + context.globalAlpha = 1; + context.fillStyle = '#333'; + context.textBaseline = 'middle'; + context.fillText(s, 4, 5 + 9); + row.canvasRestore(context); + } + } + }); } connectedCallback() { @@ -71,7 +142,6 @@ export class TabPaneFrequencySample extends BaseElement { this.frequencyLoadingList.push(1); this.frequencyProgressEL!.loading = true; this.frequencyLoadingPage.style.visibility = 'visible'; - getTabPaneFrequencySampleData( frqSampleParam.leftNs + frqSampleParam.recordStartNs, frqSampleParam.rightNs + frqSampleParam.recordStartNs, diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts index 1bced89a1d40682767a091c65c94a877897b3c3d..e283c52181bfed68dc9d00ad90abd4516d2dd473 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts @@ -61,7 +61,7 @@ export class TabPaneSchedPriority extends BaseElement { }); procedurePool.submitWithName('logic1', 'spt-getCpuPriority', {}, undefined, async (res: Array) => { for (const item of res) { - if (item.cpu && !this.selectionParam?.cpus.includes(item.cpu)) { + if (item.cpu === null || !(sptParam.cpus.includes(item.cpu))) { continue; } if (!(item.endTs < sptParam.leftNs || item.startTs > sptParam.rightNs)) { @@ -70,6 +70,7 @@ export class TabPaneSchedPriority extends BaseElement { if (args) { strArg = args!.split(','); } + const filterList = ['0', '0x0']; const slice = Utils.SCHED_SLICE_MAP.get(`${item.itId}-${item.startTs}`); if (slice) { item.priority = slice!.priority; @@ -78,7 +79,11 @@ export class TabPaneSchedPriority extends BaseElement { item.priorityType = 'RT'; } else if (item.priority >= 89 && item.priority <= 99) { item.priorityType = 'VIP2.0'; - } else if (item.priority >= 100 && strArg.length > 1 && (strArg[1] !== '0' || strArg[2] !== '0')) { + } else if ( + item.priority >= 100 && + strArg.length > 1 && + (!filterList.includes(strArg[1]) || !filterList.includes(strArg[2])) + ) { item.priorityType = 'STATIC_VIP'; } else { item.priorityType = 'CFS'; diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts index 6b9faaf4cf0aed0c8877bc2737279c108cd46bd1..bb6a6c09d4dc367ab537fd3f5475a95a373fa7e6 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts @@ -222,6 +222,11 @@ export class TabPaneCallTree extends BaseElement { this.callTreeTbl!.addEventListener('row-click', (evt: any) => { // @ts-ignore let data = evt.detail.data as MerageBean; + document.dispatchEvent( + new CustomEvent('triangle-flag', { + detail: { time: data.tsArray, type: 'triangle' }, + }) + ); this.setRightTableData(data); data.isSelected = true; this.callTreeSelectedData = data; @@ -452,8 +457,7 @@ export class TabPaneCallTree extends BaseElement { this.isChartShow = true; this.callTreeFilter!.disabledMining = true; showButtonMenu(this.callTreeFilter, this.needShowMenu); - if (!data) - this.frameChart!.data = this.callTreeDataSource; + if (!data) this.frameChart!.data = this.callTreeDataSource; this.frameChart?.calculateChartData(); } else if (data.icon === 'tree') { callTreePageChart?.setAttribute('class', ''); diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts index 0e511cb868891cfd1c8f3d01fbd9aeef26e3a554..b4b4eda9b53423db85ff60151c0a4e4fee05cfe6 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts @@ -172,6 +172,11 @@ export class TabpaneFilesystemCalltree extends BaseElement { this.fsCallTreeTbl!.addEventListener('row-click', (evt: any) => { // @ts-ignore let data = evt.detail.data as FileMerageBean; + document.dispatchEvent( + new CustomEvent('triangle-flag', { + detail: { time: data.tsArray, type: 'triangle' }, + }) + ); this.setRightTableData(data); data.isSelected = true; this.fsCallTreeCurrentSelectedData = data; @@ -441,7 +446,7 @@ export class TabpaneFilesystemCalltree extends BaseElement { this.isChartShow = true; this.fsCallTreeFilter!.disabledMining = true; showButtonMenu(this.fsCallTreeFilter, this.needShowMenu); - if (!data){ + if (!data){ this.frameChart!.data = this.fsCallTreeDataSource; } this.frameChart?.calculateChartData(); diff --git a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts index 4f162b94b2a2832e3b8aaf314a933ac06c86b899..bded913a05639e4fb82dfca85fc9e6384e291741 100644 --- a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts +++ b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts @@ -23,6 +23,7 @@ import { LitTable } from '../../../../../base-ui/table/lit-table.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 expandedNodeList: Set = new Set(); private logLevel: string[] = ['Debug', 'Info', 'Warn', 'Error','Fatal']; @@ -89,7 +90,7 @@ export class TabPaneHiLogSummary extends BaseElement { -
+