diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index f909b021eb39021c63018b15cc7064a1d9ae99c7..f5cbbc3316436fb8153f5e8c14a202782edb66c8 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -23,6 +23,8 @@ import { querySceneSearchFunc, querySearchFunc, threadPool, + querySfVSyncData, + querySingleVSyncData } from '../database/SqlLite.js'; import { RangeSelectStruct, TraceRow } from './trace/base/TraceRow.js'; import { TimerShaftElement } from './trace/TimerShaftElement.js'; @@ -49,6 +51,7 @@ import { ns2xByTimeShaft, PairPoint, Rect, + drawVsync } from '../database/ui-worker/ProcedureWorkerCommon.js'; import { SpChartManager } from './chart/SpChartManager.js'; import { CpuStruct, WakeupBean } from '../database/ui-worker/ProcedureWorkerCPU.js'; @@ -102,6 +105,7 @@ 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 { SpKeyboard } from '../component/SpKeyboard.js' import { HiPerfCallChartStruct } from '../database/ui-worker/ProcedureWorkerHiPerfCallChart.js'; import { type HiSysEventStruct } from '../database/ui-worker/ProcedureWorkerHiSysEvent.js'; import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon.js'; @@ -198,6 +202,11 @@ export class SpSystemTrace extends BaseElement { private expandRowList: Array> = []; private _slicesList: Array = []; private _flagList: Array = []; + private _frameList: Array = []; + private _isVsync: boolean = false; + private queryFunData: Array = []; + private querydbData: Array = []; + private singleVSyncData: Array = []; set snapshotFile(data: FileInfo) { this.snapshotFiles = data; @@ -210,6 +219,51 @@ export class SpSystemTrace extends BaseElement { set flagList(list: Array) { this._flagList = list; } + async makeVsyncLine() { + if (this._isVsync) { + const range = this.timerShaftEL?.rangeRuler?.range; + const totalTime = range!.endNS - range!.startNS; + const totalHeight = this.canvasPanel!.clientHeight; + const drawData = []; + if (this.singleVSyncData.length === 0) { + if (this.querydbData.length === 0) { + this.querydbData = await querySfVSyncData(); + } + } else { + if (this.queryFunData.length === 0) { + this.queryFunData = await querySingleVSyncData(); + } + for (let i = 0; i < this.queryFunData.length; i++) { + this.queryFunData[i].color = '#808080'; + } + } + let allShowData = this.querydbData.length > 0 ? this.querydbData.filter((data: any) => data.startTime > range!.startNS && data.startTime < range!.endNS) : this.queryFunData.filter((data: any) => data.startTime > range!.startNS && data.startTime < range!.endNS); + for (let i = 0; i < allShowData.length; i++) { + let data = allShowData[i]; + const x1 = ns2x(data.startTime, range!.startNS, range!.endNS, totalTime, this.timerShaftEL!.sportRuler!.frame); + let x0 = 0; + if (i === allShowData.length - 1) { + x0 = ns2x(range!.endNS, range!.startNS, range!.endNS, totalTime, this.timerShaftEL!.sportRuler!.frame); + } else { + x0 = ns2x(allShowData[i + 1].startTime, range!.startNS, range!.endNS, totalTime, this.timerShaftEL!.sportRuler!.frame); + } + if ((data.value && data.value === 1) || data.color) { + const x = x1; + const y = 0; + const width = x0 - x1; + const height = totalHeight; + data.frame = new Rect(x, y, width, height); + } + if (data.color && i % 2) { + data.color = '#ffffff' + } + drawData.push(data); + } + this.refreshCanvas(true, '', drawData); + } else { + this.refreshCanvas(true, '', []) + } + } addPointPair(startPoint: PairPoint, endPoint: PairPoint) { if (startPoint.rowEL.collect) { @@ -742,8 +796,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!); @@ -1128,7 +1182,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 = []; @@ -1211,7 +1265,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!); @@ -1391,7 +1445,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); }); @@ -1650,10 +1704,14 @@ export class SpSystemTrace extends BaseElement { } // refresh main canvas and favorite canvas - refreshCanvas(cache: boolean, from?: string) { + refreshCanvas(cache: boolean, from?: string, frameList?: any[] | undefined) { if (this.visibleRows.length == 0) { return; } + if (frameList) { + this._frameList = []; + this._frameList.push(...frameList); + } //clear main canvas this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight); this.favoriteChartListEL?.clearRect(); @@ -1738,7 +1796,29 @@ export class SpSystemTrace extends BaseElement { this.timerShaftEL! ); this.favoriteChartListEL?.drawLogsLineSegment(this.traceSheetEL!.systemLogFlag, this.timerShaftEL!); + //---------------------------新增代码开始-------------------------- + if (this._frameList.length > 0) { + for (let i = 0; i < this._frameList.length; i++) { + if (this._frameList[i].frame) { + drawVsync( + this.canvasPanelCtx, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + { + x: this._frameList[i].frame!.x!, + y: this._frameList[i].frame!.y!, + width: this._frameList[i].frame!.width!, + height: this.canvasPanel!.clientHeight! + } as Rect, + this._frameList[i]!.color! + ); + } + } + } + + //---------------------------新增代码结束-------------------------- // Draw the connection curve if (this.linkNodes) { drawLinkLines( @@ -1826,6 +1906,11 @@ export class SpSystemTrace extends BaseElement { this.offsetMouse = 0; this.mouseCurrentPosition = 0; this.style.cursor = 'default'; + requestAnimationFrame(() => { + setTimeout(() => { + this.makeVsyncLine(); + }, 100) + }) return; } TraceRow.isUserInteraction = false; @@ -1845,7 +1930,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'); } @@ -1915,6 +2000,11 @@ export class SpSystemTrace extends BaseElement { if (keyPressWASD) { this.keyPressMap.set(keyPress, true); this.hoverFlag = null; + requestAnimationFrame(() => { + setTimeout(() => { + this.makeVsyncLine(); + }, 100) + }) } this.timerShaftEL!.documentOnKeyPress(ev, this.currentSlicesTime); if (keyPress === 'f') { @@ -2022,13 +2112,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(); @@ -2057,8 +2147,22 @@ export class SpSystemTrace extends BaseElement { } if (!this.loadTraceCompleted) return; let keyPress = ev.key.toLocaleLowerCase(); + if (keyPress === 'v') { + this._isVsync = !this._isVsync; + if (this._isVsync) { + this.makeVsyncLine(); + } else { + this.refreshCanvas(true, '', []) + } + + } if (keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd') { this.keyPressMap.set(keyPress, false); + requestAnimationFrame(() => { + setTimeout(() => { + this.makeVsyncLine(); + }, 100) + }) } TraceRow.isUserInteraction = false; this.observerScrollHeightEnable = false; @@ -3640,6 +3744,11 @@ export class SpSystemTrace extends BaseElement { (e) => { if (e.ctrlKey) { if (e.deltaY > 0) { + requestAnimationFrame(() => { + setTimeout(() => { + this.makeVsyncLine(); + }, 100) + }) e.preventDefault(); e.stopPropagation(); let eventS = new KeyboardEvent('keypress', { @@ -3653,6 +3762,11 @@ export class SpSystemTrace extends BaseElement { }, 200); } if (e.deltaY < 0) { + requestAnimationFrame(() => { + setTimeout(() => { + this.makeVsyncLine(); + }, 100) + }) e.preventDefault(); e.stopPropagation(); let eventW = new KeyboardEvent('keypress', { @@ -4279,6 +4393,10 @@ export class SpSystemTrace extends BaseElement { } reset(progress: Function | undefined | null) { + this._frameList = []; + this.queryFunData = []; + this.querydbData = []; + this._isVsync = false; this.visibleRows.length = 0; this.tipEL!.style.display = 'none'; this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight); @@ -4321,6 +4439,9 @@ export class SpSystemTrace extends BaseElement { } init = async (param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) => { + setTimeout(async () => { + this.singleVSyncData = await querySingleVSyncData(); + }, 500) progress('Load database', 6); this.rowsPaneEL!.scroll({ top: 0, diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 67650603a8971af80b5ee5301e6aab118189daa8..3fc33db9d33d90d660f48fb923bd9df95731e14d 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -1825,6 +1825,28 @@ export const queryHiPerfEventListData = (eventTypeId: number): Promise> => +query( + 'querySfVSyncData', + `SELECT ts,value,c.ts-tb.start_ts startTime + FROM + process_measure c, + trace_range tb + WHERE + c.filter_id IN (SELECT process_measure_filter.id AS traceId FROM process_measure_filter JOIN process USING (ipid) WHERE process.name = ${`'` + String.fromCharCode(115,117,114,102,97,99,101,102,108,105,110,103,101,114) + `'`} + AND process_measure_filter.name = ${`'` + String.fromCharCode(86,83,89,78,67,45,97,112,112) + `'`})` +) +export const querySingleVSyncData = ():Promise> => +query( + 'querySingleVSyncData', + `SELECT ts,c.ts-tb.start_ts startTime + FROM + callstack c, + trace_range tb + WHERE + c.id IN (SELECT callstack.id AS trackId FROM callstack JOIN process WHERE process.name = ${`'` + String.fromCharCode(114,101,110,100,101,114,95,115,101,114,118,105,99,101) + `'`} + AND callstack.name like ${`'` + String.fromCharCode(72,58,71,101,110,101,114,97,116,101,86,115,121,110,99,67,111,117,110,116,37) + `'`})` +) export const queryHiPerfEventData = (eventTypeId: number, cpu: number): Promise> => query( 'queryHiPerfEventList', diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts index f4165328d29a7a3c051d8590c4294389ba958b97..80dcd2ed37697971eb13e5aa5a300f1b188d8dcf 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts @@ -1375,6 +1375,24 @@ export function mem( } } +//---------------------------新增代码开始-------------------------- + +export function drawVsync( + vsyncContext: CanvasRenderingContext2D | any, + startNS: number, + endNS: number, + totalNS: number, + frame:Rect, + color:string +){ + vsyncContext.lineWidth = 2; + vsyncContext.fillStyle = color?color:"#808080"; + vsyncContext.globalAlpha = 0.4; + vsyncContext.fillRect(frame.x,frame.y,frame.width,frame.height); +} + +//---------------------------新增代码结束-------------------------- + export function drawWakeUpList( wakeUpListContext: CanvasRenderingContext2D | any, wake: WakeupBean | undefined | null,