diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index 2b6bf58f4c1160141eeeeb1aa3ee45de77c20b87..817044b6ab002b8c9884b8bc59e9743a80f97fe8 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -13,9 +13,6 @@ * limitations under the License. */ -import { CpuFreqLimitsStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; -import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock'; -import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq'; import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc'; import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic'; import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation'; @@ -34,8 +31,10 @@ import { LitTabs } from '../../base-ui/tabs/lit-tabs'; import { TabPaneSummary } from '../component/trace/sheet/ark-ts/TabPaneSummary'; import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler'; import { SampleStruct } from '../database/ui-worker/ProcedureWorkerBpftrace'; +import { GpuCounterStruct } from '../database/ui-worker/ProcedureWorkerGpuCounter'; export class SelectionParam { + traceId: string | undefined | null; recordStartNs: number = 0; leftNs: number = 0; rightNs: number = 0; @@ -69,11 +68,12 @@ export class SelectionParam { string, ((arg: unknown) => Promise> | undefined) | undefined >(); + dmaFenceNameData: Array = [];//新增框选dma_fence数据 irqCallIds: Array = []; softIrqCallIds: Array = []; funTids: Array = []; funAsync: Array<{ name: string; pid: number }> = []; - funCatAsync: Array<{ pid: number;threadName: string }> = []; + funCatAsync: Array<{ pid: number; threadName: string }> = []; nativeMemory: Array = []; nativeMemoryStatistic: Array = []; nativeMemoryAllProcess: Array<{ pid: number; ipid: number }> = []; @@ -112,11 +112,11 @@ export class SelectionParam { gpuTotal: boolean; gpuWindow: boolean; } = { - gl: false, - graph: false, - gpuWindow: false, - gpuTotal: false, - }; + gl: false, + graph: false, + gpuWindow: false, + gpuTotal: false, + }; purgeableTotalAbility: Array = []; purgeableTotalVM: Array = []; purgeablePinAbility: Array = []; @@ -132,6 +132,7 @@ export class SelectionParam { sysAlllogsData: Array = []; hiSysEvents: Array = []; sampleData: Array = []; + gpuCounter: Array = []; // @ts-ignore pushSampleData(it: TraceRow): void { @@ -246,10 +247,20 @@ export class SelectionParam { this.threadIds.push(parseInt(th.rowId!)); } else if (th.rowType === TraceRow.ROW_TYPE_FUNC) { if (th.asyncFuncName) { - this.funAsync.push({ - name: th.asyncFuncName, - pid: th.asyncFuncNamePID || 0, - }); + if (typeof th.asyncFuncName === 'string') { + this.funAsync.push({ + name: th.asyncFuncName, + pid: th.asyncFuncNamePID || 0, + }); + } else { + for (let i = 0; i < th.asyncFuncName.length; i++) { + const el = th.asyncFuncName[i]; + this.funAsync.push({ + name: el, + pid: th.asyncFuncNamePID || 0, + }); + } + } } else if (th.asyncFuncThreadName) { if (typeof th.asyncFuncThreadName === 'string') { this.funCatAsync.push({ @@ -309,10 +320,21 @@ export class SelectionParam { TabPaneTaskFrames.TaskArray = []; sp.pushPidToSelection(this, it.rowParentId!); if (it.asyncFuncName) { - this.funAsync.push({ - name: it.asyncFuncName, - pid: it.asyncFuncNamePID || 0, - }); + if (typeof it.asyncFuncName === 'string') { + this.funAsync.push({ + name: it.asyncFuncName, + pid: it.asyncFuncNamePID || 0, + }); + } else { + //@ts-ignore + for (let i = 0; i < it.asyncFuncName.length; i++) { + const el = it.asyncFuncName[i]; + this.funAsync.push({ + name: el, + pid: it.asyncFuncNamePID || 0, + }); + } + } } else if (it.asyncFuncThreadName) { if (typeof it.asyncFuncThreadName === 'string') { this.funCatAsync.push({ @@ -323,7 +345,7 @@ export class SelectionParam { for (let i = 0; i < it.asyncFuncThreadName.length; i++) { const tn = it.asyncFuncThreadName[i]; this.funCatAsync.push({ - pid: it.asyncFuncNamePID || 0,//@ts-ignore + pid: it.asyncFuncNamePID || 0, //@ts-ignore threadName: tn }); } @@ -334,8 +356,8 @@ export class SelectionParam { let isIntersect = (filterFunc: FuncStruct, rangeData: RangeSelectStruct): boolean => 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; // @ts-ignore let taskData = it.dataListCache.filter((taskData: FuncStruct) => { @@ -465,6 +487,13 @@ export class SelectionParam { // @ts-ignore pushFileSystem(it: TraceRow, sp: SpSystemTrace): void { + if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM_GROUP) { + it.childrenList.forEach((child) => { + child.rangeSelect = true; + child.checkType = '2'; + this.pushFileSystem(child,sp); + }); + } if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) { if (it.rowId === 'FileSystemLogicalWrite') { if (this.fileSystemType.length === 0) { @@ -604,7 +633,7 @@ export class SelectionParam { if (it.rowType === TraceRow.ROW_TYPE_JANK) { let isIntersect = (filterJank: JanksStruct, rangeData: RangeSelectStruct): boolean => 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') { if (it.rowParentId === 'frameTime') { @@ -643,8 +672,7 @@ export class SelectionParam { const [rangeStart, rangeEnd] = [TraceRow.range?.startNS, TraceRow.range?.endNS]; const startNS = TraceRow.rangeSelectObject?.startNS || rangeStart; const endNS = TraceRow.rangeSelectObject?.endNS || rangeEnd; - let minNodeId; - let maxNodeId; + let minNodeId, maxNodeId; if (!it.dataListCache || it.dataListCache.length === 0) { return; } @@ -702,18 +730,20 @@ export class SelectionParam { // @ts-ignore return isIntersect(frameSelectData, TraceRow.rangeSelectObject!); }); - let copyFrameSelectData = JSON.parse(JSON.stringify(frameSelectData)) as Array; + let copyFrameSelectData = JSON.parse(JSON.stringify(frameSelectData)); let frameSelectDataIdArr: Array = []; for (let data of copyFrameSelectData) { frameSelectDataIdArr.push(data.id); } - let jsCpuProfilerData = copyFrameSelectData.filter((item: JsCpuProfilerChartFrame): unknown => { - if (item.depth !== 0) { - return; + let jsCpuProfilerData = copyFrameSelectData.filter((item: unknown) => { + // @ts-ignore + if (item.depth === 0) { + // @ts-ignore + setSelectState(item, frameSelectDataIdArr); + // @ts-ignore + item.isSelect = true; + return item; } - setSelectState(item, frameSelectDataIdArr); - item.isSelect = true; - return item; }); this.jsCpuProfilerData = jsCpuProfilerData; } @@ -903,7 +933,7 @@ export class SelectionParam { if (it.rowType === TraceRow.ROW_TYPE_FRAME_ANIMATION) { let isIntersect = (animationStruct: FrameAnimationStruct, selectStruct: RangeSelectStruct): boolean => 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); // @ts-ignore let frameAnimationList = it.dataListCache.filter((frameAnimationBean: FrameAnimationStruct) => { @@ -976,8 +1006,14 @@ export class SelectionParam { // @ts-ignore pushThread(it: TraceRow, sp: SpSystemTrace): void { + this.perfEventTypeId = TraceRow.ROW_TYPE_HIPERF_THREADTYPE[0] === -2 ? undefined : TraceRow.ROW_TYPE_HIPERF_THREADTYPE[0]; if (it.rowType === TraceRow.ROW_TYPE_THREAD) { sp.pushPidToSelection(this, it.rowParentId!); + if(it.dataListCache && it.dataListCache.length) { + //@ts-ignore + let hiTid = it.dataListCache[0]!.tid; + this.perfThread.push(parseInt(hiTid)) + } this.threadIds.push(parseInt(it.rowId!)); info('load thread traceRow id is : ', it.rowId); } @@ -1091,6 +1127,13 @@ export class SelectionParam { } } + //匹配id + pushDmaFence(it: TraceRow, sp: SpSystemTrace) { + if (it.rowType === TraceRow.ROW_TYPE_DMA_FENCE) { + this.dmaFenceNameData.push(it.rowId!); + } + } + // @ts-ignore pushGpuMemoryVmTracker(it: TraceRow, sp: SpSystemTrace): void { if (it.rowType === TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER) { @@ -1200,6 +1243,7 @@ export class SelectionParam { this.pushVmTracker(it, sp); this.pushVmTrackerShm(it, sp); this.pushClock(it, sp); + this.pushDmaFence(it, sp); this.pushGpuMemoryVmTracker(it, sp); this.pushDmaVmTracker(it, sp); this.pushPugreable(it, sp); @@ -1210,6 +1254,7 @@ export class SelectionParam { } export class BoxJumpParam { + traceId: string | undefined | null; leftNs: number = 0; rightNs: number = 0; cpus: Array = []; @@ -1263,3 +1308,12 @@ export class Fps { timeStr: string = ''; fps: number = 0; } + +export class GpuCounter { + startNS: number = 0; + height: number = 0; + dur: number = 0; + type: string = ''; + startTime: number = 0; + frame: object = {}; +} diff --git a/ide/src/trace/bean/FuncStruct.ts b/ide/src/trace/bean/FuncStruct.ts index e2aaef6ab2350cbb7181e8d72aa004de1e674823..214bf1103971b831674fc33cefdb5982e4c9a3ab 100644 --- a/ide/src/trace/bean/FuncStruct.ts +++ b/ide/src/trace/bean/FuncStruct.ts @@ -37,6 +37,15 @@ export class FuncStruct extends BaseStruct { identify: number | undefined; track_id: number | undefined; nofinish: boolean = false; + // distributed relation chain + ts: number | undefined; + pid: number | undefined; + traceId: string | undefined; + chainId: string | undefined; + chainName: string | undefined; + spanId: string | undefined; + parentSpanId: string | undefined; + chainFlag: string | undefined; static draw(funcBeanStructCanvasCtx: CanvasRenderingContext2D, funcBeanStruct: FuncStruct): void { if (funcBeanStruct.frame) { diff --git a/ide/src/trace/bean/JanksStruct.ts b/ide/src/trace/bean/JanksStruct.ts index 1ba1592cba704bcdadfde0791f44f071c2ccd03d..d2a2f31f926fc6c30df3bca698b27e3606b33f08 100644 --- a/ide/src/trace/bean/JanksStruct.ts +++ b/ide/src/trace/bean/JanksStruct.ts @@ -30,7 +30,7 @@ export class JanksStruct extends BaseStruct { jank_type: string | undefined; type: string | undefined; pid: number | undefined; - frame_type: string | undefined; // app、renderService、FrameTime + frameType: string | undefined; // app、renderService、FrameTime app_dur: number | undefined; src_slice: string | undefined; dst_slice: string | undefined; diff --git a/ide/src/trace/bean/ProcessStruct.ts b/ide/src/trace/bean/ProcessStruct.ts index 77c5b5d0a0d91f0fa02a3bf0fb403b17d9ac9e81..5827545e92b03698ae5a4aaccee22ae3d14ddb96 100644 --- a/ide/src/trace/bean/ProcessStruct.ts +++ b/ide/src/trace/bean/ProcessStruct.ts @@ -15,7 +15,7 @@ import { ColorUtils } from '../component/trace/base/ColorUtils'; import { BaseStruct } from './BaseStruct'; -import { CpuStruct } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; +import { Utils } from '../component/trace/base/Utils'; const padding = 1; @@ -36,7 +36,7 @@ export class ProcessStruct extends BaseStruct { static draw(processBeanCanvasCtx: CanvasRenderingContext2D, processBeanStruct: ProcessStruct): void { if (processBeanStruct.frame) { processBeanCanvasCtx.fillStyle = ColorUtils.colorForTid(processBeanStruct.pid || 0); - let miniHeight = Math.round(processBeanStruct.frame.height / CpuStruct.cpuCount); + let miniHeight = Math.round(processBeanStruct.frame.height / Utils.getInstance().getCpuCount()); processBeanCanvasCtx.fillRect( processBeanStruct.frame.x, processBeanStruct.frame.y + (processBeanStruct.cpu || 0) * miniHeight + padding, diff --git a/ide/src/trace/bean/StateModle.ts b/ide/src/trace/bean/StateModle.ts index 5e0fbce1d0e96d72b33220406b5f26c135278fd7..29428539e22f78f3997015e0142c22a635bcd57e 100644 --- a/ide/src/trace/bean/StateModle.ts +++ b/ide/src/trace/bean/StateModle.ts @@ -31,10 +31,12 @@ export class StateGroup { children?: Array; isSelected?: boolean = false; totalCount?: number = 0; - cycleDur?: number; + cycleDur?: number | string = 0; cycle: number = 0; id?: number; cpu?: number = 0; + startTs?: number = 0; + chartDur?: number = 0; } export class FuncNameCycle { diff --git a/ide/src/trace/bean/ThreadStruct.ts b/ide/src/trace/bean/ThreadStruct.ts index e9f077c011510d6d1a2d28e9b9eab94c527357fd..eec90a7e0fba28011f6e0cec0d028dd61cd6d949 100644 --- a/ide/src/trace/bean/ThreadStruct.ts +++ b/ide/src/trace/bean/ThreadStruct.ts @@ -45,6 +45,8 @@ export class ThreadStruct extends BaseStruct { start_ts: number | undefined; state: string | undefined; type: string | undefined; + prio: number | undefined; + curveFloatY: number | undefined; static draw(threadBeanCanvasCtx: CanvasRenderingContext2D, threadBeanStructData: ThreadStruct): void { if (threadBeanStructData.frame) { @@ -135,4 +137,7 @@ export class ThreadStruct extends BaseStruct { d1.dur === d2.dur ); } + static contrast(d1: ThreadStruct, d2: string | undefined | null, d3: string | undefined | null): boolean { + return d1.pid === Number(d2) && d1.tid === Number(d3); + } } diff --git a/ide/src/trace/component/SpFlags.ts b/ide/src/trace/component/SpFlags.ts index 2b4c86d0968a51fca56626a9b7dd92b2dab291a2..2e031762dd8070185eb499a27ce184ce8ca43a08 100644 --- a/ide/src/trace/component/SpFlags.ts +++ b/ide/src/trace/component/SpFlags.ts @@ -224,11 +224,6 @@ export class FlagsConfig { switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], describeContent: 'Ffrt Convert templates', }, - { - title: 'Bpftrace', - switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], - describeContent: '', - }, { title: 'HMKernel', switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], @@ -244,6 +239,11 @@ export class FlagsConfig { switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], describeContent: 'Lost Frame and HitchTime templates', }, + { + title: 'Start&Finish Trace Category', + switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], + describeContent: 'Asynchronous trace aggregation', + }, { title: 'UserPluginsRow', switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], diff --git a/ide/src/trace/component/SpHelp.ts b/ide/src/trace/component/SpHelp.ts index f75e7a1e06a6d05bf5d11b0d95cb441b9cb07e96..5abcc64fbac7a42a9f4e268bfb75a88b444344bb 100644 --- a/ide/src/trace/component/SpHelp.ts +++ b/ide/src/trace/component/SpHelp.ts @@ -23,6 +23,9 @@ import { EventDefinition, eventDefinitions } from '../enums/helpDocEnums'; @element('sp-help') export class SpHelp extends BaseElement { private appContent: HTMLElement | undefined | null; + private helpFile: HTMLElement | undefined | null; + private navbarContainer: HTMLElement | undefined | null; + private backToTop: HTMLElement | undefined | null; get dark(): boolean { return this.hasAttribute('dark'); @@ -34,15 +37,20 @@ export class SpHelp extends BaseElement { } else { this.removeAttribute('dark'); } - this.appContent!.innerHTML = + this.helpFile!.innerHTML = '('lit-main-menu-group'); @@ -73,17 +81,18 @@ export class SpHelp extends BaseElement { }); let urlParams = new URL(window.location.href).searchParams; if (urlParams && urlParams.get('action') && urlParams.get('action')!.length > 4) { - this.itemHelpClick(urlParams); + this.itemHelpClick(urlParams, that); } } - private itemHelpClick(urlParams: URLSearchParams): void { + private itemHelpClick(urlParams: URLSearchParams, that: this): void { if (urlParams.get('action')!.length > 4) { let helpDocIndex = urlParams.get('action')!.substring(5); let helpDocDetail = this.getEventDefinitionByIndex(Number(helpDocIndex)); - this.appContent!.innerHTML = ``; + + this.navbarInit(helpDocDetail!.name); } } @@ -253,10 +262,54 @@ export class SpHelp extends BaseElement { event: event, action: 'help_doc', }); - that.appContent!.innerHTML = ``; + that.helpFile!.innerHTML = ``; + this.navbarInit(docName); this.changeItemURL(index!); } + private navbarInit(docName: string): void { + fetch(`/application/doc/${docName}.html`) + .then(response => response.text()) + .then(htmlString => { + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlString, "text/html"); + + const hTags = Array.from(doc.body.querySelectorAll('h1, h2, h3, h4, h5, h6')).map((header) => ({ + id: header.id, + text: header.textContent!.trim() + })); + this.navbarContainer!.innerHTML = ``; + + let navLinks = this.navbarContainer!.querySelectorAll('#nav-links a'); + navLinks.forEach((navLink) => { + navLink.addEventListener('click', (e) => { + let lis = this.navbarContainer!.querySelectorAll('#nav-links li'); + lis.forEach(li => li.classList.remove('active')); + navLink.closest('li')!.classList.add('active'); + let targetId = navLink.id; + e.preventDefault(); + this.helpFile!.innerHTML = ``; + }) + }) + + this.backToTop!.querySelector('#back-to-top')!.addEventListener('click', (e)=> { + e.preventDefault(); + navLinks.forEach((navLink) => { + navLink.closest('li')?.classList.remove('active'); + }); + this.helpFile!.innerHTML = ``; + }); + + }) + .catch(error => { + console.error('Error fetching and modifying HTML:', error); + }); + } + private changeItemURL(index: string): void { let url = new URL(window.location.href); let actionParam = url.searchParams.get('action'); @@ -478,29 +531,119 @@ export class SpHelp extends BaseElement { background-color: var(--dark-background5,#F6F6F6); } .body{ - width: 90%; - margin-left: 3%; + width: 99%; + margin-left: 15px; display: grid; grid-template-columns: min-content 1fr; - background-color: var(--dark-background3,#FFFFFF); border-radius: 16px 16px 16px 16px; } .content{ - background: var(--dark-background3,#FFFFFF); border-style: none none none solid; border-width: 1px; border-color: rgba(166,164,164,0.2); border-radius: 0px 16px 16px 0px; - padding: 40px 20px 40px 20px; + padding-left:15px; display: flex; + overflow-y: hidden; + box-sizing: border-box; + } + #navbar-container { + border-left: 5px solid #ecb829; + } + #navbar-container ul { + list-style-type: none; + width:100%; + margin: 0; + padding: 0; + } + #navbar-container ul li { + position: relative; + width:100%; + height:30px; + line-height:30px; + text-align: left; + padding: 0 10px; + box-sizing: border-box; + border: none; + margin: 0; + } + #navbar-container ul li a { + width:100%; + height:100%; + color: black; + font-family: Helvetica; + font-size: 14px; + text-decoration: none; + display: block; + padding: 0; + border: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + #navbar-container ul li:hover, + #navbar-container ul li:focus { + color: #ecb829; + cursor: pointer; + } + #navbar-container ul li:hover a, + #navbar-container ul li:focus a { + color: #ecb829; } + #navbar-container ul li .tooltiptext { + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + visibility: hidden; + width: 100%; + background-color: #ecb829; + color: #fff; + font-family: Helvetica; + font-size: 14px; + text-align: center; + border-radius: 6px; + padding: 5px 5px; + margin-left:5px; + position: absolute; + z-index: 1; + opacity: 0; + transition: opacity 0.3s; + margin-bottom: 40px; + &::after { + content: ''; + position: absolute; + bottom: -10px; + left: 50%; + margin-left: -10px; + width: 0; + height: 0; + border-style: solid; + border-width: 10px 10px 0 10px; + border-color: #ecb829 transparent transparent transparent; + } + } + #navbar-container ul li.tooltip:hover .tooltiptext { + visibility: visible; + opacity: 1; + } + #navbar-container ul li.active, #navbar-container ul li.active a { + color: #ecb829; + }
+
+ +
+ + +
+
diff --git a/ide/src/trace/component/SpInfoAndStas.html.ts b/ide/src/trace/component/SpInfoAndStas.html.ts index cfc018d1ee7bf2b3f7607889546673c64742dc33..9a7961c0fefd48d1affca91e36f42f0be9747fdc 100644 --- a/ide/src/trace/component/SpInfoAndStas.html.ts +++ b/ide/src/trace/component/SpInfoAndStas.html.ts @@ -57,7 +57,6 @@ export const SpInfoAndStatHtml = `
-
+
Target Platform:
@@ -172,7 +173,7 @@ export const SpRecordTraceHtml = `
- Add HDC Device
diff --git a/ide/src/trace/component/SpRecordTrace.ts b/ide/src/trace/component/SpRecordTrace.ts index cb2ffb1114e88d077e4e1f3f351ca60eefee62bd..e02ac30e494866db005551453d1e8652448373d8 100644 --- a/ide/src/trace/component/SpRecordTrace.ts +++ b/ide/src/trace/component/SpRecordTrace.ts @@ -60,12 +60,16 @@ import { createSdkConfig, createHiSystemEventPluginConfig, createArkTsConfig, - createHiLogConfig, + createHiLogConfig, createFFRTPluginConfig, } from './SpRecordConfigModel'; import { SpRecordTraceHtml } from './SpRecordTrace.html'; +import { SpFFRTConfig } from './setting/SpFFRTConfig'; const DEVICE_NOT_CONNECT = - '设备未连接,请使用系统管理员权限打开cmd窗口,并执行hdc kill,然后重新添加设备。若还没有效果,请重新插拔一下手机。'; +'
1.请关闭DevEco Studio,DevEco Testing等会占用hdc端口的应用
' + +'
2.请使用系统管理员权限打开cmd窗口,并执行hdc kill,确保PC端任务管理器中没有hdc进程
' + +'
3.若没有效果,请重新插拔一下手机
' + +'
紧急情况可拷贝trace命令,在cmd窗口离线抓取
'; @element('sp-record-trace') export class SpRecordTrace extends BaseElement { @@ -98,6 +102,7 @@ export class SpRecordTrace extends BaseElement { private spRecordTemplate: SpRecordTemplate | undefined; private spArkTs: SpArkTs | undefined; private spHiLog: SpHilogRecord | undefined; + private spFFRTConfig: SpFFRTConfig | undefined; private ftraceSlider: LitSlider | undefined | null; private spWebShell: SpWebHdcShell | undefined; private menuGroup: LitMainMenuGroup | undefined | null; @@ -169,7 +174,7 @@ export class SpRecordTrace extends BaseElement { this.recordButton!.hidden = true; this.disconnectButton!.hidden = true; this.devicePrompt!.innerText = 'Device not connected'; - this.hintEl!.textContent = DEVICE_NOT_CONNECT; + this.hintEl!.innerHTML = DEVICE_NOT_CONNECT; if (!this.showHint) { this.showHint = true; } @@ -207,7 +212,7 @@ export class SpRecordTrace extends BaseElement { this.recordButton!.hidden = true; this.disconnectButton!.hidden = true; this.devicePrompt!.innerText = 'Device not connected'; - this.hintEl!.textContent = DEVICE_NOT_CONNECT; + this.hintEl!.innerHTML = DEVICE_NOT_CONNECT; if (!this.showHint) { this.showHint = true; } @@ -587,6 +592,7 @@ export class SpRecordTrace extends BaseElement { this.spHiSysEvent = new SpHisysEvent(); this.spArkTs = new SpArkTs(); this.spHiLog = new SpHilogRecord(); + this.spFFRTConfig = new SpFFRTConfig(); this.spWebShell = new SpWebHdcShell(); this.spRecordTemplate = new SpRecordTemplate(this); this.appContent = this.shadowRoot?.querySelector('#app-content') as HTMLElement; @@ -816,16 +822,17 @@ export class SpRecordTrace extends BaseElement { clickHandlerFun?: Function, fileChoose: boolean = false ): MenuItem { + let that = this; return { title: title, icon: icon, fileChoose: fileChoose, clickHandler: (): void => { - this.appContent!.innerHTML = ''; - this.appContent!.append(configPage); - this.freshMenuItemsStatus(title); + that.appContent!.innerHTML = ''; + that.appContent!.append(configPage); + that.freshMenuItemsStatus(title); if (clickHandlerFun) { - clickHandlerFun(this); + clickHandlerFun(that); } }, }; @@ -851,8 +858,9 @@ export class SpRecordTrace extends BaseElement { this.buildMenuItem('VM Tracker', 'vm-tracker', this.spVmTracker!), this.buildMenuItem('HiSystemEvent', 'externaltools', this.spHiSysEvent!), this.buildMenuItem('Ark Ts', 'file-config', this.spArkTs!), + this.buildMenuItem('FFRT', 'file-config', this.spFFRTConfig!), this.buildMenuItem('Hilog', 'realIntentionBulb', this.spHiLog!), - this.buildMenuItem('SDK Config', 'file-config', this.spSdkConfig!), + this.buildMenuItem('SDK Config', 'realIntentionBulb', this.spSdkConfig!), ]; } @@ -963,14 +971,19 @@ export class SpRecordTrace extends BaseElement { this.freshConfigMenuDisable(true); if (SpApplication.isLongTrace) { HdcDeviceManager.shellResultAsString( - CmdConstant.CMD_CLEAR_LONG_FOLD + this.recordSetting!.longOutPath, + `${CmdConstant.CMD_CLEAR_LONG_FOLD + this.recordSetting!.longOutPath}*`, false ).then(() => { HdcDeviceManager.shellResultAsString( CmdConstant.CMD_MKDIR_LONG_FOLD + this.recordSetting!.longOutPath, false ).then(() => { - this.recordLongTraceCmd(traceCommandStr); + HdcDeviceManager.shellResultAsString( + CmdConstant.CMD_SET_FOLD_AUTHORITY + this.recordSetting!.longOutPath, + false + ).then( ()=> { + this.recordLongTraceCmd(traceCommandStr); + }); }); }); } else { @@ -1041,7 +1054,14 @@ export class SpRecordTrace extends BaseElement { } private recordTraceCmd(traceCommandStr: string): void { - HdcDeviceManager.shellResultAsString(CmdConstant.CMD_SHELL + traceCommandStr, false).then((traceResult) => { + const self = this; + let executeCmdCallBack = (cmdStateResult: string): void => { + if (cmdStateResult.includes('tracing ')) { + self.litSearch!.setPercent('Start to record...', -1); + } + }; + this.litSearch!.setPercent('Waiting to record...', -1); + HdcDeviceManager.shellResultAsString(CmdConstant.CMD_SHELL + traceCommandStr, false, executeCmdCallBack).then((traceResult) => { let re = this.isSuccess(traceResult); if (re === 0) { this.litSearch!.setPercent('Tracing htrace down', -1); @@ -1273,8 +1293,8 @@ export class SpRecordTrace extends BaseElement { this.loadLongTraceFile(timStamp).then(() => { let main = this!.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu; let children = main.menus as Array; - let child = children[0].children as Array; - let fileHandler = child[1].clickHandler; + let child = children[1].children as Array; + let fileHandler = child[0].clickHandler; if (fileHandler && !SpRecordTrace.cancelRecord) { this.freshConfigMenuDisable(false); this.freshMenuDisable(false); @@ -1345,6 +1365,7 @@ export class SpRecordTrace extends BaseElement { createHiSystemEventPluginConfig(this.spHiSysEvent!, request); createArkTsConfig(this.spArkTs!, this.recordSetting!, request); createHiLogConfig(reportingFrequency, this.spHiLog!, request); + createFFRTPluginConfig(this.spFFRTConfig!, SpRecordTrace.selectVersion, request); } return request; }; diff --git a/ide/src/trace/component/SpSystemTrace.event.ts b/ide/src/trace/component/SpSystemTrace.event.ts index ef1744b77bf143a61dbedac1c6fe02fdd76782ad..8bcaed67c8615c66f40c5c0a2816437180e0aab4 100644 --- a/ide/src/trace/component/SpSystemTrace.event.ts +++ b/ide/src/trace/component/SpSystemTrace.event.ts @@ -18,20 +18,21 @@ import { ThreadStruct, ThreadStructOnClick } from '../database/ui-worker/Procedu import { TraceRow } from './trace/base/TraceRow'; import { JankStruct, JankStructOnClick } from '../database/ui-worker/ProcedureWorkerJank'; import { HeapSnapshotStruct, HeapSnapshotStructOnClick } from '../database/ui-worker/ProcedureWorkerHeapSnapshot'; -import { funcStructOnClick } from '../database/ui-worker/ProcedureWorkerFunc'; -import { CpuFreqStructOnClick } from '../database/ui-worker/ProcedureWorkerFreq'; -import { ClockStructOnClick } from '../database/ui-worker/ProcedureWorkerClock'; -import { SnapshotStructOnClick } from '../database/ui-worker/ProcedureWorkerSnapshot'; -import { IrqStructOnClick } from '../database/ui-worker/ProcedureWorkerIrq'; -import { HeapStructOnClick } from '../database/ui-worker/ProcedureWorkerHeap'; -import { JsCpuProfilerStructOnClick } from '../database/ui-worker/ProcedureWorkerCpuProfiler'; -import { AppStartupStructOnClick } from '../database/ui-worker/ProcedureWorkerAppStartup'; -import { allAppStartupStructOnClick } from '../database/ui-worker/ProcedureWorkerAllAppStartup'; -import { SoStructOnClick } from '../database/ui-worker/ProcedureWorkerSoInit'; -import { FrameAnimationStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameAnimation'; -import { FrameDynamicStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameDynamic'; -import { FrameSpacingStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameSpacing'; -import { sampleStructOnClick } from '../database/ui-worker/ProcedureWorkerBpftrace'; +import { FuncStruct, funcStructOnClick } from '../database/ui-worker/ProcedureWorkerFunc'; +import { CpuFreqStruct, CpuFreqStructOnClick } from '../database/ui-worker/ProcedureWorkerFreq'; +import { ClockStruct, ClockStructOnClick } from '../database/ui-worker/ProcedureWorkerClock'; +import { DmaFenceStruct, DmaFenceStructOnClick } from '../database/ui-worker/ProcedureWorkerDmaFence'; +import { SnapshotStruct, SnapshotStructOnClick } from '../database/ui-worker/ProcedureWorkerSnapshot'; +import { IrqStruct, IrqStructOnClick } from '../database/ui-worker/ProcedureWorkerIrq'; +import { HeapStruct, HeapStructOnClick } from '../database/ui-worker/ProcedureWorkerHeap'; +import { JsCpuProfilerStruct, JsCpuProfilerStructOnClick } from '../database/ui-worker/ProcedureWorkerCpuProfiler'; +import { AppStartupStruct, AppStartupStructOnClick } from '../database/ui-worker/ProcedureWorkerAppStartup'; +import { AllAppStartupStruct, allAppStartupStructOnClick } from '../database/ui-worker/ProcedureWorkerAllAppStartup'; +import { SoStruct, SoStructOnClick } from '../database/ui-worker/ProcedureWorkerSoInit'; +import { FrameAnimationStruct, FrameAnimationStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameAnimation'; +import { FrameDynamicStruct, FrameDynamicStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameDynamic'; +import { FrameSpacingStruct, FrameSpacingStructOnClick } from '../database/ui-worker/ProcedureWorkerFrameSpacing'; +import { SampleStruct, sampleStructOnClick } from '../database/ui-worker/ProcedureWorkerBpftrace'; import { SportRuler } from './trace/timer-shaft/SportRuler'; import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; import { LitSearch } from './trace/search/Search'; @@ -39,12 +40,17 @@ import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent'; import type { SpKeyboard } from './SpKeyboard'; import { enableVSync } from './chart/VSync'; import { CpuStruct, CpuStructOnClick } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; -import { CpuStateStructOnClick } from '../database/ui-worker/cpu/ProcedureWorkerCpuState'; -import { CpuFreqLimitsStructOnClick } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; +import { CpuStateStruct, CpuStateStructOnClick } from '../database/ui-worker/cpu/ProcedureWorkerCpuState'; +import { + CpuFreqLimitsStruct, + CpuFreqLimitsStructOnClick +} from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; import { FlagsConfig } from './SpFlags'; import { LitMainMenu } from '../../base-ui/menu/LitMainMenu'; -import { PerfToolsStructOnClick } from '../database/ui-worker/ProcedureWorkerPerfTool'; +import { PerfToolsStructOnClick, PerfToolStruct } from '../database/ui-worker/ProcedureWorkerPerfTool'; +import { Utils } from './trace/base/Utils'; import { BaseStruct } from '../bean/BaseStruct'; +import { GpuCounterStruct, gpuCounterStructOnClick } from '../database/ui-worker/ProcedureWorkerGpuCounter'; function timeoutJudge(sp: SpSystemTrace): number { let timeoutJudge = window.setTimeout((): void => { @@ -95,62 +101,77 @@ function threadClickHandlerFunc(sp: SpSystemTrace): (e: ThreadStruct) => void { sp.observerScrollHeightEnable = false; sp.scrollToProcess(`${d.cpu}`, '', 'cpu-data', true); let cpuRow = sp.queryAllTraceRow>( - `trace-row[row-id='${d.cpu}'][row-type='cpu-data']`, - (row) => row.rowId === `${d.cpu}` && row.rowType === 'cpu-data' + `trace-row[row-id='${Utils.getDistributedRowId(d.cpu)}'][row-type='cpu-data']`, + (row) => row.rowId === `${Utils.getDistributedRowId(d.cpu)}` && row.rowType === 'cpu-data' )[0]; - sp.currentRow = cpuRow; - cpuRow.fixedList = [ - { - startTime: d.startTime, - dur: d.dur, - tid: d.tid, - id: d.id, - processId: d.pid, - cpu: d.cpu, - argSetID: d.argSetID, - }, - ]; - let findEntry = cpuRow!.fixedList[0]; - sp.rechargeCpuData( - // @ts-ignore - findEntry, // @ts-ignore - cpuRow.dataListCache.find((it) => it.startTime > findEntry.startTime) - ); - if ( - // @ts-ignore - findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || // @ts-ignore - findEntry!.startTime! > TraceRow.range!.endNS - ) { - sp.timerShaftEL?.setRangeNS( + if (cpuRow) { + sp.currentRow = cpuRow; + cpuRow.fixedList = [ + { + startTime: d.startTime, + dur: d.dur, + tid: d.tid, + id: d.id, + processId: d.pid, + cpu: d.cpu, + argSetID: d.argSetID, + }, + ]; + let findEntry = cpuRow!.fixedList[0]; + sp.rechargeCpuData( // @ts-ignore - findEntry!.startTime! - findEntry!.dur! * 2, // @ts-ignore - findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2 + findEntry, // @ts-ignore + cpuRow.dataListCache.find((it) => it.startTime > findEntry.startTime) + ); + if ( + // @ts-ignore + findEntry!.startTime! + findEntry!.dur! < TraceRow.range!.startNS || // @ts-ignore + findEntry!.startTime! > TraceRow.range!.endNS + ) { + sp.timerShaftEL?.setRangeNS( + // @ts-ignore + findEntry!.startTime! - findEntry!.dur! * 2, // @ts-ignore + findEntry!.startTime! + findEntry!.dur! + findEntry!.dur! * 2 + ); + } + sp.hoverStructNull().selectStructNull().wakeupListNull(); // @ts-ignore + CpuStruct.hoverCpuStruct = findEntry; // @ts-ignore + CpuStruct.selectCpuStruct = findEntry; // @ts-ignore + sp.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, 'inverted'); + sp.traceSheetEL?.displayCpuData( + CpuStruct.selectCpuStruct!, + (wakeUpBean) => { + sp.removeLinkLinesByBusinessType('thread'); + CpuStruct.wakeupBean = wakeUpBean; + sp.refreshCanvas(true); + }, + cpuClickHandlerFunc(sp) ); } - sp.hoverStructNull().selectStructNull().wakeupListNull(); // @ts-ignore - CpuStruct.hoverCpuStruct = findEntry; // @ts-ignore - CpuStruct.selectCpuStruct = findEntry; // @ts-ignore - sp.timerShaftEL?.drawTriangle(findEntry!.startTime || 0, 'inverted'); - sp.traceSheetEL?.displayCpuData( - CpuStruct.selectCpuStruct!, - (wakeUpBean) => { - sp.removeLinkLinesByBusinessType('thread'); - CpuStruct.wakeupBean = wakeUpBean; - sp.refreshCanvas(true); - }, - cpuClickHandlerFunc(sp) - ); }; return threadClickHandler; } -function scrollToFuncHandlerFunc(sp: SpSystemTrace) { - return function (funcStruct: unknown): void { +//点击prio箭头刷新canvas +function prioClickHandlerFunc(sp: SpSystemTrace) { + return function (d: any) { + ThreadStruct.prioCount = d; + ThreadStruct.isClickPrio = true; + sp.refreshCanvas(true); + }; +} + +function scrollToFuncHandlerFunc(sp: SpSystemTrace): Function { + let funClickHandle = (funcStruct: unknown): void => { + // @ts-ignore + if (funcStruct.chainId) { + } sp.observerScrollHeightEnable = true; - //@ts-ignore + // @ts-ignore sp.moveRangeToCenter(funcStruct.startTs!, funcStruct.dur!); sp.scrollToActFunc(funcStruct, false); }; + return funClickHandle; } function jankClickHandlerFunc(sp: SpSystemTrace): Function { @@ -172,7 +193,7 @@ function jankClickHandlerFunc(sp: SpSystemTrace): Function { //@ts-ignore jankRowParent.childrenList.forEach((item: TraceRow) => { //@ts-ignore - if (item.rowId === `${d.rowId}` && item.rowType === 'janks') { + if (`${item.rowId}` === `${d.rowId}` && `${item.rowType}` === 'janks') { jankRow = item; } }); @@ -181,7 +202,10 @@ function jankClickHandlerFunc(sp: SpSystemTrace): Function { if (jankRow) { JankStruct.selectJankStructList.length = 0; //@ts-ignore - let findJankEntry = jankRow!.dataListCache!.find((dat: unknown) => dat.name === d.name && dat.pid === d.pid); + let findJankEntry = jankRow!.dataListCache!.find( + //@ts-ignore + (dat: unknown) => `${dat.name}` == `${d.name}` && `${dat.pid}` == `${d.pid}` + ); if (findJankEntry) { if ( findJankEntry!.ts! + findJankEntry!.dur! < TraceRow.range!.startNS || @@ -203,8 +227,7 @@ function jankClickHandlerFunc(sp: SpSystemTrace): Function { // 绘制跟自己关联的线 datas.forEach((data) => { //@ts-ignore - let endParentRow = sp.shadowRoot?.querySelector>( - // @ts-ignore + let endParentRow = sp.shadowRoot?.querySelector>( // @ts-ignore `trace-row[row-type='process'][row-id='${data.pid}'][folder]` ); sp.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data, true); @@ -223,7 +246,7 @@ function jankClickHandlerFunc(sp: SpSystemTrace): Function { function snapshotClickHandlerFunc(sp: SpSystemTrace): Function { let snapshotClickHandler = (d: HeapSnapshotStruct): void => { sp.observerScrollHeightEnable = true; - let snapshotRow = sp.shadowRoot?.querySelector>("trace-row[row-id='heapsnapshot']"); + let snapshotRow = sp.shadowRoot?.querySelector>(`trace-row[row-id='heapsnapshot']`); let task = (): void => { if (snapshotRow) { let findEntry = snapshotRow!.dataListCache!.find((dat) => dat.startTs === d.startTs); @@ -274,6 +297,7 @@ function cpuClickHandlerTask(threadRow: TraceRow, sp: SpSystemTrace, d: ThreadStruct.selectThreadStruct!, threadClickHandlerFunc(sp), // @ts-ignore cpuClickHandlerFunc(sp), + prioClickHandlerFunc(sp), (datas, str): void => { sp.removeLinkLinesByBusinessType('thread'); if (str === 'wakeup tid') { @@ -296,14 +320,14 @@ function cpuClickHandlerFunc(sp: SpSystemTrace) { return function (d: CpuStruct): void { //@ts-ignore let traceRow = sp.shadowRoot?.querySelector>( - `trace-row[row-id='${d.processId}'][row-type='process']` + `trace-row[row-id='${Utils.getDistributedRowId(d.processId)}'][row-type='process']` ); if (traceRow) { traceRow.expansion = true; } sp.observerScrollHeightEnable = true; let threadRow = sp.queryAllTraceRow>( - `trace-row[row-id='${d.tid}'][row-type='thread']`, + `trace-row[row-id='${Utils.getDistributedRowId(d.tid)}'][row-type='thread']`, (row) => row.rowId === `${d.tid}` && row.rowType === 'thread' )[0]; sp.currentRow = threadRow; @@ -331,36 +355,37 @@ function cpuClickHandlerFunc(sp: SpSystemTrace) { }; } -//@ts-ignore -function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRow, entry?: unknown): void { - CpuStructOnClick(clickRowType, sp, cpuClickHandlerFunc(sp)) - .then(() => ThreadStructOnClick(clickRowType, sp, threadClickHandlerFunc(sp), cpuClickHandlerFunc(sp))) - //@ts-ignore - .then(() => funcStructOnClick(clickRowType, sp, row, scrollToFuncHandlerFunc(sp), entry)) - .then(() => CpuFreqStructOnClick(clickRowType, sp)) - .then(() => CpuStateStructOnClick(clickRowType, sp)) - .then(() => CpuFreqLimitsStructOnClick(clickRowType, sp)) - .then(() => ClockStructOnClick(clickRowType, sp)) - //@ts-ignore - .then(() => SnapshotStructOnClick(clickRowType, sp, row!)) - .then(() => IrqStructOnClick(clickRowType, sp)) - //@ts-ignore - .then(() => HeapStructOnClick(clickRowType, sp, row)) - //@ts-ignore - .then(() => JankStructOnClick(clickRowType, sp, row!, jankClickHandlerFunc(sp))) - //@ts-ignore - .then(() => HeapSnapshotStructOnClick(clickRowType, sp, row!, snapshotClickHandlerFunc(sp))) - //@ts-ignore - .then(() => JsCpuProfilerStructOnClick(clickRowType, sp, row!)) - .then(() => AppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp))) - .then(() => allAppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp))) - .then(() => SoStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp))) //@ts-ignore - .then(() => FrameAnimationStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), row!)) - .then(() => FrameDynamicStructOnClick(clickRowType, sp, row)) - .then(() => FrameSpacingStructOnClick(clickRowType, sp, row!)) - .then(() => sampleStructOnClick(clickRowType, sp, row)) - .then(() => PerfToolsStructOnClick(clickRowType, sp)) +function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRow, entry?: unknown): void { + CpuStructOnClick(clickRowType, sp, cpuClickHandlerFunc(sp), entry as CpuStruct) + .then(() => ThreadStructOnClick(clickRowType, sp, threadClickHandlerFunc(sp), cpuClickHandlerFunc(sp), + prioClickHandlerFunc(sp), entry as ThreadStruct)) + .then(() => funcStructOnClick(clickRowType, sp, row as TraceRow, + scrollToFuncHandlerFunc(sp), entry as FuncStruct)) + .then(() => CpuFreqStructOnClick(clickRowType, sp, entry as CpuFreqStruct)) + .then(() => CpuStateStructOnClick(clickRowType, sp, entry as CpuStateStruct)) + .then(() => CpuFreqLimitsStructOnClick(clickRowType, sp, entry as CpuFreqLimitsStruct)) + .then(() => ClockStructOnClick(clickRowType, sp, entry as ClockStruct)) + .then(() => DmaFenceStructOnClick(clickRowType, sp, entry as DmaFenceStruct)) + .then(() => SnapshotStructOnClick(clickRowType, sp, row as TraceRow, entry as SnapshotStruct)) + .then(() => IrqStructOnClick(clickRowType, sp, entry as IrqStruct)) + .then(() => HeapStructOnClick(clickRowType, sp, row as TraceRow, entry as HeapStruct)) + .then(() => JankStructOnClick(clickRowType, sp, row as TraceRow, + jankClickHandlerFunc(sp), entry as JankStruct)) + .then(() => HeapSnapshotStructOnClick(clickRowType, sp, row as TraceRow, + snapshotClickHandlerFunc(sp), entry as HeapSnapshotStruct)) + .then(() => JsCpuProfilerStructOnClick(clickRowType, sp, row as TraceRow, + entry as JsCpuProfilerStruct)) + .then(() => AppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), entry as AppStartupStruct)) + .then(() => allAppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), entry as AllAppStartupStruct)) + .then(() => SoStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp), entry as SoStruct)) + .then(() => FrameAnimationStructOnClick(clickRowType, sp, + scrollToFuncHandlerFunc(sp), row as TraceRow, entry as FrameAnimationStruct)) + .then(() => FrameDynamicStructOnClick(clickRowType, sp, row, entry as FrameDynamicStruct)) + .then(() => FrameSpacingStructOnClick(clickRowType, sp, row!, entry as FrameSpacingStruct)) + .then(() => sampleStructOnClick(clickRowType, sp, row as TraceRow, entry as SampleStruct)) + .then(() => gpuCounterStructOnClick(clickRowType, sp, entry as GpuCounterStruct)) + .then(() => PerfToolsStructOnClick(clickRowType, sp, entry as PerfToolStruct)) .then(() => { if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) { sp.removeLinkLinesByBusinessType('janks'); @@ -370,7 +395,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo sp.timerShaftEL?.removeTriangle('inverted'); if (!SportRuler.isMouseInSportRuler) { sp.traceSheetEL?.setMode('hidden'); - sp.refreshCanvas(true); + sp.refreshCanvas(true, 'click'); } }) .catch((e): void => { }); @@ -378,8 +403,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo export default function spSystemTraceOnClickHandler( sp: SpSystemTrace, clickRowType: string, - //@ts-ignore - row?: TraceRow, + row?: TraceRow, entry?: unknown ): void { if (row) { @@ -402,6 +426,9 @@ export default function spSystemTraceOnClickHandler( if (!ThreadStruct.selectThreadStruct) { sp.removeLinkLinesByBusinessType('thread'); } + if (!FuncStruct.selectFuncStruct) { + sp.removeLinkLinesByBusinessType('distributed','func'); + } if (row) { let pointEvent = sp.createPointEvent(row); SpStatisticsHttpUtil.addOrdinaryVisitAction({ @@ -413,6 +440,13 @@ export default function spSystemTraceOnClickHandler( //@ts-ignore function handleActions(sp: SpSystemTrace, rows: Array>, ev: MouseEvent): void { + if (sp.rangeSelect.isMouseDown && sp.rangeSelect.drag) { + let downRow = sp.visibleRows.find((row) => row.containPoint(ev)); + if (downRow && downRow.traceId !== Utils.currentSelectTrace) { + spSystemTraceDocumentOnMouseMoveMouseUp(sp, rows, ev); + return; + } + } sp.rangeSelect.mouseMove(rows, ev); if (sp.rangeSelect.rangeTraceRow!.length > 0) { sp.tabCpuFreq!.rangeTraceRow = sp.rangeSelect.rangeTraceRow; @@ -483,7 +517,7 @@ export function spSystemTraceDocumentOnMouseMove(sp: SpSystemTrace, ev: MouseEve } function spSystemTraceDocumentOnMouseMoveMouseDown(sp: SpSystemTrace, search: LitSearch): void { - sp.refreshCanvas(true); + sp.refreshCanvas(true, 'sp move down'); if (TraceRow.rangeSelectObject) { if (search && search.searchValue !== '') { search.clear(); @@ -500,8 +534,11 @@ function spSystemTraceDocumentOnMouseMoveMouseUp( if (!sp.rowsPaneEL!.containPoint(ev, { left: 248 })) { sp.hoverStructNull(); } + const transformYMatch = sp.canvasPanel?.style.transform.match(/\((\d+)[^\)]+\)/); + const transformY = transformYMatch![1]; + let favoriteHeight = sp.favoriteChartListEL!.getBoundingClientRect().height; rows - .filter((it) => it.focusContain(ev, sp.inFavoriteArea!) && it.collect === sp.inFavoriteArea) + .filter((it) => it.focusContain(ev, sp.inFavoriteArea!,Number(transformY),favoriteHeight) && it.collect === sp.inFavoriteArea) .filter((it) => { if (it.collect) { return true; @@ -513,19 +550,23 @@ function spSystemTraceDocumentOnMouseMoveMouseUp( } }) .forEach((tr): void => { + if (tr.rowType !== TraceRow.ROW_TYPE_CPU) { + CpuStruct.hoverCpuStruct = undefined; + } if (sp.currentRowType !== tr.rowType) { sp.currentRowType = tr.rowType || ''; } tr.findHoverStruct?.(); tr.focusHandler?.(ev); }); - requestAnimationFrame(() => sp.refreshCanvas(true)); + requestAnimationFrame(() => sp.refreshCanvas(true, 'sp move up')); } export function spSystemTraceDocumentOnMouseOut(sp: SpSystemTrace, ev: MouseEvent): void { if (!sp.loadTraceCompleted) { return; } + CpuStruct.hoverCpuStruct = undefined; TraceRow.isUserInteraction = false; SpSystemTrace.isMouseLeftDown = false; if (sp.isMouseInSheet(ev)) { @@ -635,6 +676,8 @@ export function spSystemTraceDocumentOnMouseDown(sp: SpSystemTrace, ev: MouseEve if (y > sp.timerShaftEL!.offsetHeight) { sp.rangeSelect.mouseDown(ev); sp.rangeSelect.drag = true; + let downRow = sp.visibleRows.find((row) => row.containPoint(ev)); + Utils.currentSelectTrace = downRow?.traceId; } // 如果鼠标摁下事件发生在traceRow范围或时间轴(sportRuler除外)范围内,清除上次点击调用栈产生的所有的三角旗子 // ev.offsetY:鼠标在SpSystemTrace元素的y轴偏移量 @@ -738,7 +781,7 @@ export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEven let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); let flagsItemJson = JSON.parse(flagsItem!); if (flagsItemJson.VSync === 'Enabled') { - sp.keyboardEnable && enableVSync(false, ev, () => sp.refreshCanvas(true)); + sp.keyboardEnable && enableVSync(false, ev, () => sp.refreshCanvas(true, 'sp key up')); } let keyPress = ev.key.toLocaleLowerCase(); if (keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd') { @@ -757,12 +800,14 @@ export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEven }) ); } else { - sp.dispatchEvent( - new CustomEvent('trace-next-data', { - detail: {}, - composed: false, - }) - ); + if (sp.focusTarget === '') { + sp.dispatchEvent( + new CustomEvent('trace-next-data', { + detail: {}, + composed: false, + }) + ); + } } document.addEventListener('keydown', sp.documentOnKeyDown); } @@ -838,8 +883,12 @@ function handleClickActions(sp: SpSystemTrace, x: number, y: number, ev: MouseEv x < (TraceRow.rangeSelectObject?.endX || 0) ) ) { + const transformYMatch = sp.canvasPanel?.style.transform.match(/\((\d+)[^\)]+\)/); + const transformY = transformYMatch![1]; let inFavoriteArea = sp.favoriteChartListEL?.containPoint(ev); - let rows = sp.visibleRows.filter((it) => it.focusContain(ev, inFavoriteArea!) && it.collect === inFavoriteArea); + let favoriteHeight = sp.favoriteChartListEL!.getBoundingClientRect().height; + let rows = sp.visibleRows.filter((it) => + it.focusContain(ev, inFavoriteArea!, Number(transformY),favoriteHeight) && it.collect === inFavoriteArea); if (JankStruct.delJankLineFlag) { sp.removeLinkLinesByBusinessType('janks'); } @@ -852,8 +901,9 @@ function handleClickActions(sp: SpSystemTrace, x: number, y: number, ev: MouseEv strict = false; offset = true; } - if (rows && rows[0] && rows[0].getHoverStruct(strict, offset)) { - sp.onClickHandler(rows[0]!.rowType!, rows[0]); + if (rows && rows[0] && (rows[0].getHoverStruct(strict, offset) || + (rows[0].rowType === TraceRow.ROW_TYPE_GPU_COUNTER && rows[0].getHoverStruct(false)))) { + sp.onClickHandler(rows[0]!.rowType!, rows[0], rows[0].getHoverStruct(strict, offset)); sp.documentOnMouseMove(ev); } else { sp.clickEmptyArea(); diff --git a/ide/src/trace/component/SpSystemTrace.init.ts b/ide/src/trace/component/SpSystemTrace.init.ts index a37157a6664d5140347b1caa909e594c20d11b17..405dd85fdcddc56217ead81276cb5b771d32ff8e 100644 --- a/ide/src/trace/component/SpSystemTrace.init.ts +++ b/ide/src/trace/component/SpSystemTrace.init.ts @@ -26,7 +26,7 @@ import { queryEbpfSamplesCount } from '../database/sql/Memory.sql'; import { SpChartManager } from './chart/SpChartManager'; import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; import { FlagsConfig } from './SpFlags'; -import { threadPool } from '../database/SqlLite'; +import { threadPool, threadPool2 } from '../database/SqlLite'; import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; import { CpuStruct } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; import { PairPoint } from '../database/ui-worker/ProcedureWorkerCommon'; @@ -34,14 +34,16 @@ import { TraceSheet } from './trace/base/TraceSheet'; import { TimerShaftElement } from './trace/TimerShaftElement'; import { SpChartList } from './trace/SpChartList'; type HTMLElementAlias = HTMLElement | null | undefined; -function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unknown { +import { Utils } from './trace/base/Utils'; + +function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): any { Object.assign(sp, { ext(): string { return 'Handle the right button click event'; }, }); - return function (event: unknown): void { + return function (event: any): void { if (SpSystemTrace.btnTimer) { return; } @@ -78,7 +80,7 @@ function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unk }; } function rightStarOnClick(sp: SpSystemTrace) { - return function (ev: unknown): void { + return function (ev: any): void { let wakeupLists = []; wakeupLists.push(CpuStruct.selectCpuStruct?.cpu); for (let wakeupBean of SpSystemTrace.wakeupList) { @@ -86,80 +88,57 @@ function rightStarOnClick(sp: SpSystemTrace) { } let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort(); for (let wakeupCpu of wakeupCpuLists) { - // @ts-ignore - let cpuFavoriteRow: unknown = sp.shadowRoot?.querySelector>( - `trace-row[row-type='cpu-data'][row-id='${wakeupCpu}']` + let cpuFavoriteRow: any = sp.shadowRoot?.querySelector>( + `trace-row[row-type='cpu-data'][row-id='${Utils.getDistributedRowId(wakeupCpu)}']` ); if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) { continue; } - // @ts-ignore cpuFavoriteRow!.setAttribute('collect-type', ''); let replaceRow = document.createElement('div'); - // @ts-ignore replaceRow.setAttribute('row-id', `${cpuFavoriteRow.rowId}-${cpuFavoriteRow.rowType}`); replaceRow.setAttribute('type', 'replaceRow'); - // @ts-ignore replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId); replaceRow.style.display = 'none'; - // @ts-ignore cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene'); - // @ts-ignore if (sp.rowsEL!.contains(cpuFavoriteRow)) { - // @ts-ignore sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow); } - // @ts-ignore cpuFavoriteRow.tampName = cpuFavoriteRow.name; - // @ts-ignore - sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, sp.currentCollectGroup, true); - // @ts-ignore + sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, cpuFavoriteRow.traceId || sp.currentCollectGroup, true); sp.collectRows.push(cpuFavoriteRow); sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); sp.currentClickRow = null; - // @ts-ignore cpuFavoriteRow.setAttribute('draggable', 'true'); - // @ts-ignore cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp, cpuFavoriteRow)); - // @ts-ignore cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp)); - // @ts-ignore cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp, cpuFavoriteRow)); - // @ts-ignore cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp)); } sp.refreshFavoriteCanvas(); sp.refreshCanvas(true); }; } -function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: unknown) { +function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: any) { return function (): void { - // @ts-ignore sp.currentClickRow = cpuFavoriteRow; }; } function cpuFavoriteRowDragOver(sp: SpSystemTrace) { - return function (ev: unknown): void { - // @ts-ignore + return function (ev: any): void { ev.preventDefault(); - // @ts-ignore ev.dataTransfer.dropEffect = 'move'; }; } -function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: unknown) { - return function (ev: unknown): void { +function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: any) { + return function (ev: any): void { if (sp.favoriteChartListEL && sp.currentClickRow && sp.currentClickRow !== cpuFavoriteRow) { - // @ts-ignore let rect = cpuFavoriteRow.getBoundingClientRect(); - // @ts-ignore if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { //向上移动 - // @ts-ignore sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow); - // @ts-ignore } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { //向下移动 - // @ts-ignore sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling); } sp.refreshFavoriteCanvas(); @@ -185,33 +164,25 @@ function cpuFavoriteRowDragendHandler(sp: SpSystemTrace): () => void { sp.currentClickRow = null; }; } -function triangleFlagHandler(sp: SpSystemTrace): (event: unknown) => void { - return function (event: unknown): void { - // @ts-ignore +function triangleFlagHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); - // @ts-ignore if (event.detail.timeCallback && temporaryTime) { - // @ts-ignore event.detail.timeCallback(temporaryTime); } }; } -function numberCalibrationHandler(sp: SpSystemTrace): (event: unknown) => void { - return function (event: unknown): void { - // @ts-ignore +function numberCalibrationHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { sp.timerShaftEL!.sportRuler!.times = event.detail.time; - // @ts-ignore sp.timerShaftEL!.sportRuler!.counts = event.detail.counts; - // @ts-ignore sp.timerShaftEL!.sportRuler!.durations = event.detail.durations; sp.timerShaftEL!.sportRuler?.draw(); }; } -function flagChangeHandler(sp: SpSystemTrace): (event: unknown) => void { - return function (event: unknown): void { - // @ts-ignore +function flagChangeHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { sp.timerShaftEL?.modifyFlagList(event.detail); - // @ts-ignore if (event.detail.hidden) { sp.selectFlag = undefined; if (sp._flagList.length <= 0) { @@ -227,11 +198,9 @@ function flagChangeHandler(sp: SpSystemTrace): (event: unknown) => void { } }; } -function slicesChangeHandler(sp: SpSystemTrace): (event: unknown) => void { - return function (event: unknown): void { - // @ts-ignore +function slicesChangeHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { sp.timerShaftEL?.modifySlicesList(event.detail); - // @ts-ignore if (event.detail.hidden) { sp.slicestime = null; if (sp._slicesList.length <= 0) { @@ -247,9 +216,8 @@ function slicesChangeHandler(sp: SpSystemTrace): (event: unknown) => void { } }; } -function collectHandler(sp: SpSystemTrace): (event: unknown) => void { - return function (event: unknown): void { - // @ts-ignore +function collectHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { let currentRow = event.detail.row; if (currentRow.collect) { collectHandlerYes(sp, currentRow, event); @@ -282,22 +250,17 @@ function collectHandler(sp: SpSystemTrace): (event: unknown) => void { currentRow.addEventListener('dragstart', () => { sp.currentClickRow = currentRow; }); - currentRow.addEventListener('dragover', (ev: unknown) => { - // @ts-ignore + currentRow.addEventListener('dragover', (ev: any) => { ev.preventDefault(); - // @ts-ignore ev.dataTransfer.dropEffect = 'move'; }); currentRow.addEventListener('drop', collectHandlerDrop(sp, currentRow)); currentRow.addEventListener('dragend', collectHandlerDragEnd(sp)); }; } -function collectHandlerNo(sp: SpSystemTrace, currentRow: unknown, event: unknown): void { - // @ts-ignore +function collectHandlerNo(sp: SpSystemTrace, currentRow: any, event: any): void { sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect'); - // @ts-ignore if (event.detail.type !== 'auto-collect') { - // @ts-ignore let rowIndex = sp.collectRows.indexOf(currentRow); if (rowIndex !== -1) { sp.collectRows.splice(rowIndex, 1); @@ -305,102 +268,110 @@ function collectHandlerNo(sp: SpSystemTrace, currentRow: unknown, event: unknown } let row = currentRow; let allowExpansionRow = []; - // @ts-ignore while (row.hasParentRowEl) { - // @ts-ignore let parent = row.parentRowEl; allowExpansionRow.push(parent); row = parent; } - for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { - if (allowExpansionRow[index]?.hasAttribute('scene')) { - if (allowExpansionRow[index]!.expansion) { - allowExpansionRow[index].updateChildRowStatus(); - } else { - allowExpansionRow[index].expansion = true; + if (allowExpansionRow.length === 1) { + for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { + if (allowExpansionRow[index]?.hasAttribute('scene')) { + if (allowExpansionRow[index]!.expansion) { + allowExpansionRow[index].updateChildRowStatus(); + } else { + allowExpansionRow[index].expansion = true; + } + } + } + } else { + for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { + let currentItemRow = allowExpansionRow[index]; + if (currentItemRow.hasAttribute('scene')) { + if (currentItemRow.rowParentId !== '') { + if (currentItemRow.expansion) { + currentItemRow.updateChildRowStatus(); + } else { + currentItemRow.expansion = true; + } + } + else { + currentItemRow.expansion = true; + let number = currentItemRow.childrenList.indexOf(currentRow); + if (number !== -1) {// 确保 currentRow 在 childrenList 中 + let childrenEl = currentItemRow.childrenList[number]; + let childrenNextEl = currentItemRow.childrenList[number + 1]; + if (childrenEl) { + if (childrenNextEl) { + currentItemRow.parentNode.insertBefore(childrenEl, currentItemRow.childrenList[number + 1]); + } else if (childrenEl.nextSibling) { + currentItemRow.parentNode.insertBefore(childrenEl, childrenEl.nextSibling); + } else { + currentItemRow.parentNode.appendChild(childrenEl); + } + } + } + } } } } allowExpansionRow.length = 0; + let traceId = currentRow.traceId ? `${currentRow.traceId}-` : ''; let replaceRow = sp.rowsEL!.querySelector( - // @ts-ignore - `div[row-id='${currentRow.rowId}-${currentRow.rowType}']` + `div[row-id='${traceId}${currentRow.rowId}-${currentRow.rowType}']` ); // 取消收藏时,删除父亲ID - // @ts-ignore currentRow.name = currentRow.tampName; if (replaceRow !== null) { - // @ts-ignore sp.rowsEL!.replaceChild(currentRow, replaceRow); - // @ts-ignore currentRow.style.boxShadow = '0 10px 10px #00000000'; } } -function collectHandlerYes(sp: SpSystemTrace, currentRow: unknown, event: unknown): void { - if ( - !sp.collectRows.find((find) => { - return find === currentRow; - }) - ) { - // @ts-ignore +function collectHandlerYes(sp: SpSystemTrace, currentRow: any, event: any): void { + if (!sp.collectRows.find((find) => find === currentRow)) { sp.collectRows.push(currentRow); } let replaceRow = document.createElement('div'); - // @ts-ignore - replaceRow.setAttribute('row-id', `${currentRow.rowId}-${currentRow.rowType}`); + let traceId = currentRow.traceId ? `${currentRow.traceId}-` : ''; + replaceRow.setAttribute('row-id', `${traceId}${currentRow.rowId}-${currentRow.rowType}`); replaceRow.setAttribute('type', 'replaceRow'); - // @ts-ignore replaceRow.setAttribute('row-parent-id', currentRow.rowParentId); replaceRow.style.display = 'none'; - // @ts-ignore if (!currentRow.hasAttribute('scene')) { - // @ts-ignore currentRow.setAttribute('row-hidden', ''); } else { - // @ts-ignore currentRow.removeAttribute('row-hidden'); } // 添加收藏时,在线程名前面追加父亲ID - // @ts-ignore let rowParentId = currentRow.rowParentId; - // @ts-ignore currentRow.tampName = currentRow.name; if (rowParentId) { - // @ts-ignore - let parentRows = sp.shadowRoot?.querySelectorAll>(`trace-row[row-id='${rowParentId}']`); + let parentRows = sp.shadowRoot?.querySelectorAll>(`trace-row[row-id='${rowParentId}']`); parentRows?.forEach((parentRow) => { if ( parentRow?.name && - // @ts-ignore parentRow?.name !== currentRow.name && !parentRow.rowType!.startsWith('cpu') && !parentRow.rowType!.startsWith('thread') && !parentRow.rowType!.startsWith('func') && - // @ts-ignore !currentRow.name.includes(parentRow.name) ) { - // @ts-ignore currentRow.name += `(${parentRow.name})`; } }); } - // @ts-ignore if (!currentRow.hasParentRowEl) { - // @ts-ignore sp.rowsEL!.replaceChild(replaceRow, currentRow); } - // @ts-ignore - sp.favoriteChartListEL?.insertRow(currentRow, sp.currentCollectGroup, event.detail.type !== 'auto-collect'); + let group = currentRow.traceId || sp.currentCollectGroup; + sp.favoriteChartListEL?.insertRow(currentRow, group, event.detail.type !== 'auto-collect'); } -function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | undefined | null): (ev: unknown) => void { - return function (ev: unknown) { +function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | undefined | null): (ev: any) => void { + return function (ev: any) { if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) { let rect = currentRow!.getBoundingClientRect(); - // @ts-ignore if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { //向上移动 sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!); - // @ts-ignore } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { //向下移动 sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!); @@ -409,8 +380,8 @@ function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | unde } }; } -function collectHandlerDragEnd(sp: SpSystemTrace): (ev: unknown) => void { - return function (ev: unknown): void { +function collectHandlerDragEnd(sp: SpSystemTrace): (ev: any) => void { + return function (ev: any): void { sp.linkNodes.forEach((itln) => { if (itln[0].rowEL.collect) { if (sp.timerShaftEL?._checkExpand) { @@ -447,8 +418,7 @@ function selectHandler(sp: SpSystemTrace): void { }); if (rows.length === 0) { const allRows = [ - // @ts-ignore - ...sp.shadowRoot!.querySelectorAll>('trace-row'), + ...sp.shadowRoot!.querySelectorAll>('trace-row'), ...sp.favoriteChartListEL!.getAllCollectRows(), ]; for (const row of allRows) { @@ -468,8 +438,7 @@ function selectHandler(sp: SpSystemTrace): void { let checkRows = rows; if (!refreshCheckBox) { checkRows = [ - // @ts-ignore - ...sp.shadowRoot!.querySelectorAll>("trace-row[check-type='2']"), + ...sp.shadowRoot!.querySelectorAll>(`trace-row[check-type='2']`), ...sp.favoriteChartListEL!.getAllSelectCollectRows(), ]; } @@ -480,36 +449,24 @@ function selectHandler(sp: SpSystemTrace): void { selectHandlerRows(sp, checkRows); }; } -// @ts-ignore -function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array>, refreshCheckBox: boolean): void { +function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array>, refreshCheckBox: boolean): void { if (refreshCheckBox) { if (rows.length > 0) { - sp.queryAllTraceRow().forEach((row) => { - row.checkType = '0'; - if (row.folder) { - row.childrenList.forEach((ite) => (ite.checkType = '0')); - } - }); + sp.queryAllTraceRow().forEach((row) => (row.checkType = '0')); rows.forEach((it) => (it.checkType = '2')); } else { - sp.queryAllTraceRow().forEach((row) => { - row.checkType = '-1'; - if (row.folder) { - row.childrenList.forEach((it) => (it.checkType = '-1')); - } - }); + sp.queryAllTraceRow().forEach((row) => (row.checkType = '-1')); return; } } } -// @ts-ignore -function selectHandlerRows(sp: SpSystemTrace, rows: Array>): void { +function selectHandlerRows(sp: SpSystemTrace, rows: Array>): void { let selection = new SelectionParam(); + selection.traceId = Utils.currentSelectTrace; selection.cpuStateRowsId = sp.stateRowsId; selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; - // @ts-ignore - selection.recordStartNs = (window as unknown).recordStartNS; + selection.recordStartNs = Utils.getInstance().getRecordStartNS(Utils.currentSelectTrace); rows.forEach((it) => { selection.pushSelection(it, sp); if (sp.rangeTraceRow!.length !== rows.length) { @@ -558,8 +515,7 @@ function resizeObserverHandler(sp: SpSystemTrace): void { TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth(); requestAnimationFrame(() => { sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth()); - // @ts-ignore - sp.shadowRoot!.querySelectorAll>('trace-row').forEach((it) => { + sp.shadowRoot!.querySelectorAll>('trace-row').forEach((it) => { it.updateWidth(sp.clientWidth); }); }); @@ -603,8 +559,7 @@ function intersectionObserverHandler(sp: SpSystemTrace): void { sp.intersectionObserver = new IntersectionObserver( (entries) => { entries.forEach((it) => { - // @ts-ignore - let tr = it.target as TraceRow; + let tr = it.target as TraceRow; // 目标元素的可见比例 tr.intersectionRatio = it.intersectionRatio; // 判断目标元素是否可见 isIntersecting为true是可见 @@ -661,8 +616,7 @@ function smartEventSubscribe(sp: SpSystemTrace): void { window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => { if (!collapse) { // 一键折叠之前,记录当前打开的泳道图 - // @ts-ignore - sp.expandRowList = Array.from(sp.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; + sp.expandRowList = Array.from(sp.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; } sp.collapseAll = true; sp.setAttribute('disable', ''); @@ -729,7 +683,6 @@ export function spSystemTraceInitElement(sp: SpSystemTrace): void { sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector('tabpane-frequency-sample'); sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector('tabpane-counter-sample'); sp.rangeSelect = new RangeSelect(sp); - // @ts-ignore rightButton?.addEventListener('click', rightButtonOnClick(sp, rightStar)); rightStar?.addEventListener('click', rightStarOnClick(sp)); documentInitEvent(sp); @@ -745,190 +698,156 @@ export function spSystemTraceInitElement(sp: SpSystemTrace): void { smartEventSubscribe(sp); } -function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: unknown): void { +function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: any): void { if (findEntry) { - // @ts-ignore - if (findEntry.startTime > TraceRow.range!.endNS || findEntry.startTime + findEntry.dur < TraceRow.range!.startNS) { - // @ts-ignore - sp.moveRangeToLeft(findEntry.startTime!, findEntry.dur!); - } + sp.moveRangeToCenter(findEntry.startTime!, findEntry.dur!); sp.queryAllTraceRow().forEach((item) => { item.highlight = false; }); - // @ts-ignore if (findEntry.type === 'cpu') { findEntryTypeCpu(sp, findEntry); - // @ts-ignore } else if (findEntry.type === 'func') { findEntryTypeFunc(sp, findEntry); - // @ts-ignore } else if (findEntry.type === 'thread||process') { findEntryTypeThreadProcess(sp, findEntry); - // @ts-ignore } else if (findEntry.type === 'sdk') { findEntryTypeSdk(sp, findEntry); } - // @ts-ignore sp.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); } } +function setToNext(current: number, totalResults: number): number { + const index = (current + 1) % totalResults; + return index; +} + +function setToPrevious(current: number, totalResults: number): number { + let index = current - 1; + if (index < 0) { + index = totalResults - 1; + } + return index; +} + +function searchImp(structs: Array, needle: number, i: number, j:number): number { + if (i === j) return -1; + if (i + 1 === j) { + return needle >= structs[i].startTime ? i : -1; + } + const mid = Math.floor((j - i) / 2) + i; + const midValue = structs[mid].startTime; + if (needle < midValue) { + return searchImp(structs, needle, i, mid); + } else { + return searchImp(structs, needle, mid, j); + } +} + export function spSystemTraceShowStruct( sp: SpSystemTrace, previous: boolean, currentIndex: number, - structs: Array, + structs: Array, retargetIndex?: number ): number { if (structs.length === 0) { return 0; } let findIndex = spSystemTraceShowStructFindIndex(previous, currentIndex, structs, retargetIndex); - let findEntry: unknown; - if (findIndex >= 0) { - findEntry = structs[findIndex]; - } else { - if (previous) { - for (let i = structs.length - 1; i >= 0; i--) { - let it = structs[i]; - // @ts-ignore - if (it.startTime! + it.dur! < TraceRow.range!.startNS) { - findIndex = i; - break; - } - } - if (findIndex === -1) { - findIndex = structs.length - 1; - } - } else { - // @ts-ignore - findIndex = structs.findIndex((it) => it.startTime! > TraceRow.range!.endNS); - if (findIndex === -1) { - findIndex = 0; - } - } - findEntry = structs[findIndex]; - } + let findEntry: any; + findEntry = structs[findIndex]; moveRangeToCenterAndHighlight(sp, findEntry); return findIndex; } function spSystemTraceShowStructFindIndex( previous: boolean, currentIndex: number, - structs: Array, + structs: Array, retargetIndex: number | undefined ): number { + let findIndex = -1; + const totalResults = structs.length; const rangeStart = TraceRow.range!.startNS; const rangeEnd = TraceRow.range!.endNS; - if (rangeStart > SpSystemTrace.currentStartTime && !retargetIndex) { - SpSystemTrace.currentStartTime = rangeStart; + const currentStart = structs[currentIndex]?.startTime; + if (retargetIndex && retargetIndex > 0) { + currentIndex = retargetIndex; } - let findIndex = -1; - if (previous) { - if (retargetIndex) { - findIndex = retargetIndex - 1; - SpSystemTrace.retargetIndex = findIndex; + //不在时间区域内 + if (!retargetIndex && (currentIndex === -1 || currentStart < rangeStart || currentStart > rangeEnd)) { + const searchIndex = searchImp(structs, rangeStart, 0, totalResults); + if (previous) { + if (searchIndex === -1) { + findIndex = setToPrevious(currentIndex, totalResults); + } else { + findIndex = searchIndex; + } } else { - for (let i = structs.length - 1; i >= 0; i--) { - let it = structs[i]; - // @ts-ignore - if (i < currentIndex && it.startTime! >= rangeStart && it.startTime! + it.dur! <= rangeEnd) { - findIndex = i; - break; - } + if (searchIndex === -1) { + findIndex = setToNext(currentIndex, totalResults); + } else { + findIndex = searchIndex; } } } else { - if (currentIndex > 0) { - if (SpSystemTrace.currentStartTime > rangeStart) { - SpSystemTrace.currentStartTime = rangeStart; - if ( - // @ts-ignore - structs[currentIndex].startTime < rangeStart || - // @ts-ignore - structs[currentIndex].startTime! + structs[currentIndex].dur! > rangeEnd - ) { - currentIndex = -1; - } - } - if (SpSystemTrace.currentStartTime !== 0 && SpSystemTrace.currentStartTime < rangeStart) { - SpSystemTrace.currentStartTime = 0; - SpSystemTrace.retargetIndex = 0; - } + if (previous) { + findIndex = setToPrevious(currentIndex, totalResults); + } else { + findIndex = setToNext(currentIndex, totalResults); } - findIndex = structs.findIndex((it, idx) => { - // @ts-ignore - return idx > currentIndex && it.startTime! >= rangeStart && it.startTime! + it.dur! <= rangeEnd; - }); } return findIndex; } -function findEntryTypeCpu(sp: SpSystemTrace, findEntry: unknown): void { - // @ts-ignore +function findEntryTypeCpu(sp: SpSystemTrace, findEntry: any): void { CpuStruct.selectCpuStruct = findEntry; CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; - sp.queryAllTraceRow("trace-row[row-type='cpu-data']", (row): boolean => row.rowType === 'cpu-data').forEach( + sp.queryAllTraceRow(`trace-row[row-type='cpu-data']`, (row): boolean => row.rowType === 'cpu-data').forEach( (item): void => { - // @ts-ignore - if (item.rowId === `${findEntry.cpu}`) { + if (item.rowId === `${Utils.getDistributedRowId(findEntry.cpu)}`) { sp.rechargeCpuData( - // @ts-ignore - findEntry, - // @ts-ignore + findEntry, // @ts-ignore item.dataListCache.find((it) => it.startTime > findEntry.startTime) ); item.fixedList = [findEntry]; } - // @ts-ignore - item.highlight = item.rowId === `${findEntry.cpu}`; + item.highlight = item.rowId === `${Utils.getDistributedRowId(findEntry.cpu)}`; item.draw(true); } ); - // @ts-ignore sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true); sp.onClickHandler(TraceRow.ROW_TYPE_CPU); } -function findEntryTypeFunc(sp: SpSystemTrace, findEntry: unknown): void { +function findEntryTypeFunc(sp: SpSystemTrace, findEntry: any): void { sp.observerScrollHeightEnable = true; sp.scrollToActFunc( { - // @ts-ignore startTs: findEntry.startTime, - // @ts-ignore dur: findEntry.dur, - // @ts-ignore tid: findEntry.tid, - // @ts-ignore pid: findEntry.pid, - // @ts-ignore depth: findEntry.depth, - // @ts-ignore argsetid: findEntry.argsetid, - // @ts-ignore funName: findEntry.funName, - // @ts-ignore cookie: findEntry.cookie, + row_id: findEntry.rowId ? findEntry.rowId : null,//因异步trace分类出的rowId类型有三种,故新增row_id字段,该字段为异步方法的对应的rowId,支持搜索查询定位到该方法属于那个row,只有缓存的异步trace数据中含该字段 }, true ); } -function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: unknown): void { +function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: any): void { let threadProcessRow = sp.rowsEL?.querySelectorAll>('trace-row')[0]; if (threadProcessRow) { let filterRow = threadProcessRow.childrenList.filter( - // @ts-ignore - (row) => row.rowId === findEntry.rowId && row.rowId === findEntry.rowType + (row) => row.rowId === Utils.getDistributedRowId(findEntry.rowId) && row.rowId === findEntry.rowType )[0]; filterRow!.highlight = true; - // @ts-ignore - sp.closeAllExpandRows(findEntry.rowParentId); - // @ts-ignore + sp.closeAllExpandRows(Utils.getDistributedRowId(findEntry.rowParentId)); sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); let completeEntry = (): void => { sp.hoverStructNull(); sp.selectStructNull(); sp.wakeupListNull(); - // @ts-ignore sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); }; if (filterRow!.isComplete) { @@ -938,12 +857,10 @@ function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: unknown): void } } } -function findEntryTypeSdk(sp: SpSystemTrace, findEntry: unknown): void { - // @ts-ignore - let parentRow = sp.shadowRoot!.querySelector>("trace-row[row-type='sdk'][folder]"); +function findEntryTypeSdk(sp: SpSystemTrace, findEntry: any): void { + let parentRow = sp.shadowRoot!.querySelector>(`trace-row[row-type='sdk'][folder]`); if (parentRow) { let sdkRow = parentRow.childrenList.filter( - // @ts-ignore (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType )[0]; sdkRow!.highlight = true; @@ -951,16 +868,13 @@ function findEntryTypeSdk(sp: SpSystemTrace, findEntry: unknown): void { sp.hoverStructNull(); sp.selectStructNull(); sp.wakeupListNull(); - // @ts-ignore sp.onClickHandler(findEntry.rowType!); - // @ts-ignore sp.closeAllExpandRows(findEntry.rowParentId); - // @ts-ignore sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); } async function spSystemTraceInitBuffer( sp: SpSystemTrace, - param: { buf?: ArrayBuffer; Url?: string }, + param: { buf?: ArrayBuffer; Url?: string; buf2?: ArrayBuffer }, wasmConfigUri: string, progress: Function ): Promise<{ @@ -979,7 +893,13 @@ async function spSystemTraceInitBuffer( if (!status) { return { status: false, msg: msg }; } - SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap === undefined ? undefined : sdkConfigMap; + SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap; + if (param.buf2) { + let { status, msg } = await threadPool2.initSqlite(param.buf2, parseConfig, configJson, progress); + if (!status) { + return { status: false, msg: msg }; + } + } return null; } else { return null; @@ -1007,10 +927,11 @@ async function spSystemTraceInitUrl( } export async function spSystemTraceInit( sp: SpSystemTrace, - param: { buf?: ArrayBuffer; url?: string }, + param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string }, wasmConfigUri: string, - progress: Function -): Promise { + progress: Function, + isDistributed: boolean +): Promise { progress('Load database', 6); sp.rowsPaneEL!.scroll({ top: 0, left: 0 }); let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, progress); @@ -1021,10 +942,13 @@ export async function spSystemTraceInit( if (rsUrl) { return rsUrl; } - await sp.chartManager?.init(progress); + if (isDistributed) { + await sp.chartManager?.initDistributedChart(progress, param.fileName1 || 'Trace 1', param.fileName2 || 'Trace 2'); + } else { + await sp.chartManager?.init(progress); + } let rowId: string = ''; - // @ts-ignore - sp.rowsEL?.querySelectorAll>('trace-row').forEach((it) => { + sp.rowsEL?.querySelectorAll>('trace-row').forEach((it) => { if (it.name.includes('Ark Ts')) { rowId = it.rowId!; } @@ -1035,8 +959,7 @@ export async function spSystemTraceInit( progress('completed', 100); info('All TraceRow Data initialized'); sp.loadTraceCompleted = true; - // @ts-ignore - sp.rowsEL!.querySelectorAll>('trace-row').forEach((it) => { + sp.rowsEL!.querySelectorAll>('trace-row').forEach((it) => { if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) { it.addTemplateTypes('Ark Ts'); for (let child of it.childrenList) { @@ -1044,7 +967,7 @@ export async function spSystemTraceInit( } } if (it.folder) { - let offsetYTimeOut: unknown = undefined; + let offsetYTimeOut: any = undefined; it.addEventListener('expansion-change', expansionChangeHandler(sp, offsetYTimeOut)); } if (sp.loadTraceCompleted) { @@ -1053,28 +976,49 @@ export async function spSystemTraceInit( } sp.intersectionObserver?.observe(it); }); + // trace文件加载完毕,将动效json文件读取并存入缓存 + let funDetailUrl = `https://${window.location.host.split(':')[0]}:${ + window.location.port + }/application/doc/funDetail.json`; + var xhr = new XMLHttpRequest(); + // 创建XMLHttpRequest对象 + xhr.open('GET', funDetailUrl); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4 && xhr.status === 200) { + var content = xhr.responseText; + caches.open('/funDetail').then((cache) => { + let headers = new Headers(); + headers.append('Content-Type', 'application/json'); + return cache + .put( + '/funDetail', + new Response(content, { + status: 200, + headers, + }) + ) + .then(); + }); + } + }; + xhr.send(); // 发送请求 return { status: true, msg: 'success' }; } -function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: unknown): (event: unknown) => void { - return function (event: unknown) { +function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: any): (event: any) => void { + return function (event: any) { let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce((pre, cur) => pre + cur.clientHeight!, 0); let offset = sp.rowsPaneEL!.scrollHeight - max; sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset; JankStruct.delJankLineFlag = false; if (offsetYTimeOut) { - // @ts-ignore clearTimeout(offsetYTimeOut); } - // @ts-ignore if (event.detail.expansion) { offsetYTimeOut = setTimeout(() => { sp.linkNodes.forEach((linkNode) => { - JankStruct.selectJankStructList?.forEach((selectStruct: unknown) => { - // @ts-ignore + JankStruct.selectJankStructList?.forEach((selectStruct: any) => { if (event.detail.rowId === selectStruct.pid) { - // @ts-ignore JankStruct.selectJankStruct = selectStruct; - // @ts-ignore JankStruct.hoverJankStruct = selectStruct; } }); @@ -1154,10 +1098,8 @@ export function spSystemTraceParentRowSticky(sp: SpSystemTrace, deltaY: number): if (deltaY > 0) { // 从上往下划 const expandRowList = sp.visibleRows.filter((vr) => vr.expansion); - // @ts-ignore - expandRowList.forEach((vr: TraceRow) => { - // @ts-ignore - const visibleNotCollectList = vr.childrenList.filter((child: TraceRow) => !child.collect && !child.sleeping); + expandRowList.forEach((vr: TraceRow) => { + const visibleNotCollectList = vr.childrenList.filter((child: TraceRow) => !child.collect && !child.sleeping); vr.sticky = visibleNotCollectList.length > 0; }); } else if (deltaY < 0) { diff --git a/ide/src/trace/component/SpSystemTrace.line.ts b/ide/src/trace/component/SpSystemTrace.line.ts index b4c9bfc3176790fcbc0a6e16b00fb405666c879c..34a661b420e6c5f9b3e34bd179a1062586e31848 100644 --- a/ide/src/trace/component/SpSystemTrace.line.ts +++ b/ide/src/trace/component/SpSystemTrace.line.ts @@ -16,13 +16,17 @@ import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; import { SpSystemTrace } from './SpSystemTrace'; import { TraceRow } from './trace/base/TraceRow'; -import { LineType, ns2xByTimeShaft } from '../database/ui-worker/ProcedureWorkerCommon'; +import { LineType, PairPoint, ns2xByTimeShaft } from '../database/ui-worker/ProcedureWorkerCommon'; import { TabPaneTaskFrames } from './trace/sheet/task/TabPaneTaskFrames'; import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc'; import { queryBySelectExecute } from '../database/sql/ProcessThread.sql'; import { queryTaskPoolOtherRelationData, queryTaskPoolRelationData } from '../database/sql/Func.sql'; import { queryBySelectAllocationOrReturn } from '../database/sql/SqlLite.sql'; import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; +import { Utils } from './trace/base/Utils'; +import { TraceMode } from '../SpApplicationPublicFunc'; +import { BaseStruct } from '../bean/BaseStruct'; +import { getTimeString } from './trace/sheet/TabPaneCurrentSelection'; //@ts-ignore function collectionHasJank(jankRow: unknown, collectList: TraceRow[]): boolean { @@ -43,7 +47,7 @@ function setPoint( rowEL: unknown, isRight: boolean, business: string -): unknown { +): PairPoint { return { x: x, y: y, @@ -52,7 +56,80 @@ function setPoint( rowEL: rowEL!, isRight: isRight, business: business, - }; + } as PairPoint; +} + +function addPointHandle( + sp: SpSystemTrace, + sourceData: FuncStruct, + sourceThreadRow: TraceRow, + targetData: FuncStruct, + targetThreadRow: TraceRow, + lineType?:string +): void { + let sourceParentRow: TraceRow | null | undefined; + let targetParentRow: TraceRow | null | undefined; + if (Utils.currentTraceMode === TraceMode.DISTRIBUTED) { + sourceParentRow = sp.shadowRoot?.querySelector>( + `trace-row[row-id='${sourceData.pid}-${sourceData.traceId}'][row-type='process'][folder]` + ); + targetParentRow = sp.shadowRoot?.querySelector>( + `trace-row[row-id='${targetData.pid}-${targetData.traceId}'][row-type='process'][folder]` + ); + } else { + sourceParentRow = sp.shadowRoot?.querySelector>( + `trace-row[row-id='${sourceData.pid}'][row-type='process'][folder]` + ); + targetParentRow = sp.shadowRoot?.querySelector>( + `trace-row[row-id='${targetData.pid}'][row-type='process'][folder]` + ); + } + let [startY, startOffSetY, startRowEl, isThreadRow] = + getPointModel(sp, sourceThreadRow, sourceParentRow, sourceData, 0.9); + let [endY, endOffSetY, endRowEl] = + getPointModel(sp, targetThreadRow, targetParentRow, targetData, 0.1); + let startX = Math.floor(ns2xByTimeShaft(sourceData.ts || sourceData.startTs || 0, sp.timerShaftEL!)); + let endX = Math.floor(ns2xByTimeShaft(targetData.ts! || targetData.startTs!, sp.timerShaftEL!)); + const startPoint = setPoint(startX, startY, startOffSetY, sourceData.ts || sourceData.startTs || 0, startRowEl, true, 'distributed'); + const endPoint = setPoint(endX, endY, endOffSetY, targetData.ts! || targetData.startTs!, endRowEl, true, 'distributed'); + startPoint.rangeTime = `${getTimeString((targetData.ts || targetData.startTs! || 0) - (sourceData.ts || sourceData.startTs || 0))}`; + if (startPoint && endPoint) { + startPoint.lineType = endPoint.lineType = LineType.brokenLine; + startPoint.lineColor = endPoint.lineColor = '#ff0000'; + sp.addPointPair(startPoint, endPoint,lineType); + } +} + +function getPointModel( + sp: SpSystemTrace, + threadRow: TraceRow | null | undefined, + parentRow: TraceRow | null | undefined, + dataStruct: FuncStruct, + pointYHeight: number, +): [number, number, TraceRow, boolean] { + let pointY: number = 0; + let isThreadRow = false; + let pointRowEl: TraceRow | null | undefined; + let pointOffSetY: number = 0; + if (threadRow) { + pointY = threadRow?.translateY + 20 * (dataStruct.depth! + pointYHeight); + pointRowEl = threadRow; + pointOffSetY = 20 * (dataStruct.depth! + pointYHeight); + isThreadRow = true; + } else if (parentRow) { + if (!parentRow.expansion) { + pointY = parentRow?.translateY! + 4 * (dataStruct.depth! + 0.5); + pointRowEl = parentRow!; + pointOffSetY = 4 * (dataStruct.depth! + 0.5); + } + } else { + pointRowEl = sp.shadowRoot?.querySelector>( + `trace-row[row-id='trace-${dataStruct.traceId}'][row-type='trace-${dataStruct.traceId}'][folder]` + ); + pointY = pointRowEl?.translateY! + 4 * (dataStruct.depth! + 0.5); + pointOffSetY = 4 * (dataStruct.depth! + 0.5); + } + return [pointY, pointOffSetY, pointRowEl!, isThreadRow]; } function selectJankApp( @@ -67,10 +144,10 @@ function selectJankApp( //@ts-ignore let findJankEntry = endRowStruct!.dataListCache!.find( //@ts-ignore - (dat: unknown) => dat.name === data.name && dat.pid === data.pid + (dat: unknown) => `${dat.name}` === `${data.name}` && `${dat.pid}` === `${data.pid}` ); let tts = - findJankEntry.frame_type === 'frameTime' ? selectJankStruct.ts! : selectJankStruct.ts! + selectJankStruct.dur!; + findJankEntry.frameType === 'frameTime' ? selectJankStruct.ts! : selectJankStruct.ts! + selectJankStruct.dur!; let startParentRow: unknown; // startRow为子泳道,子泳道不存在,使用父泳道 if (startRow) { @@ -118,6 +195,7 @@ function selectJankApp( function findJankApp( endParentRow: unknown, sp: SpSystemTrace, + data: unknown, startRow: unknown, selectJankStruct: JankStruct, endRowStruct: unknown @@ -128,7 +206,7 @@ function findJankApp( //@ts-ignore (dat: unknown) => dat.name === data.name && dat.pid === data.pid ); - let tts = selectJankStruct.frame_type === 'frameTime' ? findJankEntry.ts : findJankEntry.ts! + findJankEntry.dur!; + let tts = selectJankStruct.frameType === 'frameTime' ? findJankEntry.ts : findJankEntry.ts! + findJankEntry.dur!; //@ts-ignore let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5); let endRowEl = endRowStruct; @@ -179,10 +257,10 @@ function addPointLink( //连线规则:frametimeline的头----app的头,app的尾----renderservice的头 let tts: number = 0; if (findJankEntry) { - if (selectJankStruct.frame_type === 'app') { + if (selectJankStruct.frameType === 'app') { selectJankApp(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct); } - if (findJankEntry.frame_type === 'app') { + if (findJankEntry.frameType === 'app') { //@ts-ignore findJankApp(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct); } @@ -190,9 +268,9 @@ function addPointLink( if (data.children.length >= 1) { let endP; //@ts-ignore - if (data.children[0].frame_type === 'frameTime') { + if (data.children[0].frameType === 'frameTime') { //@ts-ignore - endP = sp.shadowRoot?.querySelector>("trace-row[row-type='janks'][row-id='frameTime']"); + endP = sp.shadowRoot?.querySelector>(`trace-row[row-type='janks'][row-id='frameTime']`); } else { //@ts-ignore endP = sp.shadowRoot?.querySelector>( @@ -209,7 +287,7 @@ function addPointLink( function getEndStruct(data: unknown, sp: SpSystemTrace): unknown { let endRowStruct: unknown; //@ts-ignore - if (data.frame_type === 'frameTime') { + if (data.frameType === 'frameTime') { endRowStruct = sp.shadowRoot?.querySelector>( "trace-row[row-id='actual frameTime'][row-type='janks']" ); @@ -239,7 +317,7 @@ function drawJankLineEndParent( //泳道未展开的情况,查找endRowStruct if (!endRowStruct) { //@ts-ignore - if (data.frame_type === 'frameTime') { + if (data.frameType === 'frameTime') { //@ts-ignore endParentRow.childrenList.forEach((item: TraceRow) => { if (item.rowId === 'actual frameTime' && item.rowType === 'janks') { @@ -295,7 +373,7 @@ export function spSystemTraceDrawJankLine( return; } let selectRowId = 'actual frameTime'; - if (selectJankStruct.frame_type === 'frameTime') { + if (selectJankStruct.frameType === 'frameTime') { startRow = sp.shadowRoot?.querySelector>( `trace-row[row-id='${selectRowId}'][row-type='janks']` ); @@ -318,6 +396,62 @@ export function spSystemTraceDrawJankLine( } } +export function spSystemTraceDrawDistributedLine( + sp: SpSystemTrace, + sourceData: FuncStruct, + targetData: FuncStruct, + selectFuncStruct: FuncStruct, +): void { + let collectList = sp.favoriteChartListEL!.getAllCollectRows() as TraceRow[]; + if (!selectFuncStruct) { + return; + } + let sourceThreadRow; + let targetThreadRow; + let sourceRowId; + let targetRowId; + if (Utils.currentTraceMode === TraceMode.DISTRIBUTED) { + sourceRowId = `${sourceData.tid}-${sourceData.traceId}`; + targetRowId = `${targetData.tid}-${targetData.traceId}`; + sourceThreadRow = sp.shadowRoot?.querySelector( + `trace-row[row-id='${sourceRowId}'][row-type='func']` + ) as TraceRow; + targetThreadRow = sp.shadowRoot?.querySelector( + `trace-row[row-id='${targetRowId}'][row-type='func']` + ) as TraceRow; + } else { + sourceRowId = `${sourceData.tid}`; + targetRowId = `${targetData.tid}`; + sourceThreadRow = sp.shadowRoot?.querySelector( + `trace-row[row-id='${sourceData.tid}'][row-type='func']` + ) as TraceRow; + targetThreadRow = sp.shadowRoot?.querySelector( + `trace-row[row-id='${targetData.tid}'][row-type='func']` + ) as TraceRow; + } + if (!sourceThreadRow || !targetThreadRow) { + for (let collectChart of collectList) { + if ( + !sourceThreadRow && + (Utils.currentTraceMode !== TraceMode.DISTRIBUTED || collectChart.traceId === sourceData.traceId) && + collectChart.rowId === sourceRowId && + collectChart.rowType === 'func' + ) { + sourceThreadRow = collectChart; + } + if ( + !targetThreadRow && + (Utils.currentTraceMode !== TraceMode.DISTRIBUTED || collectChart.traceId === targetData.traceId) && + collectChart.rowId === targetRowId && + collectChart.rowType === 'func' + ) { + targetThreadRow = collectChart; + } + } + } + addPointHandle(sp, sourceData, sourceThreadRow, targetData, targetThreadRow,'distributedLine'); +} + function taskPoolOtherRelationData( selectRow: unknown, sp: SpSystemTrace, @@ -555,7 +689,7 @@ function jankPoint( let ts: number = 0; if (findJankEntry) { ts = selectThreadStruct.startTime! + selectThreadStruct.dur! / 2; - const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectThreadStruct); + const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow,selectThreadStruct.pid); const [endY, endRowEl, endOffSetY] = sp.calculateEndY(endParentRow, endRowStruct); sp.addPointPair( sp.makePoint( @@ -582,6 +716,45 @@ function jankPoint( } } +function junkBinder( + endRowStruct: any, + selectFuncStruct: FuncStruct, + startRow: any, + endParentRow: any, + sp: SpSystemTrace, + data: any +) { + let findJankEntry = endRowStruct!.fixedList[0]; + let ts: number = 0; + if (findJankEntry) { + ts = selectFuncStruct.startTs! + selectFuncStruct.dur! / 2; + const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectFuncStruct.pid,selectFuncStruct); + const [endY, endRowEl, endOffSetY] = sp.calculateEndY(endParentRow, endRowStruct, data); + sp.addPointPair( + sp.makePoint( + ns2xByTimeShaft(ts, sp.timerShaftEL!), + ts, + startY, + startRowEl!, + startOffSetY, + 'func', + LineType.straightLine, + selectFuncStruct.startTs == ts + ), + sp.makePoint( + ns2xByTimeShaft(findJankEntry.startTs!, sp.timerShaftEL!), + findJankEntry.startTs!, + endY, + endRowEl, + endOffSetY, + 'func', + LineType.straightLine, + true + ) + ); + } +} + export function spSystemTraceDrawThreadLine( sp: SpSystemTrace, endParentRow: unknown, @@ -617,3 +790,41 @@ export function spSystemTraceDrawThreadLine( } } } + +export function spSystemTraceDrawFuncLine( + sp: SpSystemTrace, + endParentRow: any, + selectFuncStruct: FuncStruct | undefined, + data: any, + binderTid:Number +): void { + let collectList = sp.favoriteChartListEL!.getCollectRows(); + if(selectFuncStruct === undefined || selectFuncStruct === null){ + return; + } + let selectRowId = selectFuncStruct?.tid?selectFuncStruct?.tid:binderTid.toString(); + let startRow = sp.shadowRoot?.querySelector>(`trace-row[row-id='${selectRowId}'][row-type='func']`) + // let startRow = sp.getStartRow(selectRowId, collectList); + if (!startRow) { + for (let collectChart of collectList) { + if (collectChart.rowId === selectRowId.toString() && collectChart.rowType === 'func') { + startRow = collectChart as TraceRow; + break; + } + } + } + if (endParentRow) { + endParentRow.expansion = true; + let endRowStruct: any = sp.shadowRoot?.querySelector>( + `trace-row[row-id='${data.tid}'][row-type='func']` + ); + if (!endRowStruct) { + endRowStruct = endParentRow.childrenList.find((item: TraceRow) => { + return item.rowId === `${data.tid}` && item.rowType === 'func'; + }); + } + if (endRowStruct) { + junkBinder(endRowStruct, selectFuncStruct, startRow, endParentRow, sp, data); + } + } +} diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index b42eec42aa8d054254c7826f79f0f8a4c71557b8..1dd3d91228b0ef6568bb7c1bd089a1d8682c4c10 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -16,7 +16,7 @@ import { BaseElement, element } from '../../base-ui/BaseElement'; import './trace/TimerShaftElement'; import './trace/base/TraceRow'; -import { threadPool } from '../database/SqlLite'; +import { threadPool, threadPool2 } from '../database/SqlLite'; import { TraceRow } from './trace/base/TraceRow'; import { TimerShaftElement } from './trace/TimerShaftElement'; import './trace/base/TraceSheet'; @@ -42,6 +42,8 @@ import { ns2xByTimeShaft, PairPoint, Rect, + prioClickHandlerFun, + drawThreadCurve, } from '../database/ui-worker/ProcedureWorkerCommon'; import { SpChartManager } from './chart/SpChartManager'; import { CpuStruct, WakeupBean } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; @@ -62,6 +64,7 @@ import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerD import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility'; import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility'; import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock'; +import { DmaFenceStruct } from '../database/ui-worker/ProcedureWorkerDmaFence'; import { Utils } from './trace/base/Utils'; import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq'; import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; @@ -106,6 +109,8 @@ import { spSystemTraceShowStruct, } from './SpSystemTrace.init'; import { + spSystemTraceDrawDistributedLine, + spSystemTraceDrawFuncLine, spSystemTraceDrawJankLine, spSystemTraceDrawTaskPollLine, spSystemTraceDrawThreadLine, @@ -124,6 +129,8 @@ import { SampleStruct } from '../database/ui-worker/ProcedureWorkerBpftrace'; import { readTraceFileBuffer } from '../SpApplicationPublicFunc'; import { PerfToolStruct } from '../database/ui-worker/ProcedureWorkerPerfTool'; import { BaseStruct } from '../bean/BaseStruct'; +import { GpuCounterStruct } from '../database/ui-worker/ProcedureWorkerGpuCounter'; +import { SpProcessChart } from './chart/SpProcessChart'; function dpr(): number { return window.devicePixelRatio || 1; @@ -213,7 +220,8 @@ export class SpSystemTrace extends BaseElement { _flagList: Array = []; static currentStartTime: number = 0; static retargetIndex: number = 0; - private prevScrollY: number = 0; + prevScrollY: number = 0; + focusTarget: string = ''; set snapshotFile(data: FileInfo) { this.snapshotFiles = data; @@ -265,27 +273,37 @@ export class SpSystemTrace extends BaseElement { }; } - addPointPair(startPoint: PairPoint, endPoint: PairPoint): void { - if (startPoint.rowEL.collect) { - if (this.timerShaftEL?._checkExpand) { - startPoint.rowEL.translateY = - startPoint.rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; + addPointPair(startPoint: PairPoint, endPoint: PairPoint, lineType?: string): void { + if(startPoint !== null && startPoint.rowEL !== null && endPoint !== null && endPoint.rowEL !== null){ + if (startPoint.rowEL.collect) { + if (this.timerShaftEL?._checkExpand) { + startPoint.rowEL.translateY = + startPoint.rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; + } else { + startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195; + } } else { - startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195; + startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; } - } else { - startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; - } - if (endPoint.rowEL.collect) { - endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195; - } else { - endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; + if (endPoint.rowEL.collect) { + endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195; + } else { + endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; + } + startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY; + endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY; + startPoint.backrowEL = startPoint.rowEL; + endPoint.backrowEL = endPoint.rowEL; + //判断是否是分布式连线,分布式连线需有rangeTime + if (!lineType) { + this.linkNodes.push([startPoint, endPoint]); + } else { + if (startPoint.rangeTime) { + this.linkNodes.push([startPoint, endPoint]); + } + } + this.refreshCanvas(true); } - startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY; - endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY; - startPoint.backrowEL = startPoint.rowEL; - endPoint.backrowEL = endPoint.rowEL; - this.linkNodes.push([startPoint, endPoint]); } clearPointPair(): void { @@ -294,6 +312,9 @@ export class SpSystemTrace extends BaseElement { removeLinkLinesByBusinessType(...businessTypes: string[]): void { this.linkNodes = this.linkNodes.filter((pointPair) => { + if (businessTypes.indexOf('distributed') >= 0) { + FuncStruct.selectLineFuncStruct = []; + } return businessTypes.indexOf(pointPair[0].business) <= -1; }); } @@ -376,6 +397,11 @@ export class SpSystemTrace extends BaseElement { if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) { event = 'DeliverInputEvent Func'; } + } else if (it.rowType === TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH) { + event = 'TouchEventDispatch'; + if (it.rowParentId === TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH) { + event = 'TouchEventDispatch Func'; + } } else { event = it.name; } @@ -547,7 +573,6 @@ export class SpSystemTrace extends BaseElement { TraceRow.range!.refresh = true; requestAnimationFrame(() => this.refreshCanvas(false)); }, 200); - requestAnimationFrame(() => this.refreshCanvas(false)); spSystemTraceParentRowSticky(this, deltaY); this.prevScrollY = currentScrollY; }; @@ -685,6 +710,58 @@ export class SpSystemTrace extends BaseElement { this.favoriteChartListEL!.clientHeight ); } + // draw prio curve + if ( + ThreadStruct.isClickPrio && + this.currentRow!.parentRowEl!.expansion && + ThreadStruct.selectThreadStruct && + ThreadStruct.contrast(ThreadStruct.selectThreadStruct, this.currentRow!.rowParentId, this.currentRow!.rowId) + ) { + let context: CanvasRenderingContext2D; + if (this.currentRow!.currentContext) { + context = this.currentRow!.currentContext; + } else { + context = this.currentRow!.collect ? this.canvasFavoritePanelCtx! : this.canvasPanelCtx!; + } + this.drawPrioCurve(context, this.currentRow!); + } + } + + // draw prio curve + drawPrioCurve(context: any, row: TraceRow) { + let curveDrawList: any = []; + let oldVal: number = -1; + let threadFilter = row.dataListCache.filter((it: any) => it.state === 'Running'); //筛选状态是Running的数据 + //计算每个点的坐标 + prioClickHandlerFun(ThreadStruct.prioCount, row, threadFilter, curveDrawList, oldVal); + //绘制曲线透明度设置1,根据计算的曲线坐标开始画图 + context.globalAlpha = 1; + context.beginPath(); + let x0, y0; + if (curveDrawList[0] && curveDrawList[0].frame) { + x0 = curveDrawList[0].frame.x; + y0 = curveDrawList[0].curveFloatY; + } + context!.moveTo(x0!, y0!); + if (SpSystemTrace.isKeyUp || curveDrawList.length < 90) { + for (let i = 0; i < curveDrawList.length - 1; i++) { + let re = curveDrawList[i]; + let nextRe = curveDrawList[i + 1]; + drawThreadCurve(context, re, nextRe); + } + context.closePath(); + } else if (!SpSystemTrace.isKeyUp && curveDrawList.length >= 90) { + let x, y; + if (curveDrawList[curveDrawList.length - 1] && curveDrawList[curveDrawList.length - 1].frame) { + x = curveDrawList[curveDrawList.length - 1].frame.x; + y = curveDrawList[curveDrawList.length - 1].curveFloatY; + } + context.lineWidth = 1; + context.strokeStyle = '#ffc90e'; + context.lineCap = 'round'; + context.lineTo(x, y); + context.stroke(); + } } documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev); @@ -736,26 +813,18 @@ export class SpSystemTrace extends BaseElement { setCurrentSlicesTime(): void { if (CpuStruct.selectCpuStruct) { - if (CpuStruct.selectCpuStruct.startTime && CpuStruct.selectCpuStruct.dur) { - this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime; - this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime + CpuStruct.selectCpuStruct.dur; - } + this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime; + this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime! + CpuStruct.selectCpuStruct.dur!; } else if (ThreadStruct.selectThreadStruct) { - if (ThreadStruct.selectThreadStruct.startTime && ThreadStruct.selectThreadStruct.dur) { - this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime; - this.currentSlicesTime.endTime = - ThreadStruct.selectThreadStruct.startTime + ThreadStruct.selectThreadStruct.dur; - } + this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime; + this.currentSlicesTime.endTime = + ThreadStruct.selectThreadStruct.startTime! + ThreadStruct.selectThreadStruct.dur!; } else if (FuncStruct.selectFuncStruct) { - if (FuncStruct.selectFuncStruct.startTs && FuncStruct.selectFuncStruct.dur) { - this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs; - this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs + FuncStruct.selectFuncStruct.dur; - } + this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs; + this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs! + FuncStruct.selectFuncStruct.dur!; } else if (IrqStruct.selectIrqStruct) { - if (IrqStruct.selectIrqStruct.startNS && IrqStruct.selectIrqStruct.dur) { - this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS; - this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS + IrqStruct.selectIrqStruct.dur; - } + this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS; + this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS! + IrqStruct.selectIrqStruct.dur!; } else if (TraceRow.rangeSelectObject) { this.currentRow = undefined; if (TraceRow.rangeSelectObject.startNS && TraceRow.rangeSelectObject.endNS) { @@ -763,16 +832,35 @@ export class SpSystemTrace extends BaseElement { this.currentSlicesTime.endTime = TraceRow.rangeSelectObject.endNS; } } else if (JankStruct.selectJankStruct) { - if (JankStruct.selectJankStruct.ts && JankStruct.selectJankStruct.dur) { - this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts; - this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts + JankStruct.selectJankStruct.dur; - } + this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts; + this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts! + JankStruct.selectJankStruct.dur!; } else if (SampleStruct.selectSampleStruct) { if (SampleStruct.selectSampleStruct.begin && SampleStruct.selectSampleStruct.end) { this.currentSlicesTime.startTime = SampleStruct.selectSampleStruct.begin - SampleStruct.selectSampleStruct.startTs!; this.currentSlicesTime.endTime = SampleStruct.selectSampleStruct.end - SampleStruct.selectSampleStruct.startTs!; } + } else if (GpuCounterStruct.selectGpuCounterStruct) { + this.currentSlicesTime.startTime = + GpuCounterStruct.selectGpuCounterStruct.startNS! - GpuCounterStruct.selectGpuCounterStruct.startTime!; + this.currentSlicesTime.endTime = + GpuCounterStruct.selectGpuCounterStruct.startNS! + + GpuCounterStruct.selectGpuCounterStruct.dur! - + GpuCounterStruct.selectGpuCounterStruct.startTime!; + } else if (AppStartupStruct.selectStartupStruct) { + this.currentSlicesTime.startTime = AppStartupStruct.selectStartupStruct.startTs; + this.currentSlicesTime.endTime = AppStartupStruct.selectStartupStruct.startTs! + AppStartupStruct.selectStartupStruct.dur!; + } else if (AllAppStartupStruct.selectStartupStruct) { + this.currentSlicesTime.startTime = AllAppStartupStruct.selectStartupStruct.startTs; + this.currentSlicesTime.endTime = AllAppStartupStruct.selectStartupStruct.startTs! + AllAppStartupStruct.selectStartupStruct.dur!; + } else if (PerfToolStruct.selectPerfToolStruct) { + this.currentSlicesTime.startTime = PerfToolStruct.selectPerfToolStruct.startTs; + this.currentSlicesTime.endTime = PerfToolStruct.selectPerfToolStruct.startTs! + PerfToolStruct.selectPerfToolStruct.dur!; + } else if(DmaFenceStruct.selectDmaFenceStruct){ + if (DmaFenceStruct.selectDmaFenceStruct.startTime && DmaFenceStruct.selectDmaFenceStruct.dur) { + this.currentSlicesTime.startTime = DmaFenceStruct.selectDmaFenceStruct.startTime; + this.currentSlicesTime.endTime = DmaFenceStruct.selectDmaFenceStruct.startTime + DmaFenceStruct.selectDmaFenceStruct.dur; + } } else { this.currentSlicesTime.startTime = 0; this.currentSlicesTime.endTime = 0; @@ -790,26 +878,39 @@ export class SpSystemTrace extends BaseElement { AppStartupStruct.selectStartupStruct || SoStruct.selectSoStruct || SampleStruct.selectSampleStruct || + GpuCounterStruct.selectGpuCounterStruct || AllAppStartupStruct.selectStartupStruct || FrameAnimationStruct.selectFrameAnimationStruct || - JsCpuProfilerStruct.selectJsCpuProfilerStruct; + JsCpuProfilerStruct.selectJsCpuProfilerStruct || + PerfToolStruct.selectPerfToolStruct || + DmaFenceStruct.selectDmaFenceStruct; this.calculateSlicesTime(selectedStruct, shiftKey); return this.slicestime; }; - private calculateSlicesTime(selectedStruct: unknown, shiftKey: boolean): void { - if (selectedStruct) { - let startTs = 0; // @ts-ignore - if (selectedStruct.begin && selectedStruct.end) { + private calculateSlicesTime(selected: unknown, shiftKey: boolean): void { + if (selected) { + let startTs = 0; + // @ts-ignore + if (selected.begin && selected.end) { + // @ts-ignore + startTs = selected.begin - selected.startTs; // @ts-ignore - startTs = selectedStruct.begin - selectedStruct.startTs; // @ts-ignore - let end = selectedStruct.end - selectedStruct.startTs; + let end = selected.end - selected.startTs; + this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey); + // @ts-ignore + } else if (selected.startNS && selected.dur) { + // @ts-ignore + startTs = selected.startNS - selected.startTime; + // @ts-ignore + let end = selected.startNS + selected.dur - selected.startTime; this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey); } else { - startTs = // @ts-ignore - selectedStruct.startTs || selectedStruct.startTime || selectedStruct.startNS || selectedStruct.ts || 0; // @ts-ignore - let dur = selectedStruct.dur || selectedStruct.totalTime || selectedStruct.endNS - selectedStruct.startNS || 0; + // @ts-ignore + startTs = selected.startTs || selected.startTime || selected.startNS || selected.ts || 0; + // @ts-ignore + let dur = selected.dur || selected.totalTime || selected.endNS - selected.startNS || 0; this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey); } } else { @@ -839,6 +940,7 @@ export class SpSystemTrace extends BaseElement { }) ); } else { + if(this.focusTarget === ''){ this.dispatchEvent( new CustomEvent('trace-next-data', { detail: { down: true }, @@ -846,6 +948,7 @@ export class SpSystemTrace extends BaseElement { }) ); } + } } }; @@ -1071,6 +1174,8 @@ export class SpSystemTrace extends BaseElement { HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined; SampleStruct.hoverSampleStruct = undefined; PerfToolStruct.hoverPerfToolStruct = undefined; + GpuCounterStruct.hoverGpuCounterStruct = undefined; + DmaFenceStruct.hoverDmaFenceStruct = undefined;//清空hover slice this.tipEL!.style.display = 'none'; return this; } @@ -1080,6 +1185,7 @@ export class SpSystemTrace extends BaseElement { CpuStruct.wakeupBean = null; CpuFreqStruct.selectCpuFreqStruct = undefined; ThreadStruct.selectThreadStruct = undefined; + ThreadStruct.isClickPrio = false; FuncStruct.selectFuncStruct = undefined; SpHiPerf.selectCpuStruct = undefined; CpuStateStruct.selectStateStruct = undefined; @@ -1102,6 +1208,8 @@ export class SpSystemTrace extends BaseElement { HitchTimeStruct.selectHitchTimeStruct = undefined; SampleStruct.selectSampleStruct = undefined; PerfToolStruct.selectPerfToolStruct = undefined; + GpuCounterStruct.selectGpuCounterStruct = undefined; + DmaFenceStruct.selectDmaFenceStruct = undefined;//清空选中slice return this; } @@ -1129,8 +1237,9 @@ export class SpSystemTrace extends BaseElement { if (!SportRuler.isMouseInSportRuler) { this.traceSheetEL?.setMode('hidden'); } - this.removeLinkLinesByBusinessType('task', 'thread'); - this.refreshCanvas(true); + this.removeLinkLinesByBusinessType('task', 'thread', 'func'); + this.removeLinkLinesByBusinessType('task', 'thread', 'distributed'); + this.refreshCanvas(true, 'click empty'); JankStruct.delJankLineFlag = true; } @@ -1149,6 +1258,11 @@ export class SpSystemTrace extends BaseElement { TraceRow.ROW_TYPE_SAMPLE, (): boolean => SampleStruct.hoverSampleStruct !== null && SampleStruct.hoverSampleStruct !== undefined, ], + [ + TraceRow.ROW_TYPE_GPU_COUNTER, + (): boolean => + GpuCounterStruct.hoverGpuCounterStruct !== null && GpuCounterStruct.hoverGpuCounterStruct !== undefined, + ], [ TraceRow.ROW_TYPE_CPU_FREQ, (): boolean => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined, @@ -1269,9 +1383,10 @@ export class SpSystemTrace extends BaseElement { (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, ], ]); + // @ts-ignore onClickHandler(clickRowType: string, row?: TraceRow, entry?: unknown): void { - spSystemTraceOnClickHandler(this, clickRowType, row, entry); + spSystemTraceOnClickHandler(this, clickRowType, row as TraceRow, entry); } makePoint( @@ -1308,10 +1423,22 @@ export class SpSystemTrace extends BaseElement { spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data, isBinderClick); } + drawDistributedLine( + sourceData: FuncStruct, + targetData: FuncStruct, + selectFuncStruct: FuncStruct, + ): void { + spSystemTraceDrawDistributedLine(this, sourceData, targetData, selectFuncStruct); + } + drawThreadLine(endParentRow: unknown, selectThreadStruct: ThreadStruct | undefined, data: unknown): void { spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data); } + drawFuncLine(endParentRow: any, selectFuncStruct: FuncStruct | undefined, data: any, binderTid: Number): void { + spSystemTraceDrawFuncLine(this, endParentRow, selectFuncStruct, data, binderTid); + } + getStartRow(selectRowId: number | undefined, collectList: unknown[]): unknown { let startRow = this.shadowRoot?.querySelector>( `trace-row[row-id='${selectRowId}'][row-type='thread']` @@ -1329,34 +1456,31 @@ export class SpSystemTrace extends BaseElement { return startRow; } - calculateStartY(startRow: unknown, selectThreadStruct: ThreadStruct): [number, unknown, number] { - // @ts-ignore - let startY = startRow!.translateY!; + calculateStartY(startRow: any, pid: number | undefined, selectFuncStruct?: FuncStruct): [number, any, number] { + let startY = startRow ? startRow!.translateY! : 0; let startRowEl = startRow; - let startOffSetY = 20 * 0.5; - const startParentRow = this.shadowRoot?.querySelector>( // @ts-ignore - `trace-row[row-id='${startRow.rowParentId}'][folder]` + let startOffSetY = selectFuncStruct ? 20 * (0.5 + Number(selectFuncStruct.depth)) : 20 * 0.5; + const startParentRow = startRow ? this.shadowRoot?.querySelector>(`trace-row[row-id='${startRow.rowParentId}'][folder]`) : this.shadowRoot?.querySelector>( + `trace-row[row-id='${pid}'][folder]` ); const expansionFlag = this.collectionHasThread(startRow); if (startParentRow && !startParentRow.expansion && expansionFlag) { startY = startParentRow.translateY!; startRowEl = startParentRow; - startOffSetY = 10 * 0.5; + startOffSetY = selectFuncStruct ? 10 * (0.5 + Number(selectFuncStruct.depth)) : 10 * 0.5; } return [startY, startRowEl, startOffSetY]; } - calculateEndY(endParentRow: unknown, endRowStruct: unknown): [number, unknown, number] { - // @ts-ignore + calculateEndY(endParentRow: any, endRowStruct: any, data?: any): [number, any, number] { let endY = endRowStruct.translateY!; let endRowEl = endRowStruct; - let endOffSetY = 20 * 0.5; - const expansionFlag = this.collectionHasThread(endRowStruct); // @ts-ignore + let endOffSetY = data ? 20 * (0.5 + Number(data.depth)) : 20 * 0.5; + const expansionFlag = this.collectionHasThread(endRowStruct); if (!endParentRow.expansion && expansionFlag) { - // @ts-ignore endY = endParentRow.translateY!; endRowEl = endParentRow; - endOffSetY = 10 * 0.5; + endOffSetY = data ? 10 * (0.5 + Number(data.depth)) : 10 * 0.5; } return [endY, endRowEl, endOffSetY]; } @@ -1365,7 +1489,7 @@ export class SpSystemTrace extends BaseElement { const collectList = this.favoriteChartListEL!.getCollectRows(); for (let item of collectList!) { // @ts-ignore - if (item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) { + if (threadRow && item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) { return false; } } @@ -1438,8 +1562,10 @@ export class SpSystemTrace extends BaseElement { }), scrollTop: this.rowsEL!.scrollTop, favoriteScrollTop: this.favoriteChartListEL!.scrollTop, + drawFlag: this.timerShaftEL!.sportRuler!.flagList,//下载时存旗帜的信息 + markFlag: this.timerShaftEL!.sportRuler!.slicesTimeList,//下载时存M和shiftM的信息 }); - this.downloadRecordFile(data).then(() => {}); + this.downloadRecordFile(data).then(() => { }); } }); } @@ -1473,35 +1599,15 @@ export class SpSystemTrace extends BaseElement { this.currentCollectGroup = '2'; this.restoreRecordCollectRows(record.G2); } - if (record.expand) { - let expandRows = // @ts-ignore - Array.from(this.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; - let expands: Array = record.expand; - //关闭不在记录中的父泳道 - for (let expandRow of expandRows) { - if ( - !expands.includes( - (it: unknown) => - // @ts-ignore - it.id === expandRow.rowId && it.name === expandRow.name && it.type === expandRow.rowType - ) - ) { - expandRow.expansion = false; - } - } - //展开记录的泳道 - for (let it of record.expand) { - // @ts-ignore - let traceRow = this.rowsEL!.querySelector>( - `trace-row[folder][row-id='${it.id}'][row-type='${it.type}']` - ); - if (traceRow && !traceRow.expansion) { - traceRow.expansion = true; - } - } - } + this.restoreRecordExpandAndTimeRange(record); this.currentCollectGroup = currentGroup; - this.timerShaftEL?.setRangeNS(record.leftNS, record.rightNS); + if (record.drawFlag !== undefined) { + this.timerShaftEL!.sportRuler!.flagList = record.drawFlag;//获取下载时存的旗帜信息 + this.selectFlag = this.timerShaftEL!.sportRuler!.flagList.find((it) => it.selected);//绘制被选中旗帜对应的线 + } + if (record.markFlag !== undefined) { + this.timerShaftEL!.sportRuler!.slicesTimeList = record.markFlag;//获取下载时存的M键信息 + } TraceRow.range!.refresh = true; this.refreshCanvas(true); this.restoreRecordScrollTop(record.scrollTop, record.favoriteScrollTop); @@ -1509,6 +1615,41 @@ export class SpSystemTrace extends BaseElement { }); } + private restoreRecordExpandAndTimeRange(record: unknown): void { + // @ts-ignore + if (record.expand) { + let expandRows = // @ts-ignore + Array.from(this.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; + // @ts-ignore + let expands: Array = record.expand; + //关闭不在记录中的父泳道 + for (let expandRow of expandRows) { + if ( + !expands.includes( + (it: unknown) => + // @ts-ignore + it.id === expandRow.rowId && it.name === expandRow.name && it.type === expandRow.rowType + ) + ) { + expandRow.expansion = false; + } + } + //展开记录的泳道 + // @ts-ignore + for (let it of record.expand) { + // @ts-ignore + let traceRow = this.rowsEL!.querySelector>( + `trace-row[folder][row-id='${it.id}'][row-type='${it.type}']` + ); + if (traceRow && !traceRow.expansion) { + traceRow.expansion = true; + } + } + } + // @ts-ignore + this.timerShaftEL?.setRangeNS(record.leftNS, record.rightNS); + } + private restoreRecordScrollTop(mainScrollTop: number, favoriteScrollTop: number): void { if (mainScrollTop && mainScrollTop > 0) { this.rowsPaneEL!.scroll({ @@ -1675,9 +1816,11 @@ export class SpSystemTrace extends BaseElement { } scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void { + let id = Utils.getDistributedRowId(rowId); + let parentId = Utils.getDistributedRowId(rowParentId); let traceRow = // @ts-ignore - this.rowsEL!.querySelector>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) || - this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType); + this.rowsEL!.querySelector>(`trace-row[row-id='${id}'][row-type='${rowType}']`) || + this.favoriteChartListEL!.getCollectRow((row) => row.rowId === id && row.rowType === rowType); if (traceRow?.collect) { this.favoriteChartListEL!.scroll({ top: @@ -1689,7 +1832,7 @@ export class SpSystemTrace extends BaseElement { }); } else { // @ts-ignore - let row = this.rowsEL!.querySelector>(`trace-row[row-id='${rowParentId}'][folder]`); + let row = this.rowsEL!.querySelector>(`trace-row[row-id='${parentId}'][folder]`); if (row && !row.expansion) { row.expansion = true; } @@ -1709,7 +1852,7 @@ export class SpSystemTrace extends BaseElement { this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType); if (rootRow && rootRow!.collect) { this.favoriteAreaSearchHandler(rootRow); - rootRow.expandFunc(); + rootRow.expandFunc(rootRow, this); if (!this.isInViewport(rootRow)) { setTimeout(() => { rootRow!.scrollIntoView({ behavior: 'smooth' }); @@ -1722,7 +1865,7 @@ export class SpSystemTrace extends BaseElement { row.expansion = true; } if (rootRow) { - rootRow.expandFunc(); + rootRow.expandFunc(rootRow, this); } setTimeout(() => { rootRow!.scrollIntoView({ behavior: 'smooth', block: 'center' }); @@ -1742,11 +1885,13 @@ export class SpSystemTrace extends BaseElement { } scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void { - let condition = `trace-row[row-id='${rowId}'][row-type='${rowType}'][row-parent-id='${rowParentId}']`; + let id = Utils.getDistributedRowId(rowId); + let parentId = Utils.getDistributedRowId(rowParentId); + let condition = `trace-row[row-id='${id}'][row-type='${rowType}'][row-parent-id='${parentId}']`; let rootRow = // @ts-ignore this.rowsEL!.querySelector>(condition) || this.favoriteChartListEL!.getCollectRow((row) => { - return row.rowId === rowId && row.rowType === rowType && row.rowParentId === rowParentId; + return row.rowId === id && row.rowType === rowType && row.rowParentId === parentId; }); if (rootRow?.collect) { this.favoriteAreaSearchHandler(rootRow); @@ -1812,8 +1957,9 @@ export class SpSystemTrace extends BaseElement { this.wakeupListNull(); this.traceSheetEL?.setMode('hidden'); this.removeLinkLinesByBusinessType('janks'); + this.removeLinkLinesByBusinessType('distributed'); TraceRow.range!.refresh = true; - this.refreshCanvas(false); + this.refreshCanvas(false, 'slice mark event'); } loadDatabaseUrl( @@ -1822,7 +1968,7 @@ export class SpSystemTrace extends BaseElement { complete?: ((res: { status: boolean; msg: string }) => void) | undefined ): void { this.observerScrollHeightEnable = false; - this.init({ url: url }, '', progress).then((res) => { + this.init({ url: url }, '', progress, false).then((res) => { if (complete) { // @ts-ignore complete(res); @@ -1837,10 +1983,19 @@ export class SpSystemTrace extends BaseElement { buf: ArrayBuffer, thirdPartyWasmConfigUrl: string, progress: (name: string, percent: number) => void, - complete?: ((res: { status: boolean; msg: string }) => void) | undefined + isDistributed: boolean, + complete?: ((res: { status: boolean; msg: string }) => void) | undefined, + buf2?: ArrayBuffer, + fileName1?: string, + fileName2?: string ): void { this.observerScrollHeightEnable = false; - this.init({ buf }, thirdPartyWasmConfigUrl, progress).then((res) => { + if (isDistributed) { + this.timerShaftEL?.setAttribute('distributed', ''); + } else { + this.timerShaftEL?.removeAttribute('distributed'); + } + this.init({ buf, buf2, fileName1, fileName2 }, thirdPartyWasmConfigUrl, progress, isDistributed).then((res) => { // @ts-ignore this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it)); if (complete) { @@ -1874,6 +2029,29 @@ export class SpSystemTrace extends BaseElement { }); }); }; + + loadGpuCounter = async (ev: File) => { + this.observerScrollHeightEnable = false; + await this.initGpuCounter(ev); + this.rowsEL?.querySelectorAll('trace-row').forEach((it: any) => this.observer.observe(it)); + window.publish(window.SmartEvent.UI.MouseEventEnable, { + mouseEnable: true, + }); + }; + + initGpuCounter = async (ev: File) => { + this.rowsPaneEL!.scroll({ + top: 0, + left: 0, + }); + this.chartManager?.initGpuCounter(ev).then(() => { + this.loadTraceCompleted = true; + this.rowsEL!.querySelectorAll>('trace-row').forEach((it) => { + this.intersectionObserver?.observe(it); + }); + }); + }; + // @ts-ignore queryAllTraceRow(selectors?: string, filter?: (row: TraceRow) => boolean): TraceRow[] { return [ @@ -1912,20 +2090,52 @@ export class SpSystemTrace extends BaseElement { async searchCPU(query: string): Promise> { let pidArr: Array = []; let tidArr: Array = []; - for (let key of Utils.PROCESS_MAP.keys()) { - if (`${key}`.includes(query) || (Utils.PROCESS_MAP.get(key) || '').includes(query)) { + let processMap = Utils.getInstance().getProcessMap(Utils.currentSelectTrace); + let threadMap = Utils.getInstance().getThreadMap(Utils.currentSelectTrace); + for (let key of processMap.keys()) { + if (`${key}`.includes(query) || (processMap.get(key) || '').includes(query)) { pidArr.push(key); } } - for (let key of Utils.THREAD_MAP.keys()) { - if (`${key}`.includes(query) || (Utils.THREAD_MAP.get(key) || '').includes(query)) { + for (let key of threadMap.keys()) { + if (`${key}`.includes(query) || (threadMap.get(key) || '').includes(query)) { tidArr.push(key); } } - return await searchCpuDataSender(pidArr, tidArr); + return await searchCpuDataSender(pidArr, tidArr, Utils.currentSelectTrace); + } + //根据seach的内容匹配异步缓存数据中那些符合条件 + seachAsyncFunc(query: string) { + let asyncFuncArr: Array = []; + let strNew = (str: any) => { + const specialChars = { + "^": '\\^', + "$": '\\$', + ".": '\\.', + "*": '\\*', + "+": '\\+', + "?": '\\?', + "-": '\\-', + "|": '\\|', + "(": '\\(', + ")": '\\)', + "[": '\\[', + "]": '\\]', + "{": '\\{', + "}": '\\}', + }; + return str.replace(/[$\^.*+?|()\[\]{}-]/g, (match: string) => specialChars[match as keyof typeof specialChars]); // 类型断言 + } + let regex = new RegExp(strNew(query), 'i') + SpProcessChart.asyncFuncCache.forEach((item: any) => { + if (regex.test(item.funName)) { + asyncFuncArr.push(item) + } + }) + return asyncFuncArr } - async searchFunction(cpuList: Array, query: string): Promise> { + async searchFunction(cpuList: Array, asynList: Array, query: string): Promise> { let processList: Array = []; let traceRow = // @ts-ignore this.shadowRoot!.querySelector>('trace-row[scene]') || @@ -1934,7 +2144,11 @@ export class SpSystemTrace extends BaseElement { // @ts-ignore this.shadowRoot!.querySelectorAll>("trace-row[row-type='process'][scene]").forEach( (row): void => { - processList.push(row.rowId!); + let rowId = row.rowId; + if (rowId && rowId.includes('-')){ + rowId = rowId.split('-')[0]; + } + processList.push(rowId as string); } ); if (query.includes('_')) { @@ -1944,17 +2158,37 @@ export class SpSystemTrace extends BaseElement { query = query.replace(/%/g, '\\%'); } let list = await querySceneSearchFunc(query, processList); + cpuList = cpuList.concat(asynList); cpuList = cpuList.concat(list); // @ts-ignore cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); return cpuList; } else { let list = await querySearchFunc(query); + cpuList = cpuList.concat(asynList); cpuList = cpuList.concat(list); // @ts-ignore cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0)); return cpuList; } } + searchTargetTraceHandler(): void { + if (Utils.currentSelectTrace) { + let traceFolder1 = this.shadowRoot!.querySelector>(`trace-row[row-id='trace-1']`); + let traceFolder2 = this.shadowRoot!.querySelector>(`trace-row[row-id='trace-2']`); + if (Utils.currentSelectTrace === '1') { + if (traceFolder2?.expansion) { + traceFolder2!.expansion = false; + } + traceFolder1!.expansion = true; + } else { + if (traceFolder1?.expansion) { + traceFolder1!.expansion = false; + } + traceFolder2!.expansion = true; + } + } + } + searchSdk(dataList: Array, query: string): Array { let traceRow = // @ts-ignore this.shadowRoot!.querySelector>('trace-row[scene]') || @@ -2006,7 +2240,13 @@ export class SpSystemTrace extends BaseElement { if (FuncStruct.funcSelect) { this.onClickHandler(TraceRow.ROW_TYPE_FUNC, undefined, entry); } // @ts-ignore - this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, 'func', true, entry.depth || 0); + this.scrollToDepth( + `${funcRowID}`, // @ts-ignore + `${Utils.getDistributedRowId(funcStract.pid)}`, + 'func', + true, // @ts-ignore + entry.depth || 0 + ); FuncStruct.funcSelect = true; } }; @@ -2019,8 +2259,11 @@ export class SpSystemTrace extends BaseElement { funcStract.dur = (TraceRow.range?.totalNS || 0) - (funcStract.startTs || 0); // @ts-ignore funcStract.flag = 'Did not end'; } - } // @ts-ignore - let funcRowID = !funcStract.cookie ? `${funcStract.tid}` : `${funcStract.funName}-${funcStract.pid}`; + } + //@ts-ignore + let funId = funcStract.row_id === null ? `${funcStract.funName}-${funcStract.pid}` : funcStract.row_id; + //@ts-ignore + let funcRowID = (funcStract.cookie === null || funcStract.cookie === undefined) ? `${Utils.getDistributedRowId(funcStract.tid)}` : funId; let targetRow = this.favoriteChartListEL?.getCollectRow((row) => { return row.rowId === funcRowID && row.rowType === 'func'; }); @@ -2030,8 +2273,11 @@ export class SpSystemTrace extends BaseElement { //如果目标泳道图在收藏上面,则跳转至收藏 this.toTargetDepth(funcStract, funcRowID, funcStract); return; - } // @ts-ignore - let parentRow = this.rowsEL!.querySelector>(`trace-row[row-id='${funcStract.pid}'][folder]`); + } + let parentRow = this.rowsEL!.querySelector>( + // @ts-ignore + `trace-row[row-id='${Utils.getDistributedRowId(funcStract.pid)}'][folder]` + ); if (!parentRow) { return; } @@ -2046,8 +2292,10 @@ export class SpSystemTrace extends BaseElement { } } filterRow.fixedList = [funcStract]; - filterRow!.highlight = highlight; // @ts-ignore - let row = this.rowsEL!.querySelector>(`trace-row[row-id='${funcStract.pid}'][folder]`); + filterRow!.highlight = highlight; + let row = this.rowsEL!.querySelector>( // @ts-ignore + `trace-row[row-id='${Utils.getDistributedRowId(funcStract.pid)}'][folder]` + ); this.currentRow = row; if (row && !row.expansion) { row.expansion = true; @@ -2061,7 +2309,8 @@ export class SpSystemTrace extends BaseElement { // @ts-ignore this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'thread', false); // @ts-ignore this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true); - filterRow!.onComplete = completeEntry; + // filterRow!.onComplete = completeEntry; + completeEntry(); } } @@ -2086,7 +2335,7 @@ export class SpSystemTrace extends BaseElement { } this.timerShaftEL?.setRangeNS(leftNs, rightNs); TraceRow.range!.refresh = true; - this.refreshCanvas(true); + this.refreshCanvas(true, 'move range to left'); } moveRangeToCenter(startTime: number, dur: number): void { @@ -2101,13 +2350,13 @@ export class SpSystemTrace extends BaseElement { } this.timerShaftEL?.setRangeNS(leftNs, rightNs); TraceRow.range!.refresh = true; - this.refreshCanvas(true); + this.refreshCanvas(true, 'move range to center'); } rechargeCpuData(it: CpuStruct, next: CpuStruct | undefined): void { - let p = Utils.PROCESS_MAP.get(it.processId!); - let t = Utils.THREAD_MAP.get(it.tid!); - let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`); + let p = Utils.getInstance().getProcessMap().get(it.processId!); + let t = Utils.getInstance().getThreadMap().get(it.tid!); + let slice = Utils.getInstance().getSchedSliceMap().get(`${it.id}-${it.startTime}`); if (slice) { it.end_state = slice.endState; it.priority = slice.priority; @@ -2115,7 +2364,7 @@ export class SpSystemTrace extends BaseElement { it.processName = p; it.processCmdLine = p; it.name = t; - it.type = 'thread'; + it.type = 'cpu'; if (next) { if (it.startTime! + it.dur! > next!.startTime! || it.dur === -1 || it.dur === null || it.dur === undefined) { it.dur = next!.startTime! - it.startTime!; @@ -2167,9 +2416,12 @@ export class SpSystemTrace extends BaseElement { procedurePool.clearCache(); Utils.clearData(); InitAnalysis.getInstance().isInitAnalysis = true; - procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: unknown) => {}); + procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: unknown) => { }); if (threadPool) { - threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => {}); + threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => { }); + } + if (threadPool2) { + threadPool2.submitProto(QueryEnum.ClearMemoryCache, {}, (res: any, len: number): void => { }); } this.times.clear(); resetVSync(); @@ -2178,11 +2430,12 @@ export class SpSystemTrace extends BaseElement { } init = async ( - param: { buf?: ArrayBuffer; url?: string }, + param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string }, wasmConfigUri: string, - progress: Function + progress: Function, + isDistributed: boolean ): Promise => { - return spSystemTraceInit(this, param, wasmConfigUri, progress); + return spSystemTraceInit(this, param, wasmConfigUri, progress, isDistributed); }; // @ts-ignore extracted(it: TraceRow) { @@ -2198,6 +2451,9 @@ export class SpSystemTrace extends BaseElement { this.intersectionObserver?.observe(child); }); } else { + //@ts-ignore + let parentElTopHeight = it.hasParentRowEl ? //@ts-ignore + (it.parentRowEl.getBoundingClientRect().top + it.parentRowEl.clientHeight) : this.rowsPaneEL!.getBoundingClientRect().top; it.childrenList.forEach((child): void => { if (child.hasAttribute('scene') && !child.collect) { child.rowHidden = true; @@ -2207,6 +2463,22 @@ export class SpSystemTrace extends BaseElement { child.removeEventListener('expansion-change', this.extracted(child)); } }); + if (it.getBoundingClientRect().top < 0) { + this.rowsPaneEL!.scrollTop = + this.rowsPaneEL!.scrollTop - + (it.getBoundingClientRect().top * -1 + parentElTopHeight); + } else if (it.getBoundingClientRect().top > 0) { + this.rowsPaneEL!.scrollTop = + parentElTopHeight < + it.getBoundingClientRect().top ? + this.rowsPaneEL!.scrollTop : + this.rowsPaneEL!.scrollTop - + (parentElTopHeight - it.getBoundingClientRect().top); + } else { + this.rowsPaneEL!.scrollTop = + this.rowsPaneEL!.scrollTop - + parentElTopHeight; + } this.linkNodes.map((value): void => { if ('task' === value[0].business && value[0].rowEL.parentRowEl?.rowId === it.rowId) { value[0].hidden = true; @@ -2215,11 +2487,29 @@ export class SpSystemTrace extends BaseElement { } }); } + this.resetDistributedLine(); if (!this.collapseAll) { - this.refreshCanvas(false); + this.refreshCanvas(false, 'extracted'); } }; } + + resetDistributedLine(): void { + if (FuncStruct.selectFuncStruct) { + let dataList = FuncStruct.selectLineFuncStruct; + this.removeLinkLinesByBusinessType('distributed'); + FuncStruct.selectLineFuncStruct = dataList; + for (let index = 0; index < FuncStruct.selectLineFuncStruct.length; index++) { + let sourceData = FuncStruct.selectLineFuncStruct[index]; + if (index !== FuncStruct.selectLineFuncStruct.length - 1) { + let targetData = FuncStruct.selectLineFuncStruct[index + 1]; + this.drawDistributedLine(sourceData, targetData, FuncStruct.selectFuncStruct!); + } + } + this.refreshCanvas(true); + } + } + // @ts-ignore displayTip(row: TraceRow, struct: unknown, html: string): void { let x = row.hoverX + 248; @@ -2241,7 +2531,7 @@ export class SpSystemTrace extends BaseElement { this.tipEL.style.display = 'block'; // @ts-ignore y = y + struct.depth * 20; if (row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) { - this.tipEL.style.height = '40px'; + this.tipEL.style.height = 'auto'; y = row.hoverY + row.getBoundingClientRect().top - this.getBoundingClientRect().top; } } else { @@ -2260,6 +2550,7 @@ export class SpSystemTrace extends BaseElement { TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: unknown) => { if (a === null) { window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList); + return null; } // @ts-ignore SpSystemTrace.wakeupList.push(a); // @ts-ignore this.queryCPUWakeUpList(a); diff --git a/ide/src/trace/component/SpThirdParty.ts b/ide/src/trace/component/SpThirdParty.ts index 118529aee362ca9df52cd3af8b0a11f1019821f1..b34599c3bdc57be30aafbee308a948607d638c21 100644 --- a/ide/src/trace/component/SpThirdParty.ts +++ b/ide/src/trace/component/SpThirdParty.ts @@ -15,36 +15,23 @@ import { BaseElement, element } from '../../base-ui/BaseElement'; import { LitMainMenu, MenuItem } from '../../base-ui/menu/LitMainMenu'; -import { SpApplication } from '../SpApplication'; @element('sp-third-party') export class SpThirdParty extends BaseElement { - private bodyEl: HTMLElement | undefined | null; - private uploadEl: HTMLElement | undefined | null; - private inputEl: HTMLInputElement | undefined | null; - private sp: SpApplication | undefined; + private uploadJsonBtn: HTMLElement | undefined | null; + private inputJsonEl: HTMLInputElement | undefined | null; + private uploadCsvBtn: HTMLElement | undefined | null; + private inputCsvEl: HTMLInputElement | undefined | null; initElements(): void { let parentElement = this.parentNode as HTMLElement; parentElement.style.overflow = 'hidden'; - this.bodyEl = this.shadowRoot?.querySelector('.body'); - this.uploadEl = this.shadowRoot?.querySelector('.upload-btn')?.shadowRoot?.querySelector('#custom-button'); - this.inputEl = this.shadowRoot?.querySelector('#file'); - this.uploadEl?.addEventListener('click', () => { - this.inputEl?.click(); - }); - this.inputEl!.addEventListener('change', () => { - let files = this.inputEl!.files; - if (files && files.length > 0) { - let main = this.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu; - let children = main.menus!; - let child = children[0].children as Array; - let fileHandler = child[0].fileHandler!; - fileHandler({ - detail: files[0], - }); - } - if (this.inputEl) this.inputEl.value = ''; - }); + this.uploadJsonBtn = this.shadowRoot?.querySelector('.upload-json-btn')?.shadowRoot?.querySelector('#custom-button'); + this.inputJsonEl = this.shadowRoot?.querySelector('#file'); + this.addUploadEvent(this.uploadJsonBtn!, this.inputJsonEl!); + + this.uploadCsvBtn = this.shadowRoot?.querySelector('.upload-csv-btn')?.shadowRoot?.querySelector('#custom-button'); + this.inputCsvEl = this.shadowRoot?.querySelector('#csv-file'); + this.addUploadEvent(this.uploadCsvBtn!, this.inputCsvEl!); } initHtml(): string { @@ -52,11 +39,20 @@ export class SpThirdParty extends BaseElement { ${this.initHtmlStyle()}
- - + + + Open bpftrace file + +
+
+ + - Open bpftrace file + Open gpu counter file +
`; @@ -86,11 +82,32 @@ export class SpThirdParty extends BaseElement { padding-left: 2%; padding-right: 4%; } - .upload-btn { + .upload-json-btn, .upload-csv-btn { margin-top: 2%; margin-left: 3%; } `; } + + addUploadEvent(uploadBtn: HTMLElement, uploadEl: HTMLInputElement) { + uploadBtn?.addEventListener('click', () => { + uploadEl?.click(); + }) + uploadEl!.addEventListener('change', () => { + let files = uploadEl!.files; + if (files && files.length > 0) { + let main = this.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu; + let children = main.menus!; + let child = children[0].children as Array; + let fileHandler = child[0].fileHandler!; + fileHandler({ + detail: files[0] + }) + } + if (uploadEl) uploadEl.value = ''; + }) + } } + + diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index f76abc4827e5c1b6d41cfbac6eb3f88571a28e7a..ea658a3dbe7d30716618d75290c7302d4c3d596b 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -65,6 +65,8 @@ export class FrameChart extends BaseElement { private chartClickListenerList: Array = []; private isUpdateCanvas = false; private isClickMode = false; //是否为点选模式 + _totalRootData: Array = [];//初始化顶部root的数据 + private totalRootNode!: ChartStruct; /** * set chart mode @@ -89,6 +91,14 @@ export class FrameChart extends BaseElement { this.hideTip(); } + get totalRootData(): Array { + return this._totalRootData; + } + + set totalRootData(value: Array) { + this._totalRootData = value; + } + private get total(): number { return this.getNodeValue(this.rootNode); } @@ -103,8 +113,6 @@ export class FrameChart extends BaseElement { return node.drawDur || node.dur; case ChartMode.EventCount: return node.drawEventCount || node.eventCount; - default: - return node.drawSize || node.size; } } @@ -144,6 +152,19 @@ export class FrameChart extends BaseElement { this.rootNode.eventCount += node.drawEventCount || node.eventCount; node.parent = this.rootNode; } + this.totalRootNode = new ChartStruct(); + this.totalRootNode.symbol = 'root'; + this.totalRootNode.depth = 0; + this.totalRootNode.percent = 1; + this.totalRootNode.frame = new Rect(0, scaleHeight, this.canvas!.width, depthHeight); + for (const node of this._totalRootData!) { + this.totalRootNode.children.push(node); + this.totalRootNode.count += node.drawCount || node.count; + this.totalRootNode.size += node.drawSize || node.size; + this.totalRootNode.dur += node.drawDur || node.dur; + this.totalRootNode.eventCount += node.drawEventCount || node.eventCount; + node.parent = this.totalRootNode; + } } /** @@ -219,7 +240,7 @@ export class FrameChart extends BaseElement { break; case ChartMode.Count: currentValue = `${this.total}`; - currentValuePercent = this.total / this.rootNode.count; + currentValuePercent = this.total / this.totalRootNode.count; break; case ChartMode.Duration: currentValue = Utils.getProbablyTime(this.total); @@ -227,7 +248,7 @@ export class FrameChart extends BaseElement { break; case ChartMode.EventCount: currentValue = `${this.total}`; - currentValuePercent = this.total / this.rootNode.eventCount; + currentValuePercent = this.total / this.totalRootNode.eventCount; break; } let endStr = currentValuePercent ? ` (${(currentValuePercent * 100).toFixed(2)}%)` : ''; @@ -547,8 +568,6 @@ export class FrameChart extends BaseElement { return ignore.dur; case ChartMode.EventCount: return ignore.eventCount; - default: - return ignore.size; } } @@ -562,8 +581,6 @@ export class FrameChart extends BaseElement { return node.searchDur > 0; case ChartMode.EventCount: return node.searchEventCount > 0; - default: - return node.searchSize > 0; } } @@ -638,8 +655,10 @@ export class FrameChart extends BaseElement { } else { x += scaleHeight; } - //最下边函数块悬浮框显示在函数上边 - y -= this.floatHint!.clientHeight - 1; + //顶部悬浮框显示在函数下边,下半部分悬浮框显示在函数上边 + if (y > this.floatHint!.clientHeight) { + y -= this.floatHint!.clientHeight - 1; + } this.floatHint!.style.transform = `translate(${x}px,${y}px)`; } @@ -1008,12 +1027,13 @@ export class FrameChart extends BaseElement { } }); - document.addEventListener('keyup', (e) => { - if (!ChartStruct.hoverFuncStruct) { + document.addEventListener('keydown', (e) => { + if (!ChartStruct.hoverFuncStruct || !this.isFocusing) { return; } if (e.ctrlKey && e.key.toLocaleLowerCase() === 'c') { - navigator.clipboard.writeText(ChartStruct.hoverFuncStruct!.symbol); + let hoverName: string = ChartStruct.hoverFuncStruct!.symbol.split(' (')[0]; + navigator.clipboard.writeText(hoverName); } }); this.listenerResize(); diff --git a/ide/src/trace/component/chart/SpAbilityMonitorChart.ts b/ide/src/trace/component/chart/SpAbilityMonitorChart.ts index 7ce449782d216537656da6bf1cdea5c9349eed86..e2ab376ce0f7d596756b2e364c153a5ff5310759 100644 --- a/ide/src/trace/component/chart/SpAbilityMonitorChart.ts +++ b/ide/src/trace/component/chart/SpAbilityMonitorChart.ts @@ -221,7 +221,7 @@ export class SpAbilityMonitorChart { context = userTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } userTraceRow.canvasSave(context); - (renders.monitorCpu as CpuAbilityRender).renderMainThread( + (renders['monitorCpu'] as CpuAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -268,7 +268,7 @@ export class SpAbilityMonitorChart { context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } traceRow.canvasSave(context); - (renders.monitorCpu as CpuAbilityRender).renderMainThread( + (renders['monitorCpu'] as CpuAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -318,7 +318,7 @@ export class SpAbilityMonitorChart { context = sysTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } sysTraceRow.canvasSave(context); - (renders.monitorCpu as CpuAbilityRender).renderMainThread( + (renders['monitorCpu'] as CpuAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -345,7 +345,7 @@ export class SpAbilityMonitorChart { context = memoryUsedRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } memoryUsedRow.canvasSave(context); - (renders.monitorMemory as MemoryAbilityRender).renderMainThread( + (renders['monitorMemory'] as MemoryAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -408,7 +408,7 @@ export class SpAbilityMonitorChart { context = cachedFilesTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } cachedFilesTraceRow.canvasSave(context); - (renders.monitorMemory as MemoryAbilityRender).renderMainThread( + (renders['monitorMemory'] as MemoryAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -470,7 +470,7 @@ export class SpAbilityMonitorChart { context = compressedRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } compressedRow.canvasSave(context); - (renders.monitorMemory as MemoryAbilityRender).renderMainThread( + (renders['monitorMemory'] as MemoryAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -549,7 +549,7 @@ export class SpAbilityMonitorChart { context = bytesReadRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } bytesReadRow.canvasSave(context); - (renders.monitorDiskIo as DiskIoAbilityRender).renderMainThread( + (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -607,7 +607,7 @@ export class SpAbilityMonitorChart { context = bytesWriteRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } bytesWriteRow.canvasSave(context); - (renders.monitorDiskIo as DiskIoAbilityRender).renderMainThread( + (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -696,7 +696,7 @@ export class SpAbilityMonitorChart { context = readOpsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } readOpsRow.canvasSave(context); - (renders.monitorDiskIo as DiskIoAbilityRender).renderMainThread( + (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -722,7 +722,7 @@ export class SpAbilityMonitorChart { context = writeOpsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } writeOpsRow.canvasSave(context); - (renders.monitorDiskIo as DiskIoAbilityRender).renderMainThread( + (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -803,7 +803,7 @@ export class SpAbilityMonitorChart { context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } row.canvasSave(context); - (renders.monitorNetwork as NetworkAbilityRender).renderMainThread( + (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -861,7 +861,7 @@ export class SpAbilityMonitorChart { context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } row.canvasSave(context); - (renders.monitorNetwork as NetworkAbilityRender).renderMainThread( + (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -920,7 +920,7 @@ export class SpAbilityMonitorChart { context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } row.canvasSave(context); - (renders.monitorNetwork as NetworkAbilityRender).renderMainThread( + (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, @@ -979,7 +979,7 @@ export class SpAbilityMonitorChart { context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } row.canvasSave(context); - (renders.monitorNetwork as NetworkAbilityRender).renderMainThread( + (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, diff --git a/ide/src/trace/component/chart/SpBpftraceChart.ts b/ide/src/trace/component/chart/SpBpftraceChart.ts index 32a6268f57afd7b93ab017fbb223dce3127bf30d..0cc9ed002625e19fd3ce9d0563bb24f2f521b4ca 100644 --- a/ide/src/trace/component/chart/SpBpftraceChart.ts +++ b/ide/src/trace/component/chart/SpBpftraceChart.ts @@ -51,7 +51,7 @@ export class SpBpftraceChart { traceRow.selectChangeHandler = this.trace.selectChangeHandler; traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; //添加上传按钮 - traceRow.addRowSampleUpload(); + if (!file) traceRow.addRowSampleUpload(); this.addTraceRowEventListener(traceRow, start_ts); //单独上传 if (file) { @@ -224,7 +224,7 @@ export class SpBpftraceChart { newNode['property'] = []; result.push(newNode); if (node.children) { - result = result.concat(this.getFlattenTreeData(node.children, depth + 1, node.function_name)); + result = result.concat(this.getFlattenTreeData(node.children, depth + 1, node['function_name'])); } }); return result; @@ -240,7 +240,7 @@ export class SpBpftraceChart { propertyData.forEach((propertyGroup) => { const groups: Array = []; propertyGroup.forEach((property: any) => { - const duplicateObj = groups.find((group) => group.func_name === property.func_name); + const duplicateObj = groups.find((group) => group['func_name'] === property['func_name']); if (duplicateObj) { duplicateObj['begin'] = Math.min(duplicateObj['begin'], property['begin']); duplicateObj['end'] = Math.max(duplicateObj['end'], property['end']); @@ -263,7 +263,7 @@ export class SpBpftraceChart { //数组每一项进行比对 propertyData.forEach((propertyGroup) => { propertyGroup.forEach((property: any) => { - const relation = sampleProperty.find((relation) => relation.name === property.func_name); + const relation = sampleProperty.find((relation) => relation['name'] === property['func_name']); //property属性存储每帧数据 relation?.property.push({ name: property['func_name'], @@ -272,13 +272,13 @@ export class SpBpftraceChart { begin: property['begin'], depth: relation['depth'], instructions: property['instructions'], - cycles: property.cycles, + cycles: property['cycles'], }); }); }); //获取所有名字为unknown的数据 - const unknownRelation = sampleProperty.filter((relation) => relation.name.indexOf('unknown') > -1); + const unknownRelation = sampleProperty.filter((relation) => relation['name'].indexOf('unknown') > -1); //二维数组 用于存放unknown下所有子节点的数据 let twoDimensionalArray: Array = []; let result: Array = []; @@ -288,7 +288,7 @@ export class SpBpftraceChart { const children = unknownItem['children']; //先获取到unknwon节点下每个子节点的property Object.keys(children).forEach((key) => { - unknownItem.children[key] = sampleProperty.find((relation) => relation.name === key).property; + unknownItem.children[key] = sampleProperty.find((relation) => relation['name'] === key).property; }); //将每个子节点的property加到二维数组中 Object.values(children).forEach((value: any) => { @@ -304,11 +304,11 @@ export class SpBpftraceChart { detail: unknownItem['detail'], begin: twoDimensionalArray[0][i].begin, end: 0, - depth: unknownItem.depth, + depth: unknownItem['depth'], }; for (let j = 0; j < twoDimensionalArray.length; j++) { - data.end = Math.max(twoDimensionalArray[j][i].end, data.end); - data.begin = Math.min(twoDimensionalArray[j][i].begin, data.begin); + data['end'] = Math.max(twoDimensionalArray[j][i]['end'], data['end']); + data['begin'] = Math.min(twoDimensionalArray[j][i]['begin'], data['begin']); } result.push(data); } @@ -327,7 +327,7 @@ export class SpBpftraceChart { if (node['children']) { node['children'].forEach((child: any) => { if (child['function_name'].indexOf('unknown') < 0) { - names[child.function_name] = []; + names[child['function_name']] = []; } else { this.getUnknownAllChildrenNames(child, names); } diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index 62c1bc613b612ef838615cf6142c829d2e14da2a..f577f8c66c73d3cbcc801201d7ac054fb855ce68 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -49,13 +49,16 @@ import { queryDataDICT, queryThreadAndProcessName, } from '../../database/sql/ProcessThread.sql'; -import { queryTaskPoolCallStack, queryTotalTime, queryTraceRange } from '../../database/sql/SqlLite.sql'; -import { getCpuUtilizationRate } from '../../database/sql/Cpu.sql'; +import { queryTaskPoolCallStack, queryTotalTime } from '../../database/sql/SqlLite.sql'; import { queryMemoryConfig } from '../../database/sql/Memory.sql'; import { SpLtpoChart } from './SpLTPO'; import { SpBpftraceChart } from './SpBpftraceChart'; import { sliceSender } from '../../database/data-trafic/SliceSender'; +import { BaseStruct } from '../../bean/BaseStruct'; +import { SpGpuCounterChart } from './SpGpuCounterChart'; import { SpUserFileChart } from './SpUserPluginChart' +import { queryDmaFenceIdAndCat } from '../../database/sql/dmaFence.sql' +import { queryAllFuncNames } from '../../database/sql/Func.sql'; export class SpChartManager { static APP_STARTUP_PID_ARR: Array = []; @@ -69,6 +72,7 @@ export class SpChartManager { private nativeMemory: SpNativeMemoryChart; private abilityMonitor: SpAbilityMonitorChart; private process: SpProcessChart; + private process2?: SpProcessChart; private fileSystem: SpEBPFChart; private sdkChart: SpSdkChart; private hiSyseventChart: SpHiSysEnergyChart; @@ -83,8 +87,8 @@ export class SpChartManager { private spHiSysEvent: SpHiSysEventChart; private spSegmentationChart: SpSegmentationChart; private spBpftraceChart: SpBpftraceChart; - private tranceRange = { startTs: 0, endTs: 0 }; private spPerfOutputDataChart: SpPerfOutputDataChart; + private spGpuCounterChart: SpGpuCounterChart; private spUserFileChart: SpUserFileChart; constructor(trace: SpSystemTrace) { @@ -112,10 +116,12 @@ export class SpChartManager { this.spSegmentationChart = new SpSegmentationChart(trace); this.spBpftraceChart = new SpBpftraceChart(trace); this.spPerfOutputDataChart = new SpPerfOutputDataChart(trace); + this.spGpuCounterChart = new SpGpuCounterChart(trace); this.spUserFileChart = new SpUserFileChart(trace) } async initPreprocessData(progress: Function): Promise { progress('load data dict', 50); + this.process2 = undefined; SpSystemTrace.DATA_DICT.clear(); SpChartManager.APP_STARTUP_PID_ARR = []; let dict = await queryDataDICT(); @@ -124,7 +130,7 @@ export class SpChartManager { appStartUpPids.forEach((it) => SpChartManager.APP_STARTUP_PID_ARR.push(it.pid)); } await this.initTraceConfig(); //@ts-ignore - dict.map((d) => SpSystemTrace.DATA_DICT.set(d.id, d.data)); + dict.map((d) => SpSystemTrace.DATA_DICT.set(d['id'], d['data'])); await this.cacheDataDictToWorker(); SpSystemTrace.DATA_TASK_POOL_CALLSTACK.clear(); let taskPoolCallStack = await queryTaskPoolCallStack(); @@ -134,22 +140,29 @@ export class SpChartManager { let ptArr = await queryThreadAndProcessName(); //@ts-ignore this.handleProcessThread(ptArr); info('initData timerShaftEL Data initialized'); - const range = await queryTraceRange(); - //@ts-ignore - this.tranceRange = range[0]; + let funArr = await queryAllFuncNames(); + this.handleFuncName(funArr); } async initCpu(progress: Function): Promise { progress('cpu', 70); - let count = await sliceSender(); //@ts-ignore - await this.cpu.init(count.cpu); + let result = await sliceSender(); + // @ts-ignore + SpProcessChart.threadStateList = result.threadMap; + // @ts-ignore + SpProcessChart.processRowSortMap = result.processRowSortMap; + //@ts-ignore + await this.cpu.init(result.count.cpu); info('initData cpu Data initialized'); if (FlagsConfig.getFlagsConfigEnableStatus('Bpftrace')) { await this.spBpftraceChart.init(null); } - if (FlagsConfig.getFlagsConfigEnableStatus('UserPluginsRow')){ + if (FlagsConfig.getFlagsConfigEnableStatus('UserPluginsRow')) { await this.spUserFileChart.init(null) } + if (FlagsConfig.getFlagsConfigEnableStatus('GpuCounter')) { + await this.spGpuCounterChart.init([]); + } if (FlagsConfig.getFlagsConfigEnableStatus('SchedulingAnalysis')) { await this.cpu.initCpuIdle0Data(progress); await this.cpu.initSchedulingPTData(progress); @@ -157,7 +170,8 @@ export class SpChartManager { } info('initData ProcessThreadState Data initialized'); progress('cpu rate', 75); - await this.initCpuRate(); + //@ts-ignore + await this.initCpuRate(result.cpuUtiliRateArray); info('initData Cpu Rate Data initialized'); progress('cpu freq', 80); await this.freq.init(); @@ -170,6 +184,8 @@ export class SpChartManager { await this.initCpu(progress); await this.logChart.init(); await this.spHiSysEvent.init(); + let idAndNameArr = await queryDmaFenceIdAndCat(); + this.handleDmaFenceName(idAndNameArr as { id: number; cat: string; seqno: number; driver: string; context: string }[]); progress('Clock init', 82); await this.clockChart.init(); progress('Irq init', 84); @@ -201,21 +217,100 @@ export class SpChartManager { await this.frameTimeChart.init(); await this.spPerfOutputDataChart.init(); progress('process', 92); - await this.process.initAsyncFuncData(this.tranceRange); + this.process.clearCache(); + this.process2?.clearCache(); + this.process2 = undefined; + await this.process.initAsyncFuncData({ + startTs: Utils.getInstance().getRecordStartNS(), + endTs: Utils.getInstance().getRecordEndNS(), + }); await this.process.initDeliverInputEvent(); - await this.process.init(); + await this.process.initTouchEventDispatch(); + await this.process.init(false); progress('display', 95); } - async initSample(ev: File): Promise { - await this.initSampleTime(); + async initDistributedChart(progress: Function, file1: string, file2: string): Promise { + let funArr1 = await queryAllFuncNames('1'); + let funArr2 = await queryAllFuncNames('2'); + this.handleFuncName(funArr1,'1'); + this.handleFuncName(funArr2,'2'); + progress('load data dict', 50); + SpSystemTrace.DATA_DICT.clear(); + SpChartManager.APP_STARTUP_PID_ARR = []; + SpSystemTrace.DATA_TASK_POOL_CALLSTACK.clear(); + this.process.clearCache(); + this.process2?.clearCache(); + let trace1Folder = this.createFolderRow('trace-1', 'trace-1', file1); + let trace2Folder = this.createFolderRow('trace-2', 'trace-2', file2); + this.trace.rowsEL!.appendChild(trace1Folder); + this.trace.rowsEL!.appendChild(trace2Folder); + await this.initTotalTime(true); + await this.initDistributedTraceRow('1', trace1Folder, progress); + info(`trace 1 load completed`); + await this.initDistributedTraceRow('2', trace2Folder, progress); + info(`trace 2 load completed`); + } + + async initDistributedTraceRow(traceId: string, traceFolder: TraceRow, progress: Function): Promise { + let ptArr = await queryThreadAndProcessName(traceId); + // @ts-ignore + this.handleProcessThread(ptArr, traceId); + info(`initData trace ${traceId} timerShaftEL Data initialized`); + progress(`trace ${traceId} cpu`, 70); + let count = await sliceSender(traceId); + // @ts-ignore + await this.cpu.init(count.cpu, traceFolder, traceId); + info(`initData trace ${traceId} cpu Data initialized`); + progress(`trace ${traceId} cpu freq`, 75); + await this.freq.init(traceFolder, traceId); + info(`initData trace ${traceId} cpu freq Data initialized`); + progress(`trace ${traceId} clock`, 80); + await this.clockChart.init(traceFolder, traceId); + info(`initData trace ${traceId} clock Data initialized`); + progress(`trace ${traceId} Irq`, 85); + await this.irqChart.init(traceFolder, traceId); + info(`initData trace ${traceId} irq Data initialized`); + progress(`trace ${traceId} process`, 92); + if (traceId === '2') { + if (!this.process2) { + this.process2 = new SpProcessChart(this.trace); + } + await this.process2.initAsyncFuncData( + { + startTs: Utils.getInstance().getRecordStartNS('2'), + endTs: Utils.getInstance().getRecordEndNS('2'), + }, + traceId + ); + await this.process2.init(true, traceFolder, traceId); + } else { + await this.process.initAsyncFuncData( + { + startTs: Utils.getInstance().getRecordStartNS('1'), + endTs: Utils.getInstance().getRecordEndNS('1'), + }, + traceId + ); + await this.process.init(true, traceFolder, traceId); + } + } + + async initSample(ev: File) { + await this.initSampleTime(ev, 'bpftrace'); await this.spBpftraceChart.init(ev); } + async initGpuCounter(ev: File) { + const res = await this.initSampleTime(ev, 'gpucounter'); + //@ts-ignore + await this.spGpuCounterChart.init(res); + } + async importSoFileUpdate(): Promise { SpSystemTrace.DATA_DICT.clear(); let dict = await queryDataDICT(); //@ts-ignore - dict.map((d) => SpSystemTrace.DATA_DICT.set(d.id, d.data)); + dict.map((d) => SpSystemTrace.DATA_DICT.set(d['id'], d['data'])); await this.cacheDataDictToWorker(); await perfDataQuery.initPerfCache(); await this.nativeMemory.initNativeMemory(); @@ -223,43 +318,72 @@ export class SpChartManager { this.perf.resetAllChartData(); } - handleProcessThread(arr: { id: number; name: string; type: string }[]): void { - Utils.PROCESS_MAP.clear(); - Utils.THREAD_MAP.clear(); + handleProcessThread(arr: { id: number; name: string; type: string }[], traceId?: string): void { + Utils.getInstance().getProcessMap(traceId).clear(); + Utils.getInstance().getThreadMap(traceId).clear(); for (let pt of arr) { if (pt.type === 'p') { - Utils.PROCESS_MAP.set(pt.id, pt.name); + Utils.getInstance().getProcessMap(traceId).set(pt.id, pt.name); } else { - Utils.THREAD_MAP.set(pt.id, pt.name); + Utils.getInstance().getThreadMap(traceId).set(pt.id, pt.name); } } } - initTotalTime = async (): Promise => { - let res = await queryTotalTime(); + // 将callstatck表信息转为map存入utils + handleFuncName(funcNameArray: Array,traceId?:string) { + if(traceId){ + funcNameArray.forEach((it) => { + //@ts-ignore + Utils.getInstance().getCallStatckMap().set(`${traceId}_${it.id!}`,it.name); + }); + }else { + funcNameArray.forEach((it) => { + //@ts-ignore + Utils.getInstance().getCallStatckMap().set(it.id, it.name); + }); + } + } + + initTotalTime = async (isDistributed: boolean = false): Promise => { + let res1 = await queryTotalTime('1'); + let total = res1[0].total; + Utils.getInstance().trace1RecordStartNS = res1[0].recordStartNS; + Utils.getInstance().trace1RecordEndNS = Math.max(res1[0].recordEndNS, res1[0].recordStartNS + 1); + if (isDistributed) { + let res2 = await queryTotalTime('2'); + total = Math.max(total, res2[0].total); + Utils.getInstance().trace2RecordStartNS = res2[0].recordStartNS; + Utils.getInstance().trace2RecordEndNS = Math.max(res2[0].recordEndNS, res2[0].recordStartNS + 1); + } if (this.trace.timerShaftEL) { - let total = res[0].total; - let startNS = res[0].recordStartNS; - let endNS = res[0].recordEndNS; - if (total === 0 && startNS === endNS) { + if (total === 0) { total = 1; - endNS = startNS + 1; } + Utils.getInstance().totalNS = total; this.trace.timerShaftEL.totalNS = total; this.trace.timerShaftEL.getRangeRuler()!.drawMark = true; this.trace.timerShaftEL.setRangeNS(0, total); - window.recordStartNS = startNS; - window.recordEndNS = endNS; + window.recordStartNS = Utils.getInstance().trace1RecordStartNS; + window.recordEndNS = Utils.getInstance().trace1RecordEndNS; window.totalNS = total; this.trace.timerShaftEL.loadComplete = true; } }; - initSampleTime = async (): Promise => { + initSampleTime = async (ev: File, type: string): Promise => { + let res; + let endNS = 30_000_000_000; + if (type === 'gpucounter') { + res = await this.spGpuCounterChart.getCsvData(ev); + const endTime = Number(res[res.length - 1].split(',')[0]); + const minIndex = this.spGpuCounterChart.getMinData(res) + 1; + const startTime = Number(res[minIndex].split(',')[0]); + endNS = Number((endTime - startTime).toString().slice(0, 11)); + } if (this.trace.timerShaftEL) { - let total = 30_000_000_000; + let total = endNS; let startNS = 0; - let endNS = 30_000_000_000; this.trace.timerShaftEL.totalNS = total; this.trace.timerShaftEL.getRangeRuler()!.drawMark = true; this.trace.timerShaftEL.setRangeNS(0, total); // @ts-ignore @@ -268,10 +392,10 @@ export class SpChartManager { (window as unknown).totalNS = total; this.trace.timerShaftEL.loadComplete = true; } + return res; }; - initCpuRate = async (): Promise => { - let rates = await getCpuUtilizationRate(0, this.trace.timerShaftEL?.totalNS || 0); + initCpuRate = async (rates: Array<{ cpu: number; ro: number; rate: number;}>): Promise => { if (this.trace.timerShaftEL) { this.trace.timerShaftEL.cpuUsage = rates; } @@ -300,19 +424,48 @@ export class SpChartManager { ); }); } + + createFolderRow(rowId: string, rowType: string, rowName: string, traceId?: string): TraceRow { + let row = TraceRow.skeleton(traceId); + row.setAttribute('disabled-check', ''); + row.rowId = rowId; + row.rowType = rowType; + row.rowParentId = ''; + row.folder = true; + row.style.height = '40px'; + row.name = rowName; + // @ts-ignore + row.supplier = folderSupplier(); + row.onThreadHandler = folderThreadHandler(row, this.trace); + row.addEventListener('expansion-change', (evt) => { + if (!row.expansion) { + this.trace.clickEmptyArea(); + } + }); + return row; + } + + //存名字 + handleDmaFenceName(arr: T[]) { + Utils.DMAFENCECAT_MAP.clear(); + for (let item of arr) { + Utils.DMAFENCECAT_MAP.set(item.id, item); + } + } } -export const folderSupplier = (): unknown => { - return () => new Promise>((resolve) => resolve([])); -}; // @ts-ignore -export const folderThreadHandler = (row: TraceRow, trace: SpSystemTrace) => { +export const folderSupplier = (): () => Promise => { + return () => new Promise>((resolve) => resolve([])); +}; + +export const folderThreadHandler = (row: TraceRow, trace: SpSystemTrace) => { return (useCache: boolean): void => { row.canvasSave(trace.canvasPanelCtx!); if (row.expansion) { // @ts-ignore trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); } else { - (renders.empty as EmptyRender).renderMainThread( + (renders['empty'] as EmptyRender).renderMainThread( { context: trace.canvasPanelCtx, useCache: useCache, diff --git a/ide/src/trace/component/chart/SpClockChart.ts b/ide/src/trace/component/chart/SpClockChart.ts index 96849bf91e608014c2b9bf2afe483e17a8463368..7071b74e4ca7e4b3f6a746bebc5ad94363132a49 100644 --- a/ide/src/trace/component/chart/SpClockChart.ts +++ b/ide/src/trace/component/chart/SpClockChart.ts @@ -23,17 +23,31 @@ import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { Utils } from '../trace/base/Utils'; import { clockDataSender } from '../../database/data-trafic/ClockDataSender'; import { queryClockData } from '../../database/sql/Clock.sql'; +import { DmaFenceRender, DmaFenceStruct } from '../../database/ui-worker/ProcedureWorkerDmaFence'; +import { dmaFenceSender } from '../../database/data-trafic/dmaFenceSender'; +import { queryDmaFenceName } from '../../database/sql/dmaFence.sql' +import { BaseStruct } from '../../bean/BaseStruct'; export class SpClockChart { - private trace: SpSystemTrace; + private readonly trace: SpSystemTrace; constructor(trace: SpSystemTrace) { this.trace = trace; } - async init(): Promise { - let folder = await this.initFolder(); - await this.initData(folder); + async init(parentRow?: TraceRow, traceId?: string): Promise { + let clockList = await queryClockData(traceId); + if (clockList.length === 0) { + return; + } + let folder = await this.initFolder(traceId); + if (parentRow) { + parentRow.addChildTraceRow(folder); + } else { + this.trace.rowsEL?.appendChild(folder); + } + await this.initData(folder, clockList, traceId); + await this.initDmaFence(folder); } private clockSupplierFrame( @@ -45,7 +59,7 @@ export class SpClockChart { maxValue?: number; }, isState: boolean, - isScreenState: boolean + isScreenState: boolean, ): void { traceRow.supplierFrame = (): Promise => { let promiseData = null; @@ -103,7 +117,7 @@ export class SpClockChart { context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } traceRow.canvasSave(context); - (renders.clock as ClockRender).renderMainThread( + (renders['clock'] as ClockRender).renderMainThread( { context: context, useCache: useCache, @@ -120,20 +134,23 @@ export class SpClockChart { traceRow.canvasRestore(context, this.trace); }; } - // @ts-ignore - async initData(folder: TraceRow): Promise { + + async initData(folder: TraceRow, clockList: Array<{ + name: string; + num: number; + srcname: string; + maxValue?: number; + }>, traceId?: string): Promise { let clockStartTime = new Date().getTime(); - let clockList = await queryClockData(); - if (clockList.length === 0) { - return; - } info('clockList data size is: ', clockList!.length); - this.trace.rowsEL?.appendChild(folder); + if (!traceId) { + this.trace.rowsEL?.appendChild(folder); + } ClockStruct.maxValue = clockList.map((item) => item.num).reduce((a, b) => Math.max(a, b)); for (let i = 0; i < clockList.length; i++) { const it = clockList[i]; it.maxValue = 0; - let traceRow = TraceRow.skeleton(); + let traceRow = TraceRow.skeleton(traceId); let isState = it.name.endsWith(' State'); let isScreenState = it.name.endsWith('ScreenState'); traceRow.rowId = it.name; @@ -146,15 +163,13 @@ export class SpClockChart { traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; traceRow.selectChangeHandler = this.trace.selectChangeHandler; this.clockSupplierFrame(traceRow, it, isState, isScreenState); - traceRow.getCacheData = (args: unknown): Promise> => { + traceRow.getCacheData = (args: unknown): Promise> | undefined => { if (it.name.endsWith(' Frequency')) { return clockDataSender(it.srcname, 'clockFrequency', traceRow, args); } else if (isState) { return clockDataSender(it.srcname, 'clockState', traceRow, args); } else if (isScreenState) { return clockDataSender('', 'screenState', traceRow, args); - } else { - return new Promise((): void => {}); } }; traceRow.focusHandler = (ev): void => { @@ -173,9 +188,73 @@ export class SpClockChart { let durTime = new Date().getTime() - clockStartTime; info('The time to load the ClockData is: ', durTime); } - // @ts-ignore - async initFolder(): Promise> { - let clockFolder = TraceRow.skeleton(); + + async initDmaFence(folder: TraceRow) { + let dmaFenceNameList = await queryDmaFenceName() + if (dmaFenceNameList.length) { + let dmaFenceList = []; + const timelineValues = dmaFenceNameList.map(obj => obj.timeline); + for (let i = 0; i < timelineValues.length; i++) { + let traceRow: TraceRow = TraceRow.skeleton(); + traceRow.rowId = timelineValues[i]; + traceRow.rowType = TraceRow.ROW_TYPE_DMA_FENCE; + traceRow.rowParentId = folder.rowId; + traceRow.style.height = 40 + 'px'; + traceRow.name = `${timelineValues[i]}`; + traceRow.folder = false; + traceRow.rowHidden = !folder.expansion; + traceRow.setAttribute('children', ''); + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + // @ts-ignore + traceRow.supplierFrame = () => { + return dmaFenceSender('dma_fence_init', `${timelineValues[i]}`, traceRow).then((res) => { + res.forEach((item: any) => { + let detail = Utils.DMAFENCECAT_MAP.get(item.id!); + if (detail) { + let catValue = (detail.cat.match(/^dma_(.*)$/))![1]; + item.sliceName = catValue.endsWith('ed') ? `${catValue.slice(0, -2)}(${detail.seqno})` : `${catValue}(${detail.seqno})`; + item.driver = detail.driver; + item.context = detail.context; + item.depth = 0; + } + + }) + return dmaFenceList = res; + }) + + }; + traceRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (traceRow.currentContext) { + context = traceRow.currentContext; + } else { + context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + traceRow.canvasSave(context); + (renders['dmaFence'] as DmaFenceRender).renderMainThread( + { + dmaFenceContext: context, + useCache: useCache, + type: 'dmaFence', + maxValue: 20, + index: 1, + maxName: '' + }, + traceRow + ); + traceRow.canvasRestore(context, this.trace); + }; + folder.addChildTraceRow(traceRow); + } + + } + + } + + + async initFolder(traceId?: string): Promise> { + let clockFolder = TraceRow.skeleton(traceId); clockFolder.rowId = 'Clocks'; clockFolder.index = 0; clockFolder.rowType = TraceRow.ROW_TYPE_CLOCK_GROUP; @@ -184,15 +263,14 @@ export class SpClockChart { clockFolder.folder = true; clockFolder.name = 'Clocks'; clockFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; - clockFolder.selectChangeHandler = this.trace.selectChangeHandler; // @ts-ignore - clockFolder.supplier = (): Promise => new Promise>((resolve) => resolve([])); + clockFolder.selectChangeHandler = this.trace.selectChangeHandler; + clockFolder.supplier = (): Promise => new Promise>((resolve) => resolve([])); clockFolder.onThreadHandler = (useCache): void => { clockFolder.canvasSave(this.trace.canvasPanelCtx!); if (clockFolder.expansion) { - // @ts-ignore this.trace.canvasPanelCtx?.clearRect(0, 0, clockFolder.frame.width, clockFolder.frame.height); } else { - (renders.empty as EmptyRender).renderMainThread( + (renders['empty'] as EmptyRender).renderMainThread( { context: this.trace.canvasPanelCtx, useCache: useCache, diff --git a/ide/src/trace/component/chart/SpCpuChart.ts b/ide/src/trace/component/chart/SpCpuChart.ts index cfe05ff79628d2be7fd5774dd1f24d2c6a31d563..0e73a3c2c2c0d4ce2757a0c868e6bbdf0704a9bb 100644 --- a/ide/src/trace/component/chart/SpCpuChart.ts +++ b/ide/src/trace/component/chart/SpCpuChart.ts @@ -22,6 +22,7 @@ import { renders } from '../../database/ui-worker/ProcedureWorker'; import { Utils } from '../trace/base/Utils'; import { cpuDataSender } from '../../database/data-trafic/CpuDataSender'; import { queryCpuCount, queryCpuMax, queryCpuSchedSlice } from '../../database/sql/Cpu.sql'; +import { rowThreadHandler } from './SpChartManager'; export class SpCpuChart { private trace: SpSystemTrace; @@ -38,9 +39,9 @@ export class SpCpuChart { }); res.push(...filterList); res.forEach((it, i, arr) => { - let p = Utils.PROCESS_MAP.get(it.processId!); - let t = Utils.THREAD_MAP.get(it.tid!); - let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`); + let p = Utils.getInstance().getProcessMap().get(it.processId!); + let t = Utils.getInstance().getThreadMap().get(it.tid!); + let slice = Utils.getInstance().getSchedSliceMap().get(`${it.id}-${it.startTime}`); if (slice) { it.end_state = slice.endState; it.priority = slice.priority; @@ -76,52 +77,31 @@ export class SpCpuChart { }; } - async init(cpuDataCount?: Map): Promise { + async init(cpuDataCount?: Map, parentRow?: TraceRow, traceId?: string): Promise { let CpuStartTime = new Date().getTime(); - let array = await queryCpuMax(); - let cpuCountResult = await queryCpuCount(); + let array = await queryCpuMax(traceId); + let cpuCountResult = await queryCpuCount(traceId); if (cpuCountResult && cpuCountResult.length > 0 && cpuCountResult[0]) { // @ts-ignore - (window as unknown).cpuCount = cpuCountResult[0].cpuCount; + Utils.getInstance().setWinCpuCount(cpuCountResult[0].cpuCount, traceId); } else { - // @ts-ignore - (window as unknown).cpuCount = 0; + Utils.getInstance().setWinCpuCount(0, traceId); } - let cpuSchedSlice = await queryCpuSchedSlice(); - this.initSchedSliceData(cpuSchedSlice); + let cpuSchedSlice = await queryCpuSchedSlice(traceId); + this.initSchedSliceData(cpuSchedSlice, traceId); info('Cpu trace row data size is: ', array.length); if (array && array.length > 0 && array[0]) { //@ts-ignore - let cpuMax = array[0].cpu; - CpuStruct.cpuCount = cpuMax + 1; - for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { + let cpuMax = array[0].cpu + 1; + Utils.getInstance().setCpuCount(cpuMax, traceId); + for (let i1 = 0; i1 < cpuMax; i1++) { if (cpuDataCount && (cpuDataCount.get(i1) || 0) > 0) { - const cpuId = i1; - let traceRow = TraceRow.skeleton(); - traceRow.rowId = `${cpuId}`; - traceRow.rowType = TraceRow.ROW_TYPE_CPU; - traceRow.rowParentId = ''; - traceRow.style.height = '30px'; - traceRow.name = `Cpu ${cpuId}`; - traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - traceRow.selectChangeHandler = this.trace.selectChangeHandler; - this.cpuSupplierFrame(traceRow, cpuId); - traceRow.focusHandler = (): void => { - this.trace?.displayTip( - traceRow, - CpuStruct.hoverCpuStruct, - `P:${CpuStruct.hoverCpuStruct?.processName || 'Process'} [${ - CpuStruct.hoverCpuStruct?.processId - }]T:${CpuStruct.hoverCpuStruct?.name} [${CpuStruct.hoverCpuStruct?.tid}] [Prio:${ - CpuStruct.hoverCpuStruct?.priority || 0 - }]` - ); - }; - traceRow.findHoverStruct = (): void => { - CpuStruct.hoverCpuStruct = traceRow.getHoverStruct(); - }; - this.cpuThreadHandler(traceRow, i1); - this.trace.rowsEL?.appendChild(traceRow); + let traceRow = this.createCpuRow(i1, traceId); + if (parentRow) { + parentRow.addChildTraceRow(traceRow); + } else { + this.trace.rowsEL?.appendChild(traceRow); + } } } } @@ -129,6 +109,57 @@ export class SpCpuChart { info('The time to load the Cpu data is: ', CpuDurTime); } + createCpuRow(cpuId: number, traceId?: string): TraceRow { + let traceRow = TraceRow.skeleton(traceId); + traceRow.rowId = `${cpuId}`; + traceRow.rowType = TraceRow.ROW_TYPE_CPU; + traceRow.rowParentId = ''; + traceRow.style.height = '30px'; + traceRow.name = `Cpu ${cpuId}`; + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.supplierFrame = async (): Promise => { + let res = await cpuDataSender(cpuId, traceRow, traceId); + const filterList = SpSystemTrace.keyPathList.filter((item): boolean => { + return item.cpu === cpuId; + }); + res.push(...filterList); + res.forEach((it, i, arr): void => { + let p = Utils.getInstance().getProcessMap(traceId).get(it.processId!); + let t = Utils.getInstance().getThreadMap(traceId).get(it.tid!); + let slice = Utils.getInstance().getSchedSliceMap(traceId).get(`${it.id}-${it.startTime}`); + if (slice) { + it.end_state = slice.endState; + it.priority = slice.priority; + } + it.processName = p; + it.processCmdLine = p; + it.name = t; + it.type = 'thread'; + }); + return res; + }; + traceRow.focusHandler = (): void => { + this.trace?.displayTip( + traceRow, + CpuStruct.hoverCpuStruct, + `P:${CpuStruct.hoverCpuStruct?.processName || 'Process'} [${ + CpuStruct.hoverCpuStruct?.processId + }]T:${CpuStruct.hoverCpuStruct?.name} [${CpuStruct.hoverCpuStruct?.tid}] [Prio:${ + CpuStruct.hoverCpuStruct?.priority || 0 + }]` + ); + }; + traceRow.findHoverStruct = (): void => { + CpuStruct.hoverCpuStruct = traceRow.getHoverStruct(); + }; + traceRow.onThreadHandler = rowThreadHandler('cpu-data', 'ctx', { + type: `cpu-data-${cpuId}`, + translateY: traceRow.translateY, + }, traceRow, this.trace); + return traceRow; + } + initProcessThreadStateData = async (progress: Function): Promise => { let time = new Date().getTime(); progress('StateProcessThread', 93); @@ -155,11 +186,11 @@ export class SpCpuChart { info('The time to load the first CPU Idle0 data is: ', durTime); }; - initSchedSliceData(arr: unknown[]): void { - Utils.SCHED_SLICE_MAP.clear(); + initSchedSliceData(arr: unknown[], traceId?: string): void { + Utils.getInstance().getSchedSliceMap(traceId).clear(); arr.forEach((value) => { - // @ts-ignore - Utils.SCHED_SLICE_MAP.set(`${value.itid}-${value.ts}`, { endState: value.endState, priority: value.priority }); + Utils.getInstance().getSchedSliceMap(traceId). // @ts-ignore + set(`${value.itid}-${value.ts}`, { endState: value.endState, priority: value.priority }); }); } diff --git a/ide/src/trace/component/chart/SpEBPFChart.ts b/ide/src/trace/component/chart/SpEBPFChart.ts index 082e5647c8d7e750f844b1e3057f2c5ae153d4a5..1a51e3a113f424d723754622d7f7061acc36ded6 100644 --- a/ide/src/trace/component/chart/SpEBPFChart.ts +++ b/ide/src/trace/component/chart/SpEBPFChart.ts @@ -36,11 +36,11 @@ export class SpEBPFChart { let sys = await hasFileSysData(); if (sys.length > 0) { //@ts-ignore - let fsCount = sys[0].fsCount ?? 0; + let fsCount = sys[0]['fsCount'] ?? 0; //@ts-ignore - let vmCount = sys[0].vmCount ?? 0; + let vmCount = sys[0]['vmCount'] ?? 0; //@ts-ignore - let ioCount = sys[0].ioCount ?? 0; + let ioCount = sys[0]['ioCount'] ?? 0; if (sys && sys.length > 0 && (fsCount > 0 || vmCount > 0 || ioCount > 0)) { let folder = await this.initFolder(); await this.initFileCallchain(); @@ -87,7 +87,7 @@ export class SpEBPFChart { // @ts-ignore this.trace.canvasPanelCtx?.clearRect(0, 0, fsFolder.frame.width, fsFolder.frame.height); } else { - (renders.empty as EmptyRender).renderMainThread( + (renders['empty'] as EmptyRender).renderMainThread( { context: this.trace.canvasPanelCtx, useCache: useCache, @@ -239,17 +239,17 @@ export class SpEBPFChart { initProcessDiskIOLatencyRead(i: number, folder: TraceRow, process: unknown): TraceRow { let rowRead = TraceRow.skeleton(); rowRead.index = 5 + 2 * i; //@ts-ignore - rowRead.rowId = `FileSystemDiskIOLatency-read-${process.ipid}`; + rowRead.rowId = `FileSystemDiskIOLatency-read-${process['ipid']}`; rowRead.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; rowRead.rowParentId = folder.rowId; rowRead.rowHidden = !folder.expansion; rowRead.style.height = '40px'; rowRead.style.width = '100%'; rowRead.setAttribute('children', ''); //@ts-ignore - rowRead.name = `${process.name ?? 'Process'}(${process.pid}) Max Read Latency`; + rowRead.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Read Latency`; rowRead.supplierFrame = async (): Promise => { //@ts-ignore - const res = await diskIoSender(false, process.ipid, [1, 3], TraceRow.range?.scale || 50, rowRead); + const res = await diskIoSender(false, process['ipid'], [1, 3], TraceRow.range?.scale || 50, rowRead); return res; }; rowRead.favoriteChangeHandler = this.trace.favoriteChangeHandler; @@ -271,7 +271,7 @@ export class SpEBPFChart { { context: context, useCache: useCache, //@ts-ignore - type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process.pid}`, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process['pid']}`, chartColor: ColorUtils.MD_PALETTE[0], }, rowRead @@ -285,17 +285,17 @@ export class SpEBPFChart { private initProcessDiskIOWrite(i: number, folder: TraceRow, process: unknown): TraceRow { let rowWrite = TraceRow.skeleton(); rowWrite.index = 5 + 2 * i + 1; //@ts-ignore - rowWrite.rowId = `FileSystemDiskIOLatency-write-${process.ipid}`; + rowWrite.rowId = `FileSystemDiskIOLatency-write-${process['ipid']}`; rowWrite.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; rowWrite.rowParentId = folder.rowId; rowWrite.rowHidden = !folder.expansion; rowWrite.style.height = '40px'; rowWrite.style.width = '100%'; rowWrite.setAttribute('children', ''); //@ts-ignore - rowWrite.name = `${process.name ?? 'Process'}(${process.pid}) Max Write Latency`; + rowWrite.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Write Latency`; rowWrite.supplierFrame = async (): Promise => { //@ts-ignore - const res = await diskIoSender(false, process.ipid, [2, 4], TraceRow.range?.scale || 50, rowWrite); + const res = await diskIoSender(false, process['ipid'], [2, 4], TraceRow.range?.scale || 50, rowWrite); return res; }; rowWrite.favoriteChangeHandler = this.trace.favoriteChangeHandler; @@ -317,7 +317,7 @@ export class SpEBPFChart { { context: context, useCache: useCache, //@ts-ignore - type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process.pid}`, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process['pid']}`, chartColor: ColorUtils.MD_PALETTE[8], }, rowWrite diff --git a/ide/src/trace/component/chart/SpFpsChart.ts b/ide/src/trace/component/chart/SpFpsChart.ts index 5c083ccba9e0bca5cffdfa9e58c0a4c8b0e784e5..c87a607182e68e169626fdbf8b710620016f7f26 100644 --- a/ide/src/trace/component/chart/SpFpsChart.ts +++ b/ide/src/trace/component/chart/SpFpsChart.ts @@ -61,7 +61,7 @@ export class SpFpsChart { context = fpsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } fpsRow.canvasSave(context); - (renders.fps as FpsRender).renderMainThread( + (renders['fps'] as FpsRender).renderMainThread( { context: context, useCache: useCache, diff --git a/ide/src/trace/component/chart/SpFrameTimeChart.ts b/ide/src/trace/component/chart/SpFrameTimeChart.ts index 70cbbd681fa73883ee4b481884657cea319e4ee9..cd17cb001f0444c9904b30baac9d2a299f31e6c5 100644 --- a/ide/src/trace/component/chart/SpFrameTimeChart.ts +++ b/ide/src/trace/component/chart/SpFrameTimeChart.ts @@ -119,7 +119,7 @@ export class SpFrameTimeChart { if (item.depth! >= maxDepth) { maxDepth = item.depth! + 1; } - item.frame_type = 'frameTime'; + item.frameType = 'frameTime'; item.cmdline = this.pidToProcessNameMap.get(item.pid!); item.rs_name = this.idToProcessNameMap.get(Number(item.rs_name)!); }); @@ -175,7 +175,7 @@ export class SpFrameTimeChart { if (item.depth! >= maxDepth) { maxDepth = item.depth! + 1; } - item.frame_type = 'frameTime'; + item.frameType = 'frameTime'; item.cmdline = this.pidToProcessNameMap.get(item.pid!); item.rs_name = this.idToProcessNameMap.get(Number(item.rs_name)!); item.type = '0'; diff --git a/ide/src/trace/component/chart/SpFreqChart.ts b/ide/src/trace/component/chart/SpFreqChart.ts index 1946f361bfe73f13517ed584dc04e898e726aef0..b5496db7148ad8ee307405a6e56853944c407ae2 100644 --- a/ide/src/trace/component/chart/SpFreqChart.ts +++ b/ide/src/trace/component/chart/SpFreqChart.ts @@ -20,7 +20,7 @@ import { ColorUtils } from '../trace/base/ColorUtils'; import { CpuFreqLimitRender, CpuFreqLimitsStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; import { CpuFreqStruct, FreqRender } from '../../database/ui-worker/ProcedureWorkerFreq'; import { CpuStateRender, CpuStateStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuState'; -import { folderSupplier, folderThreadHandler, getRowContext, rowThreadHandler } from './SpChartManager'; +import { folderSupplier, folderThreadHandler, rowThreadHandler } from './SpChartManager'; import { Utils } from '../trace/base/Utils'; import { cpuFreqDataSender } from '../../database/data-trafic/cpu/CpuFreqDataSender'; import { cpuStateSender } from '../../database/data-trafic/cpu/CpuStateSender'; @@ -32,85 +32,101 @@ import { queryCpuMaxFreq, queryCpuStateFilter, } from '../../database/sql/Cpu.sql'; -import { promises } from 'dns'; +import { BaseStruct } from '../../bean/BaseStruct'; export class SpFreqChart { - private trace: SpSystemTrace; //@ts-ignore - private folderRow: TraceRow | undefined; //@ts-ignore - private folderRowState: TraceRow | undefined; //@ts-ignore - private folderRowLimit: TraceRow | undefined; + private readonly trace: SpSystemTrace; constructor(trace: SpSystemTrace) { this.trace = trace; } - async init(): Promise { - let freqList = await queryCpuFreq(); - let cpuStateFilterIds = await queryCpuStateFilter(); + async init(parentRow?: TraceRow, traceId?: string): Promise { + let freqList = await queryCpuFreq(traceId); + let cpuStateFilterIds = await queryCpuStateFilter(traceId); //@ts-ignore this.trace.stateRowsId = cpuStateFilterIds; - let cpuFreqLimits = await getCpuLimitFreqId(); - let cpuFreqLimitsMax = await getCpuLimitFreqMax(cpuFreqLimits.map((limit) => limit.maxFilterId).join(',')); + let cpuFreqLimits = await getCpuLimitFreqId(traceId); + let cpuFreqLimitsMax = await getCpuLimitFreqMax(cpuFreqLimits.map((limit) => limit.maxFilterId).join(','), traceId); if (freqList.length > 0) { - this.folderRow = this.createFolderRow(); - this.folderRow.rowId = 'Cpu Frequency'; - this.folderRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_ALL; - this.folderRow.name = 'Cpu Frequency'; - this.trace.rowsEL?.appendChild(this.folderRow); + let folderRow = this.createFolderRow(traceId); + folderRow.rowId = 'Cpu Frequency'; + folderRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_ALL; + folderRow.name = 'Cpu Frequency'; + folderRow.selectChangeHandler = this.trace.selectChangeHandler; + this.trace.rowsEL?.appendChild(folderRow); info('Cpu Freq data size is: ', freqList!.length); - await this.addFreqRows(freqList); + await this.addFreqRows(freqList, folderRow, traceId); + if (parentRow) { + parentRow.addChildTraceRow(folderRow); + } else { + this.trace.rowsEL?.appendChild(folderRow); + } } if (cpuStateFilterIds.length > 0) { - this.folderRowState = this.createFolderRow(); - this.folderRowState.rowId = 'Cpu State'; - this.folderRowState.rowType = TraceRow.ROW_TYPE_CPU_STATE_ALL; - this.folderRowState.name = 'Cpu State'; - this.trace.rowsEL?.appendChild(this.folderRowState); - this.addStateRows(cpuStateFilterIds); + let folderRowState = this.createFolderRow(); + folderRowState.rowId = 'Cpu State'; + folderRowState.rowType = TraceRow.ROW_TYPE_CPU_STATE_ALL; + folderRowState.name = 'Cpu State'; + folderRowState.selectChangeHandler = this.trace.selectChangeHandler; + this.trace.rowsEL?.appendChild(folderRowState); + this.addStateRows(cpuStateFilterIds, folderRowState, traceId); + if (parentRow) { + parentRow.addChildTraceRow(folderRowState); + } else { + this.trace.rowsEL?.appendChild(folderRowState); + } } if (cpuFreqLimits.length > 0) { - this.folderRowLimit = this.createFolderRow(); - this.folderRowLimit.rowId = 'Cpu Freq Limit'; - this.folderRowLimit.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMITALL; - this.folderRowLimit.name = 'Cpu Freq Limit'; - this.trace.rowsEL?.appendChild(this.folderRowLimit); - this.addFreqLimitRows(cpuFreqLimits, cpuFreqLimitsMax); + let folderRowLimit = this.createFolderRow(); + folderRowLimit.rowId = 'Cpu Freq Limit'; + folderRowLimit.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMITALL; + folderRowLimit.name = 'Cpu Freq Limit'; + folderRowLimit.selectChangeHandler = this.trace.selectChangeHandler; + this.trace.rowsEL?.appendChild(folderRowLimit); + this.addFreqLimitRows(cpuFreqLimits, cpuFreqLimitsMax, folderRowLimit, traceId); + if (parentRow) { + parentRow.addChildTraceRow(folderRowLimit); + } else { + this.trace.rowsEL?.appendChild(folderRowLimit); + } } } - //@ts-ignore - createFolderRow(): TraceRow { - //@ts-ignore - let folder = new TraceRow(); + createFolderRow(traceId?: string): TraceRow { + let folder = TraceRow.skeleton(traceId); folder.rowParentId = ''; folder.folder = true; folder.style.height = '40px'; folder.rowHidden = folder.expansion; folder.setAttribute('children', ''); - // @ts-ignore folder.supplier = folderSupplier(); folder.onThreadHandler = folderThreadHandler(folder, this.trace); return folder; } - async addFreqRows(freqList: Array): Promise { - let freqMaxList = await queryCpuMaxFreq(); //@ts-ignore - CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; //@ts-ignore + async addFreqRows( + freqList: Array<{ cpu: number; filterId: number }>, + folderRow: TraceRow, + traceId?: string + ): Promise { + let freqMaxList = await queryCpuMaxFreq(traceId); + CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; let maxFreqObj = Utils.getFrequencyWithUnit(freqMaxList[0].maxFreq); CpuFreqStruct.maxFreq = maxFreqObj.maxFreq; CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName; for (let i = 0; i < freqList.length; i++) { const it = freqList[i]; - let traceRow = TraceRow.skeleton(); //@ts-ignore + let traceRow = TraceRow.skeleton(traceId); traceRow.rowId = `${it.filterId}`; traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ; traceRow.rowParentId = ''; - traceRow.style.height = '40px'; //@ts-ignore + traceRow.style.height = '40px'; traceRow.name = `Cpu ${it.cpu} Frequency`; traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - traceRow.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore - traceRow.supplierFrame = (): Promise => cpuFreqDataSender(it.cpu, traceRow); //queryCpuFreqData - traceRow.focusHandler = (ev): void => { + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.supplierFrame = (): Promise => cpuFreqDataSender(it.cpu, traceRow); + traceRow.focusHandler = (): void => { this.trace?.displayTip( traceRow, CpuFreqStruct.hoverCpuFreqStruct, @@ -124,33 +140,35 @@ export class SpFreqChart { 'freq', 'context', { - //@ts-ignore type: `freq${it.cpu}`, }, traceRow, this.trace ); - this.folderRow!.addChildTraceRow(traceRow); + folderRow!.addChildTraceRow(traceRow); } } - addStateRows(cpuStateFilterIds: Array): void { + addStateRows( + cpuStateFilterIds: Array<{ cpu: number; filterId: number }>, + folderRowState: TraceRow, + traceId?: string + ): void { for (let it of cpuStateFilterIds) { - let cpuStateRow = TraceRow.skeleton(); //@ts-ignore + let cpuStateRow = TraceRow.skeleton(traceId); cpuStateRow.rowId = `${it.filterId}`; cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE; cpuStateRow.rowParentId = ''; - cpuStateRow.style.height = '40px'; //@ts-ignore + cpuStateRow.style.height = '40px'; cpuStateRow.name = `Cpu ${it.cpu} State`; cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler; cpuStateRow.supplierFrame = async (): Promise => { - //@ts-ignore - let rs = await cpuStateSender(it.filterId, cpuStateRow); //@ts-ignore + let rs = await cpuStateSender(it.filterId, cpuStateRow); rs.forEach((t) => (t.cpu = it.cpu)); return rs; }; - cpuStateRow.focusHandler = (ev): void => { + cpuStateRow.focusHandler = (): void => { this.trace.displayTip( cpuStateRow, CpuStateStruct.hoverStateStruct, @@ -164,37 +182,40 @@ export class SpFreqChart { 'cpu-state', 'cpuStateContext', { - //@ts-ignore - type: `cpu-state-${it.cpu}`, //@ts-ignore + type: `cpu-state-${it.cpu}`, cpu: it.cpu, }, cpuStateRow, this.trace ); - this.folderRowState!.addChildTraceRow(cpuStateRow); + folderRowState!.addChildTraceRow(cpuStateRow); } } - addFreqLimitRows(cpuFreqLimits: Array, cpuFreqLimitsMax: Array): void { + addFreqLimitRows( + cpuFreqLimits: Array, + cpuFreqLimitsMax: Array<{ maxValue: number; filterId: number }>, + folderRowLimit: TraceRow, + traceId?: string + ): void { for (let limit of cpuFreqLimits) { let findMax = Utils.getFrequencyWithUnit( - //@ts-ignore cpuFreqLimitsMax.find((maxLimit) => maxLimit.filterId === limit.maxFilterId)?.maxValue || 0 ); - let cpuFreqLimitRow = TraceRow.skeleton(); //@ts-ignore + let cpuFreqLimitRow = TraceRow.skeleton(traceId); cpuFreqLimitRow.rowId = `${limit.cpu}`; cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT; cpuFreqLimitRow.rowParentId = ''; - cpuFreqLimitRow.style.height = '40px'; //@ts-ignore + cpuFreqLimitRow.style.height = '40px'; cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit`; cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore - cpuFreqLimitRow.setAttribute('maxFilterId', `${limit.maxFilterId}`); //@ts-ignore - cpuFreqLimitRow.setAttribute('minFilterId', `${limit.minFilterId}`); //@ts-ignore + cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; + cpuFreqLimitRow.setAttribute('maxFilterId', `${limit.maxFilterId}`); + cpuFreqLimitRow.setAttribute('minFilterId', `${limit.minFilterId}`); cpuFreqLimitRow.setAttribute('cpu', `${limit.cpu}`); cpuFreqLimitRow.supplierFrame = async (): Promise => { - //@ts-ignore - const res = await cpuFreqLimitSender(limit.maxFilterId, limit.minFilterId, limit.cpu, cpuFreqLimitRow); //@ts-ignore + const res = + await cpuFreqLimitSender(limit.maxFilterId, limit.minFilterId, limit.cpu, cpuFreqLimitRow); res.forEach((item) => (item.cpu = limit.cpu)); return res; }; @@ -216,8 +237,7 @@ export class SpFreqChart { 'cpu-limit-freq', 'context', { - //@ts-ignore - type: `cpu-limit-freq-${limit.cpu}`, //@ts-ignore + type: `cpu-limit-freq-${limit.cpu}`, cpu: limit.cpu, maxFreq: findMax?.maxFreq || 0, maxFreqName: findMax?.maxFreqName || '', @@ -225,7 +245,7 @@ export class SpFreqChart { cpuFreqLimitRow, this.trace ); - this.folderRowLimit!.addChildTraceRow(cpuFreqLimitRow); + folderRowLimit!.addChildTraceRow(cpuFreqLimitRow); } } } diff --git a/ide/src/trace/component/chart/SpGpuCounterChart.ts b/ide/src/trace/component/chart/SpGpuCounterChart.ts new file mode 100644 index 0000000000000000000000000000000000000000..37e3a8169b2a99e8e6633eb886fdacf80568c93a --- /dev/null +++ b/ide/src/trace/component/chart/SpGpuCounterChart.ts @@ -0,0 +1,428 @@ +/* + * 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 { SpSystemTrace } from '../SpSystemTrace'; +import { TraceRow } from '../trace/base/TraceRow'; +import { renders } from '../../database/ui-worker/ProcedureWorker'; +import { + GpuCounterStruct, + maleoon_counter_obj, + gpu_counter_type, + GpuCounterRender, +} from '../../database/ui-worker/ProcedureWorkerGpuCounter'; +import { folderSupplier, folderThreadHandler } from './SpChartManager'; +import { queryRangeTime } from '../../database/sql/SqlLite.sql'; + +export class SpGpuCounterChart { + trace: SpSystemTrace; + private folderRow: TraceRow | undefined; + constructor(trace: SpSystemTrace) { + this.trace = trace; + } + + async init(res: Array) { + if (res.length === 0) { + let startTime = await queryRangeTime(); + this.initFolder(res, false); + //@ts-ignore + this.addTraceRowEventListener(startTime[0].start_ts, startTime[0].end_ts); + } else { + const { gpuCounterType, start_time } = this.handleCsvData(res); + this.initFolder(res, true); + await this.initGpuCounters(gpuCounterType, start_time); + } + } + + initFolder(res: Array, isSimpleUpload: boolean): void { + this.folderRow = TraceRow.skeleton(); + this.folderRow.rowId = 'GpuCounter'; + this.folderRow.index = 0; + this.folderRow.rowType = TraceRow.ROW_TYPE_GPU_COUNTER_GROUP; + this.folderRow.rowParentId = ''; + this.folderRow.style.height = '40px'; + this.folderRow.rowHidden = this.folderRow!.expansion; + this.folderRow.setAttribute('children', ''); + this.folderRow.folder = res.length > 0 ? true : false; + this.folderRow.name = 'Gpu counter'; + //@ts-ignore + this.folderRow.supplier = folderSupplier(); + this.folderRow.onThreadHandler = folderThreadHandler(this.folderRow, this.trace); + if (!isSimpleUpload) this.folderRow.addRowSampleUpload('.csv'); + this.folderRow.addEventListener('expansion-change', this.trace.extracted(this.folderRow)); + this.trace.rowsEL?.appendChild(this.folderRow); + } + + async initGpuCounters(gpuCounterType: any, start_time: number) { + for (const key in gpuCounterType) { + let typeRows = TraceRow.skeleton(); + typeRows.rowId = key; + typeRows.rowType = TraceRow.ROW_TYPE_GPU_COUNTER; + typeRows.rowParentId = this.folderRow?.rowId; + typeRows.folder = true; + typeRows.folderTextLeft = 20; + typeRows.rowHidden = !this.folderRow!.expansion; + typeRows.style.height = '40px'; + typeRows.name = `${key}`; + typeRows.selectChangeHandler = this.trace.selectChangeHandler; + //@ts-ignore + typeRows.supplier = folderSupplier(); + typeRows.onThreadHandler = folderThreadHandler(typeRows, this.trace); + this.folderRow!.addChildTraceRow(typeRows); + this.initTypeRow(gpuCounterType[key], key, typeRows, start_time); + } + } + + initTypeRow(rowList: any, key: string, parentRow: any, start_time: number) { + const typeName = this.getKeyTypeName(key); + for (let i = 0; i < rowList.length; i++) { + let typeRow = TraceRow.skeleton(); + let maxValue = Math.max(...rowList[i].map((it: GpuCounterStruct) => Number(it.height))); + typeRow.rowId = `${typeName[i]}`; + typeRow.rowType = TraceRow.ROW_TYPE_GPU_COUNTER; + typeRow.rowParentId = key; + typeRow.folder = false; + typeRow.folderTextLeft = 40; + typeRow.style.height = '40px'; + typeRow.rowHidden = !parentRow.expansion; + typeRow.setAttribute('children', ''); + typeRow.name = `${typeName[i]}`; + typeRow.selectChangeHandler = this.trace.selectChangeHandler; + typeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + typeRow.focusHandler = () => this.focusHandler(typeRow, GpuCounterStruct.hoverGpuCounterStruct!); + typeRow.findHoverStruct = () => { + GpuCounterStruct.hoverGpuCounterStruct = typeRow.getHoverStruct(false); + }; + typeRow.supplierFrame = () => + new Promise((resolve): void => { + resolve(rowList[i]); + }); + typeRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (typeRow.currentContext) { + context = typeRow.currentContext; + } else { + context = typeRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + typeRow.canvasSave(context); + (renders.gpuCounter as GpuCounterRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${typeName[i]}`, + startTime: start_time, + maxValue: maxValue, + }, + typeRow + ); + typeRow.canvasRestore(context); + }; + parentRow.addChildTraceRow(typeRow); + } + } + + focusHandler(row: TraceRow, struct: GpuCounterStruct) { + let tip = ''; + if (struct) { + tip = ` + ${struct.height} + `; + } + this.trace?.displayTip(row, struct, tip); + } + + getKeyTypeName(key: string) { + const typeName: { [key: string]: Array } = { + cycle: ['gpu clocks', 'tiler utilization', 'binning utilization', 'rendering utilization', 'compute utilization'], + drawcall: [ + 'drawcall count', + 'vertex count', + 'primitives count', + 'visible primitives count', + 'compute invocations count', + ], + shader_cycle: [ + 'shader utilization', + 'eu utilization', + 'eu stall utilization', + 'eu idle utilization', + 'control flow instr utilization', + 'half float instr utilization', + 'tu utilization', + ], + local_count: ['concurrent warps', 'instruction count', 'quads count', 'texels count'], + local_wr: ['memory read', 'memory write', 'memory traffic'], + }; + return typeName[key]; + } + + handleCsvData(res: any, start_ts: number = 0, end_ts: number = 0) { + const minIndex = this.getMinData(res) + 1; + const gpuCounterMap = this.initGpuCounterMap(); + this.maleoon_gpu_counter_init(gpuCounterMap, res[0]); + let start_time_data = res[minIndex].split(','); + let start_time = Number(start_time_data[gpuCounterMap.timestamp]); + let last_record_time = 0; + let maleoonCounter = new maleoon_counter_obj(); + let read_line_num = res.length - 1; + let utilization_array = [ + 'tiler_utilization', + 'binning_utilization', + 'rendering_utilization', + 'compute_utilization', + 'shader_utilization', + 'eu_utilization', + 'eu_stall_utilization', + 'eu_idle_utilization', + 'control_flow_instr_utilization', + 'half_float_instr_utilization', + 'tu_utilization', + 'concurrent_warps', + ]; + + let count_array = [ + 'gpu_clocks', + 'drawcall_count', + 'vertex_count', + 'primitives_count', + 'visible_primitives_count', + 'instruction_count', + 'quads_count', + 'texels_count', + 'compute_invocations_count', + 'memory_read', + 'memory_write', + 'memory_traffic', + ]; + + for (let i = minIndex; i < read_line_num; i++) { + let datas = res[i].split(','); + if (datas.length != 25) continue; + if ( + (start_ts > 0 && Number(datas[gpuCounterMap.timestamp]) < start_ts) || + (end_ts > 0 && Number(datas[gpuCounterMap.timestamp]) > end_ts) + ) + continue; + let time_passed = Number(datas[gpuCounterMap.timestamp]) - start_time; + //去重 + if (time_passed <= last_record_time) continue; + time_passed -= last_record_time; + last_record_time += time_passed; + utilization_array.forEach((item) => { + maleoonCounter[item].push({ + startNS: Number(datas[gpuCounterMap.timestamp]), + height: gpuCounterMap[item] === -1 ? 0 : Math.floor(Number(datas[gpuCounterMap[item]])), + }); + }); + count_array.forEach((item) => { + maleoonCounter[item].push({ + startNS: Number(datas[gpuCounterMap.timestamp]), + height: gpuCounterMap[item] === -1 ? 0 : Math.floor(Number(datas[gpuCounterMap[item]])), + }); + }); + } + utilization_array.forEach((item) => { + for (let i = 0; i < maleoonCounter[item].length; i++) { + maleoonCounter[item][i].dur = maleoonCounter[item][i + 1]?.startNS - maleoonCounter[item][i].startNS || 0; + } + }); + count_array.forEach((item) => { + for (let i = 0; i < maleoonCounter[item].length; i++) { + maleoonCounter[item][i].dur = maleoonCounter[item][i + 1]?.startNS - maleoonCounter[item][i].startNS || 0; + } + }); + const gpuCounterType = this.groupByGpuCounterType(maleoonCounter); + return { gpuCounterType, start_time }; + } + + initGpuCounterMap(): any { + let gpu_counter_map = { + timestamp: -1, + + gpu_clocks: -1, + tiler_utilization: -1, + binning_utilization: -1, + rendering_utilization: -1, + compute_utilization: -1, + + drawcall_count: -1, + vertex_count: -1, + primitives_count: -1, + visible_primitives_count: -1, + compute_invocations_count: -1, + + shader_utilization: -1, + eu_utilization: -1, + eu_stall_utilization: -1, + eu_idle_utilization: -1, + control_flow_instr_utilization: -1, + half_float_instr_utilization: -1, + tu_utilization: -1, + + concurrent_warps: -1, + instruction_count: -1, + quads_count: -1, + texels_count: -1, + + memory_read: -1, + memory_write: -1, + memory_traffic: -1, + }; + return gpu_counter_map; + } + + maleoon_gpu_counter_init(gpu_counter_map: any, head_line: string) { + gpu_counter_map.timestamp = -1; + + gpu_counter_map.gpu_clocks = -1; + gpu_counter_map.tiler_utilization = -1; + gpu_counter_map.binning_utilization = -1; + gpu_counter_map.rendering_utilization = -1; + gpu_counter_map.compute_utilization = -1; + + gpu_counter_map.drawcall_count = -1; + gpu_counter_map.vertex_count = -1; + gpu_counter_map.primitives_count = -1; + gpu_counter_map.visible_primitives_count = -1; + gpu_counter_map.compute_invocations_count = -1; + + gpu_counter_map.shader_utilization = -1; + gpu_counter_map.eu_utilization = -1; + gpu_counter_map.eu_stall_utilization = -1; + gpu_counter_map.eu_idle_utilization = -1; + gpu_counter_map.control_flow_instr_utilization = -1; + gpu_counter_map.half_float_instr_utilization = -1; + gpu_counter_map.tu_utilization = -1; + + gpu_counter_map.concurrent_warps = -1; + gpu_counter_map.instruction_count = -1; + gpu_counter_map.quads_count = -1; + gpu_counter_map.texels_count = -1; + + gpu_counter_map.memory_read = -1; + gpu_counter_map.memory_write = -1; + gpu_counter_map.memory_traffic = -1; + + let paras = head_line.split(','); + for (let i = 0; i < paras.length; i++) { + if (paras[i] === 'TIMESTAMP') gpu_counter_map.timestamp = i; + + if (paras[i] === 'GPU Clocks') gpu_counter_map.gpu_clocks = i; + if (paras[i] === 'Tiler Utilization') gpu_counter_map.tiler_utilization = i; + if (paras[i] === 'Binning Queue Utilization') gpu_counter_map.binning_utilization = i; + if (paras[i] === 'Rendering Queue Utilization') gpu_counter_map.rendering_utilization = i; + if (paras[i] === 'Compute Queue Utilization') gpu_counter_map.compute_utilization = i; + + if (paras[i] === 'Drawcalls Count') gpu_counter_map.drawcall_count = i; + if (paras[i] === 'Vertex Count') gpu_counter_map.vertex_count = i; + if (paras[i] === 'Primitive Count') gpu_counter_map.primitives_count = i; + if (paras[i] === 'Visible Primitive Count') gpu_counter_map.visible_primitives_count = i; + if (paras[i] === 'Compute Shader Invocations') gpu_counter_map.compute_invocations_count = i; + + if (paras[i] === 'Shader Core Utilization') gpu_counter_map.shader_utilization = i; + if (paras[i] === 'EU Utilization') gpu_counter_map.eu_utilization = i; + if (paras[i] === 'EU Stall') gpu_counter_map.eu_stall_utilization = i; + if (paras[i] === 'EU Idle') gpu_counter_map.eu_idle_utilization = i; + if (paras[i] === 'Instructions Diverged') gpu_counter_map.control_flow_instr_utilization = i; + if (paras[i] === 'Half-float Instructions') gpu_counter_map.half_float_instr_utilization = i; + if (paras[i] === 'TU Utilization') gpu_counter_map.tu_utilization = i; + + if (paras[i] === 'Concurrent Warps') gpu_counter_map.concurrent_warps = i; + if (paras[i] === 'Instructions Executed') gpu_counter_map.instruction_count = i; + if (paras[i] === 'Quads Shaded') gpu_counter_map.quads_count = i; + if (paras[i] === 'Texels Sampled') gpu_counter_map.texels_count = i; + + if (paras[i] === 'External Memory Read') gpu_counter_map.memory_read = i; + if (paras[i] === 'External Memory Write') gpu_counter_map.memory_write = i; + if (paras[i] === 'External Memory Traffic') gpu_counter_map.memory_traffic = i; + } + } + + groupByGpuCounterType(maleoonCounter: maleoon_counter_obj) { + const gpuCounterType = new gpu_counter_type(); + let index = 0; + for (const key in maleoonCounter) { + if (index < 5) { + gpuCounterType['cycle'].push(maleoonCounter[key]); + } + if (index >= 5 && index < 10) { + gpuCounterType['drawcall'].push(maleoonCounter[key]); + } + if (index >= 10 && index < 17) { + gpuCounterType['shader_cycle'].push(maleoonCounter[key]); + } + if (index >= 17 && index < 21) { + gpuCounterType['local_count'].push(maleoonCounter[key]); + } + if (index >= 21 && index < 24) { + gpuCounterType['local_wr'].push(maleoonCounter[key]); + } + index++; + } + return gpuCounterType; + } + + /** + * 监听文件上传事件 + * @param row + * @param start_ts + */ + addTraceRowEventListener(startTime: number, endTime: number) { + this.folderRow?.uploadEl?.addEventListener('sample-file-change', (e: any) => { + this.getCsvData(e).then((res: any) => { + this.resetChartData(this.folderRow!); + const { gpuCounterType } = this.handleCsvData(res, startTime, endTime); + this.initGpuCounters(gpuCounterType, startTime); + if (!this.folderRow!.folder) this.folderRow!.folder = true; + }); + }); + } + + /** + * 清空缓存 + * @param row + */ + resetChartData(row: TraceRow) { + if (row.expansion) row.describeEl?.click(); + row.childrenList = []; + } + + getMinData(list: Array) { + const sliceList = list.slice(1, 11).map((item) => Number(item.split(',')[0])); + const nonZeroList = sliceList.filter((item) => item !== 0).sort((a, b) => a - b); + const minIndex = sliceList.findIndex((item) => item === nonZeroList[0]); + return minIndex; + } + + /** + * 获取上传的文件内容 转为json格式 + * @param file + * @returns + */ + getCsvData(file: any): Promise { + return new Promise((resolve, reject) => { + let reader = new FileReader(); + reader.readAsText(file.detail || file); + reader.onloadend = (e: any) => { + const fileContent = e.target?.result.split(/[\r\n]/).filter(Boolean); + try { + resolve(fileContent); + document.dispatchEvent(new CustomEvent('file-correct')); + } catch (error) { + document.dispatchEvent(new CustomEvent('file-error')); + } + }; + }); + } +} diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index 431c8171e3fa5a7b1179cf6dc5b11504869a5905..92d811e2388e60121d9035c34e186215affb2de8 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -53,7 +53,7 @@ export interface ResultData { existF: boolean | null | undefined; fValue: number; } - +const FOLD_HEIGHT = 20; export class SpHiPerf { static selectCpuStruct: HiPerfCpuStruct | undefined; static stringResult: ResultData | undefined; @@ -122,7 +122,6 @@ export class SpHiPerf { async initFolder(): Promise { let row = TraceRow.skeleton(); - row.setAttribute('disabled-check', ''); row.rowId = 'HiPerf'; row.index = 0; row.rowType = TraceRow.ROW_TYPE_HIPERF; @@ -199,7 +198,7 @@ export class SpHiPerf { perfCallCutRow.rowId = 'HiPerf-callchart'; perfCallCutRow.index = 0; perfCallCutRow.rowType = TraceRow.ROW_TYPE_PERF_CALLCHART; - perfCallCutRow.enableCollapseChart(); + perfCallCutRow.enableCollapseChart(FOLD_HEIGHT, this.trace); perfCallCutRow.rowParentId = 'HiPerf'; perfCallCutRow.rowHidden = !this.rowFolder.expansion; perfCallCutRow.folder = false; @@ -222,14 +221,14 @@ export class SpHiPerf { id: this.callChartId, }); // @ts-ignore - let maxHeight = res.maxDepth * 20; + let maxHeight = res.maxDepth * FOLD_HEIGHT; perfCallCutRow.funcMaxHeight = maxHeight; if (perfCallCutRow.funcExpand) { perfCallCutRow!.style.height = `${maxHeight}px`; if (perfCallCutRow.collect) { window.publish(window.SmartEvent.UI.RowHeightChange, { expand: true, - value: perfCallCutRow.funcMaxHeight - 20, + value: perfCallCutRow.funcMaxHeight - FOLD_HEIGHT, }); } } @@ -319,18 +318,15 @@ export class SpHiPerf { row.rowSettingList = [ ...cpuData.reverse().map( ( - it: unknown + it: any ): { key: string; title: string; checked?: boolean; } => { return { - // @ts-ignore key: `${it.cpu_id}-c`, - // @ts-ignore checked: it.cpu_id === 0, - // @ts-ignore title: `cpu${it.cpu_id}`, }; } @@ -577,7 +573,10 @@ export class SpHiPerf { } resetAllChartData(): void { - this.rowList?.forEach((row) => this.resetChartData(row)); + const callChartRow = this.rowList?.find(row => row.rowId === 'HiPerf-callchart'); + if (callChartRow){ + this.resetChartData(callChartRow); + } } hoverTip( diff --git a/ide/src/trace/component/chart/SpIrqChart.ts b/ide/src/trace/component/chart/SpIrqChart.ts index cfc0cbadf9a3eaf15fbefe71fc44c6d391568c93..238fc769e2490fbae01eb9a3d5519458365b7bcb 100644 --- a/ide/src/trace/component/chart/SpIrqChart.ts +++ b/ide/src/trace/component/chart/SpIrqChart.ts @@ -21,64 +21,75 @@ import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { IrqRender, IrqStruct } from '../../database/ui-worker/ProcedureWorkerIrq'; import { irqDataSender } from '../../database/data-trafic/IrqDataSender'; import { queryAllIrqNames, queryIrqList } from '../../database/sql/Irq.sql'; -import { getRowContext, rowThreadHandler } from './SpChartManager'; +import { rowThreadHandler } from './SpChartManager'; +import { BaseStruct } from '../../bean/BaseStruct'; export class SpIrqChart { - private trace: SpSystemTrace; - private irqNameMap: Map = new Map(); + private readonly trace: SpSystemTrace; constructor(trace: SpSystemTrace) { this.trace = trace; } - async init(): Promise { - let folder = await this.initFolder(); - await this.initData(folder); - } - - //@ts-ignore - async initData(folder: TraceRow): Promise { + async init(parentRow?: TraceRow, traceId?: string): Promise { let irqStartTime = new Date().getTime(); - let irqList = await queryIrqList(); + let irqList = await queryIrqList(traceId); if (irqList.length === 0) { return; } + let folder = await this.initFolder(traceId); + parentRow?.addChildTraceRow(folder); + await this.initData(folder, irqStartTime, irqList, traceId); + } + + async initData( + folder: TraceRow, + irqStartTime: number, + irqList: Array<{ name: string; cpu: number }>, + traceId?: string, + ): Promise { //加载irq table所有id和name数据 - let irqNamesArray = await queryAllIrqNames(); + let irqNamesArray = await queryAllIrqNames(traceId); + let irqNameMap: Map = new Map(); irqNamesArray.forEach((it) => { - this.irqNameMap.set(it.id, { ipiName: it.ipiName, name: it.name }); + irqNameMap.set(it.id, it.ipiName); }); info('irqList data size is: ', irqList!.length); - this.trace.rowsEL?.appendChild(folder); + if (!traceId) { + this.trace.rowsEL?.appendChild(folder); + } for (let i = 0; i < irqList.length; i++) { const it = irqList[i]; - this.addIrqRow(it, i, folder); + this.addIrqRow(it, i, folder, irqNameMap, traceId); } let durTime = new Date().getTime() - irqStartTime; info('The time to load the ClockData is: ', durTime); } - //@ts-ignore - addIrqRow(it: unknown, index: number, folder: TraceRow): void { - let traceRow = TraceRow.skeleton(); - //@ts-ignore + addIrqRow( + it: { name: string; cpu: number }, + index: number, + folder: TraceRow, + irqNameMap: Map, + traceId?: string, + ): void { + let traceRow = TraceRow.skeleton(traceId); traceRow.rowId = it.name + it.cpu; traceRow.rowType = TraceRow.ROW_TYPE_IRQ; traceRow.rowParentId = folder.rowId; - traceRow.style.height = '40px'; //@ts-ignore + traceRow.style.height = '40px'; traceRow.name = `${it.name} Cpu ${it.cpu}`; traceRow.rowHidden = !folder.expansion; - traceRow.setAttribute('children', ''); //@ts-ignore - traceRow.setAttribute('callId', `${it.cpu}`); //@ts-ignore + traceRow.setAttribute('children', ''); + traceRow.setAttribute('callId', `${it.cpu}`); traceRow.setAttribute('cat', `${it.name}`); traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; traceRow.selectChangeHandler = this.trace.selectChangeHandler; traceRow.supplierFrame = (): Promise => { - //@ts-ignore return irqDataSender(it.cpu, it.name, traceRow).then((irqs) => { irqs.forEach((irq): void => { - let irqData = this.irqNameMap.get(irq.id!); //@ts-ignore - irq.name = (it.name === 'irq' ? irqData?.ipiName : irqData?.name) || ''; + let irqName = irqNameMap.get(irq.id!); + irq.name = irqName || ''; }); return irqs; }); @@ -97,7 +108,6 @@ export class SpIrqChart { 'irq', 'context', { - //@ts-ignore type: it.name, index: index, }, @@ -107,23 +117,21 @@ export class SpIrqChart { folder.addChildTraceRow(traceRow); } - //@ts-ignore - async initFolder(): Promise> { - let irqFolder = TraceRow.skeleton(); - irqFolder.rowId = 'Irs'; + async initFolder(traceId?: string): Promise> { + let irqFolder = TraceRow.skeleton(traceId); + irqFolder.rowId = 'Irqs'; irqFolder.index = 0; irqFolder.rowType = TraceRow.ROW_TYPE_IRQ_GROUP; irqFolder.rowParentId = ''; irqFolder.style.height = '40px'; irqFolder.folder = true; - irqFolder.name = 'Irs'; /* & I/O Latency */ + irqFolder.name = 'Irqs'; /* & I/O Latency */ irqFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; - irqFolder.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore - irqFolder.supplier = (): Promise> => new Promise>((resolve) => resolve([])); + irqFolder.selectChangeHandler = this.trace.selectChangeHandler; + irqFolder.supplier = (): Promise> => new Promise>((resolve) => resolve([])); irqFolder.onThreadHandler = (useCache): void => { irqFolder.canvasSave(this.trace.canvasPanelCtx!); if (irqFolder.expansion) { - // @ts-ignore this.trace.canvasPanelCtx?.clearRect(0, 0, irqFolder.frame.width, irqFolder.frame.height); } else { (renders.empty as EmptyRender).renderMainThread( diff --git a/ide/src/trace/component/chart/SpLTPO.ts b/ide/src/trace/component/chart/SpLTPO.ts index 9014a8c357b4f0a71d6365b04225a009fc259226..3c1ca8ac6e550a9dddf7b15546a432651038f8cd 100644 --- a/ide/src/trace/component/chart/SpLTPO.ts +++ b/ide/src/trace/component/chart/SpLTPO.ts @@ -29,7 +29,6 @@ import { import { LtpoRender, LtpoStruct } from '../../database/ui-worker/ProcedureWorkerLTPO'; import { HitchTimeStruct, hitchTimeRender } from '../../database/ui-worker/ProcedureWorkerHitchTime'; import { lostFrameSender } from '../../database/data-trafic/LostFrameSender'; -import { fps } from '../../database/ui-worker/ProcedureWorkerFPS'; export class SpLtpoChart { private readonly trace: SpSystemTrace | undefined; @@ -239,28 +238,26 @@ export class SpLtpoChart { } //render_service的nowTime 集成RSHardThread泳道Fps数组的FenceId和Signaled fpsToRenderService(): void { - if (SpLtpoChart.signaledList.length || SpLtpoChart.skipDataList.length) { - let rsIndex = 0; - let hardIndex = 0; - while (rsIndex < SpLtpoChart.rsNowTimeList.length) { - if (SpLtpoChart.fpsnameList[hardIndex] && SpLtpoChart.rsNowTimeList[rsIndex]) { - if (SpLtpoChart.rsNowTimeList[rsIndex].nowTime! > SpLtpoChart.fpsnameList[hardIndex].nowTime!) { - //处理nowTime不一致的情况 - hardIndex++; - } else if (SpLtpoChart.rsNowTimeList[rsIndex].nowTime! < SpLtpoChart.fpsnameList[hardIndex].nowTime!) { - rsIndex++; - } else { - SpLtpoChart.rsNowTimeList[rsIndex].fanceId = SpLtpoChart.fpsnameList[hardIndex].fanceId; - SpLtpoChart.rsNowTimeList[rsIndex].fps = SpLtpoChart.fpsnameList[hardIndex].fps; - if (SpLtpoChart.fpsnameList[hardIndex].signaled) { - SpLtpoChart.rsNowTimeList[rsIndex].signaled = SpLtpoChart.fpsnameList[hardIndex].signaled; - } - hardIndex++; - rsIndex++; - } + let rsIndex = 0; + let hardIndex = 0; + while (rsIndex < SpLtpoChart.rsNowTimeList.length) { + if (SpLtpoChart.fpsnameList[hardIndex] && SpLtpoChart.rsNowTimeList[rsIndex]) { + if (SpLtpoChart.rsNowTimeList[rsIndex].nowTime! > SpLtpoChart.fpsnameList[hardIndex].nowTime!) { + //处理nowTime不一致的情况 + hardIndex++; + } else if (SpLtpoChart.rsNowTimeList[rsIndex].nowTime! < SpLtpoChart.fpsnameList[hardIndex].nowTime!) { + rsIndex++; } else { - return; + SpLtpoChart.rsNowTimeList[rsIndex].fanceId = SpLtpoChart.fpsnameList[hardIndex].fanceId; + SpLtpoChart.rsNowTimeList[rsIndex].fps = SpLtpoChart.fpsnameList[hardIndex].fps; + if (SpLtpoChart.fpsnameList[hardIndex].signaled) { + SpLtpoChart.rsNowTimeList[rsIndex].signaled = SpLtpoChart.fpsnameList[hardIndex].signaled; + } + hardIndex++; + rsIndex++; } + } else { + return; } } } @@ -304,7 +301,7 @@ export class SpLtpoChart { } } pushLtpoData( - lptoArr: unknown[] | undefined, + lptoArr: any[] | undefined, fanceId: Number, fps: Number, signaled: Number, @@ -334,19 +331,16 @@ export class SpLtpoChart { while (presentIndex < presentArr.length) { if (presentArr[presentIndex] && ltpoDataArr[ltpoIndex]) { if ( - //@ts-ignore - presentArr[presentIndex].startTime! + presentArr[presentIndex].dur! - (window as unknown).recordStartNS === + presentArr[presentIndex].startTime! + presentArr[presentIndex].dur! - (window as any).recordStartNS === TraceRow.range!.totalNS ) { presentArr.splice(presentIndex, 1); } if (presentArr[presentIndex].presentId === ltpoDataArr[ltpoIndex].fanceId) { - ltpoDataArr[ltpoIndex].startTs = - //@ts-ignore - Number(presentArr[presentIndex].startTime) - (window as unknown).recordStartNS; + ltpoDataArr[ltpoIndex].startTs = Number(presentArr[presentIndex].startTime) - (window as any).recordStartNS; ltpoDataArr[ltpoIndex].dur = presentArr[presentIndex].dur; - ltpoDataArr[ltpoIndex].nextStartTs = presentArr[presentIndex + 1] //@ts-ignore - ? Number(presentArr[presentIndex + 1].startTime) - (window as unknown).recordStartNS + ltpoDataArr[ltpoIndex].nextStartTs = presentArr[presentIndex + 1] + ? Number(presentArr[presentIndex + 1].startTime) - (window as any).recordStartNS : ''; ltpoDataArr[ltpoIndex].nextDur = presentArr[presentIndex + 1] ? presentArr[presentIndex + 1].dur : 0; presentIndex++; @@ -364,13 +358,38 @@ export class SpLtpoChart { let sendStartTs: number | undefined = 0; let sendDur: number | undefined = 0; let cutSendDur: number | undefined = 0; - if (ltpoDataArr[ltpoDataIndex].fanceId !== -1 && ltpoDataArr[ltpoDataIndex].nextDur) { - sendStartTs = Number(ltpoDataArr[ltpoDataIndex].startTs) + Number(ltpoDataArr[ltpoDataIndex].dur); - sendDur = - Number(ltpoDataArr[ltpoDataIndex].nextStartTs) + Number(ltpoDataArr[ltpoDataIndex].nextDur) - sendStartTs; - } if (ltpoDataArr[ltpoDataIndex] && SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex]) { if (ltpoDataArr[ltpoDataIndex].fanceId! < SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].fanceId!) { + if (ltpoDataArr[ltpoDataIndex].fanceId !== -1 && ltpoDataArr[ltpoDataIndex].nextDur) { + sendStartTs = Number(ltpoDataArr[ltpoDataIndex].startTs) + Number(ltpoDataArr[ltpoDataIndex].dur); + sendDur = + Number(ltpoDataArr[ltpoDataIndex].nextStartTs) + Number(ltpoDataArr[ltpoDataIndex].nextDur) - sendStartTs; + } + let tmpDur = cutSendDur ? Math.ceil(cutSendDur / 100000) / 10 : Math.ceil(sendDur / 100000) / 10; + if (tmpDur < 170) { + sendDataArr.push({ + dur: sendDur, + cutSendDur: cutSendDur, + value: 0, + startTs: sendStartTs, + pid: ltpoDataArr[ltpoDataIndex].fanceId, + itid: ltpoDataArr[ltpoDataIndex].fanceId, + name: undefined, + presentId: ltpoDataArr[ltpoDataIndex].fanceId, + ts: undefined, + fanceId: ltpoDataArr[ltpoDataIndex].fanceId, + fps: ltpoDataArr[ltpoDataIndex].fps, + nextStartTs: ltpoDataArr[ltpoDataIndex].nextStartTs, + nextDur: ltpoDataArr[ltpoDataIndex].nextDur, + translateY: undefined, + isHover: false, + startTime: undefined, + signaled: undefined, + nowTime: undefined, + cutTime: undefined, + frame: undefined, + }); + } ltpoDataIndex++; } else if (ltpoDataArr[ltpoDataIndex].fanceId! > SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].fanceId!) { tempRsNowTimeIndex++; @@ -379,35 +398,42 @@ export class SpLtpoChart { cutSendDur = sendDur - SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].cutTime! * 1000000; cutSendDur = cutSendDur < 0 ? 0 : cutSendDur; } + if (ltpoDataArr[ltpoDataIndex].fanceId !== -1 && ltpoDataArr[ltpoDataIndex].nextDur) { + sendStartTs = Number(ltpoDataArr[ltpoDataIndex].startTs) + Number(ltpoDataArr[ltpoDataIndex].dur); + sendDur = + Number(ltpoDataArr[ltpoDataIndex].nextStartTs) + Number(ltpoDataArr[ltpoDataIndex].nextDur) - sendStartTs; + } + let tmpDur = cutSendDur ? Math.ceil(cutSendDur / 100000) / 10 : Math.ceil(sendDur / 100000) / 10; + if (tmpDur < 170) { + sendDataArr.push({ + dur: sendDur, + cutSendDur: cutSendDur, + value: 0, + startTs: sendStartTs, + pid: ltpoDataArr[ltpoDataIndex].fanceId, + itid: ltpoDataArr[ltpoDataIndex].fanceId, + name: undefined, + presentId: ltpoDataArr[ltpoDataIndex].fanceId, + ts: undefined, + fanceId: ltpoDataArr[ltpoDataIndex].fanceId, + fps: ltpoDataArr[ltpoDataIndex].fps, + nextStartTs: ltpoDataArr[ltpoDataIndex].nextStartTs, + nextDur: ltpoDataArr[ltpoDataIndex].nextDur, + translateY: undefined, + isHover: false, + startTime: undefined, + signaled: undefined, + nowTime: undefined, + cutTime: undefined, + frame: undefined, + }); + } + ltpoDataIndex++; + tempRsNowTimeIndex++; } + }else{ + break; } - let tmpDur = cutSendDur ? Math.ceil(cutSendDur / 100000) / 10 : Math.ceil(sendDur / 100000) / 10; - if (tmpDur < 170) { - sendDataArr.push({ - dur: sendDur, - cutSendDur: cutSendDur, - value: 0, - startTs: sendStartTs, - pid: ltpoDataArr[ltpoDataIndex].fanceId, - itid: ltpoDataArr[ltpoDataIndex].fanceId, - name: undefined, - presentId: ltpoDataArr[ltpoDataIndex].fanceId, - ts: undefined, - fanceId: ltpoDataArr[ltpoDataIndex].fanceId, - fps: ltpoDataArr[ltpoDataIndex].fps, - nextStartTs: ltpoDataArr[ltpoDataIndex].nextStartTs, - nextDur: ltpoDataArr[ltpoDataIndex].nextDur, - translateY: undefined, - frame: undefined, - isHover: false, - startTime: undefined, - signaled: undefined, - nowTime: undefined, - cutTime: undefined, - }); - } - ltpoDataIndex++; - tempRsNowTimeIndex++; } return sendDataArr; } @@ -437,7 +463,7 @@ export class SpLtpoChart { } //六舍七入 specialValue(num: number) { - if (num < 0) { + if (num < 0.7) { return 0; } else { if (!num.toString().split('.')[1]) { @@ -485,6 +511,9 @@ export class SpLtpoChart { `${LtpoStruct.hoverLtpoStruct?.value!}` ); }; + row.findHoverStruct = (): void => { + LtpoStruct.hoverLtpoStruct = row.getHoverStruct(true, false, 'value'); + }; row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (row.currentContext) { @@ -526,8 +555,8 @@ export class SpLtpoChart { } let mathValue = (tmpDur * Number(SpLtpoChart.sendHitchDataArr[i].fps)) / 1000 - 1; - let finalValue = tmpVale! < 0 ? 0 : tmpVale; - SpLtpoChart.sendHitchDataArr[i].value = this.specialValue(finalValue); + let finalValue = (tmpVale! /(1000 / SpLtpoChart.sendHitchDataArr[i].fps!)) < 0.7 ? 0 : tmpVale; + SpLtpoChart.sendHitchDataArr[i].value = Number(finalValue.toFixed(1)); SpLtpoChart.sendHitchDataArr[i].name = this.specialValue(mathValue)!.toString(); } return SpLtpoChart.sendHitchDataArr; @@ -540,6 +569,9 @@ export class SpLtpoChart { `${HitchTimeStruct.hoverHitchTimeStruct?.value!}` ); }; + row.findHoverStruct = (): void => { + HitchTimeStruct.hoverHitchTimeStruct = row.getHoverStruct(true, false, 'value'); + }; row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (row.currentContext) { diff --git a/ide/src/trace/component/chart/SpPerfOutputDataChart.ts b/ide/src/trace/component/chart/SpPerfOutputDataChart.ts index ae45e19d8a44eebfc64906ac15467a6d86f192a3..57840add47c098fa6bae89f3daa5bf60e4098103 100644 --- a/ide/src/trace/component/chart/SpPerfOutputDataChart.ts +++ b/ide/src/trace/component/chart/SpPerfOutputDataChart.ts @@ -38,14 +38,11 @@ export class SpPerfOutputDataChart { } let perfToolsDur = await queryPerfToolsDur(); if (perfToolsDur.length > 0) { - // @ts-ignore this.dur = perfToolsDur[0].dur; } else { this.dur = 3000000000; } - // @ts-ignore this.perfOutputArr = perfOutputData[0].name.split(':')[2].split(','); - // @ts-ignore let endTime: number = perfOutputData[0].ts; this.startTime = endTime - window.recordStartNS - this.dur!; if (this.startTime < 0) { @@ -71,7 +68,7 @@ export class SpPerfOutputDataChart { context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } traceRow.canvasSave(context); - (renders.perfTool as PerfToolRender).renderMainThread( + (renders['perfTool'] as PerfToolRender).renderMainThread( { context: context, useCache: useCache, @@ -84,8 +81,7 @@ export class SpPerfOutputDataChart { }; } - // @ts-ignore - async initData(folder: TraceRow): Promise { + async initData(folder: TraceRow): Promise { let perfToolStartTime = new Date().getTime(); let perfToolList = [ { name: 'Application Process CPU Power Consumption(MAS)', idx: 27 }, @@ -106,7 +102,7 @@ export class SpPerfOutputDataChart { traceRow.rowId = i + ''; traceRow.rowType = TraceRow.ROW_TYPE_PERF_TOOL; traceRow.rowParentId = folder.rowId; - traceRow.style.height = '40px'; + traceRow.style.height = '24px'; traceRow.name = it.name; traceRow.rowHidden = !folder.expansion; traceRow.setAttribute('children', ''); @@ -114,13 +110,12 @@ export class SpPerfOutputDataChart { traceRow.selectChangeHandler = this.trace.selectChangeHandler; traceRow.supplierFrame = (): Promise => { let data = new PerfToolStruct(); - data.startNS = this.startTime; + data.startTs = this.startTime; data.dur = this.dur; data.count = this.perfOutputArr![it.idx]; data.id = i + 1; data.name = it.name; - // @ts-ignore - return new Promise>((resolve) => resolve([data])); + return new Promise>((resolve) => resolve([data])); }; traceRow.findHoverStruct = (): void => { PerfToolStruct.hoverPerfToolStruct = traceRow.getHoverStruct(); @@ -132,8 +127,7 @@ export class SpPerfOutputDataChart { info('The time to load the ClockData is: ', durTime); } - // @ts-ignore - async initFolder(): Promise> { + async initFolder(): Promise> { let perfFolder = TraceRow.skeleton(); perfFolder.rowId = 'perfTool'; perfFolder.index = 0; @@ -144,14 +138,13 @@ export class SpPerfOutputDataChart { perfFolder.name = 'Perf Tools'; perfFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; perfFolder.selectChangeHandler = this.trace.selectChangeHandler; - // @ts-ignore - perfFolder.supplier = (): Promise => new Promise>((resolve) => resolve([])); + perfFolder.supplier = (): Promise => new Promise>((resolve) => resolve([])); perfFolder.onThreadHandler = (useCache): void => { perfFolder.canvasSave(this.trace.canvasPanelCtx!); if (perfFolder.expansion) { this.trace.canvasPanelCtx?.clearRect(0, 0, perfFolder.frame.width, perfFolder.frame.height); } else { - (renders.empty as EmptyRender).renderMainThread( + (renders['empty'] as EmptyRender).renderMainThread( { context: this.trace.canvasPanelCtx, useCache: useCache, diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index 47be8264cd81d9995f4643780c89ee5b48ad15f2..50a6ce3e38fd07612ce703b30e820ddfd504de73 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -36,29 +36,30 @@ import { processSoInitDataSender } from '../../database/data-trafic/process/Proc import { processExpectedDataSender } from '../../database/data-trafic/process/ProcessExpectedDataSender'; import { processActualDataSender } from '../../database/data-trafic/process/ProcessActualDataSender'; import { processDeliverInputEventDataSender } from '../../database/data-trafic/process/ProcessDeliverInputEventDataSender'; -import { getMaxDepthByTid, queryAllFuncNames, queryProcessAsyncFunc, queryProcessAsyncFuncCat } from '../../database/sql/Func.sql'; +import { processTouchEventDispatchDataSender } from '../../database/data-trafic/process/ProcessTouchEventDispatchDataSender'; +import { getMaxDepthByTid, queryProcessAsyncFunc, queryProcessAsyncFuncCat } from '../../database/sql/Func.sql'; import { queryMemFilterIdMaxValue } from '../../database/sql/Memory.sql'; import { queryAllSoInitNames, queryAllSrcSlices, queryEventCountMap } from '../../database/sql/SqlLite.sql'; import { - queryProcess, queryProcessByTable, queryProcessContentCount, queryProcessMem, queryProcessSoMaxDepth, - queryProcessThreads, queryProcessThreadsByTable, queryStartupPidArray, queryRsProcess, queryTaskPoolProcessIds, + queryDistributedRelationData, } from '../../database/sql/ProcessThread.sql'; import { queryAllJankProcess } from '../../database/sql/Janks.sql'; import { BaseStruct } from '../../bean/BaseStruct'; +const FOLD_HEIGHT = 24; export class SpProcessChart { private readonly trace: SpSystemTrace; private processAsyncFuncMap: unknown = {}; private processAsyncFuncArray: unknown[] = []; - private processAsyncFuncCatMap: unknown = {}; + private processAsyncFuncCatMap: unknown = {}; private eventCountMap: unknown; private processThreads: Array = []; private processMem: Array = []; @@ -69,40 +70,76 @@ export class SpProcessChart { private threadFuncMaxDepthMap: Map = new Map(); private startupProcessArr: { pid: number }[] = []; private processSoMaxDepth: { pid: number; maxDepth: number }[] = []; - private funcNameMap: Map = new Map(); private filterIdMaxValue: Map = new Map(); private soInitNameMap: Map = new Map(); private processSrcSliceMap: Map = new Map(); + private distributedDataMap: Map< + string, + { + chainId: string; + spanId: string; + parentSpanId: string; + chainFlag: string; + traceId: string + } + > = new Map(); private renderRow: TraceRow | null = null; private loadAppStartup: boolean = false; + private isDistributed: boolean = false; + private traceId?: string | undefined; + private parentRow: TraceRow | undefined; + static asyncFuncCache: unknown[] = []; + static threadStateList: Map = new Map(); + static processRowSortMap: Map = new Map(); + constructor(trace: SpSystemTrace) { this.trace = trace; } - initAsyncFuncData = async (traceRange: { startTs: number; endTs: number }): Promise => { - const funcNamesArray = await queryAllFuncNames(); - funcNamesArray.forEach((it) => { - //@ts-ignore - this.funcNameMap.set(it.id, it.name); - }); - let asyncFuncList: unknown[] = await queryProcessAsyncFunc(traceRange); + clearCache(): void { + this.processAsyncFuncArray = []; + this.processAsyncFuncMap = {}; + this.processAsyncFuncCatMap = {}; + this.eventCountMap = {}; + this.processThreads = []; + this.processMem = []; + this.processThreadCountMap.clear(); + this.processThreadDataCountMap.clear(); + this.processFuncDataCountMap.clear(); + this.processMemDataCountMap.clear(); + this.threadFuncMaxDepthMap.clear(); + this.startupProcessArr = []; + this.processSoMaxDepth = []; + this.filterIdMaxValue.clear(); + this.soInitNameMap.clear(); + this.processSrcSliceMap.clear(); + this.distributedDataMap.clear(); + this.renderRow = null; + SpProcessChart.asyncFuncCache = []; + if (this.parentRow) { + this.parentRow.clearMemory(); + this.parentRow = undefined; + } + } + + initAsyncFuncData = async (traceRange: { startTs: number; endTs: number }, traceId?: string): Promise => { + let asyncFuncList: unknown[] = await queryProcessAsyncFunc(traceRange, traceId); for (const func of asyncFuncList) { //@ts-ignore - func.funName = this.funcNameMap.get(func.id); //@ts-ignore - func.threadName = Utils.THREAD_MAP.get(func.tid); + func.funName = this.traceId ? Utils.getInstance().getCallStatckMap().get(`${this.traceId}_${func.id}`) : Utils.getInstance().getCallStatckMap().get(func.id); //@ts-ignore + func.threadName = Utils.getInstance().getThreadMap(traceId).get(func.tid); } info('AsyncFuncData Count is: ', asyncFuncList!.length); this.processAsyncFuncArray = asyncFuncList; this.processAsyncFuncMap = Utils.groupBy(asyncFuncList, 'pid'); - let asyncFuncCatList: unknown[] = await queryProcessAsyncFuncCat(); + let asyncFuncCatList: unknown[] = await queryProcessAsyncFuncCat(traceRange); info('AsyncFuncCatData Count is: ', asyncFuncCatList!.length); - this.processAsyncFuncCatMap = Utils.groupBy(asyncFuncCatList, 'pid'); + this.processAsyncFuncCatMap = Utils.groupBy(asyncFuncCatList, 'pid'); }; initDeliverInputEvent = async (): Promise => { let row = TraceRow.skeleton(); - row.setAttribute('disabled-check', ''); row.rowId = 'DeliverInputEvent'; row.index = 0; row.rowType = TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT; @@ -117,14 +154,14 @@ export class SpProcessChart { let asyncFuncGroup = Utils.groupBy( //@ts-ignore this.processAsyncFuncArray.filter((it) => it.funName === 'deliverInputEvent'), - 'tid' + 'pid' ); // @ts-ignore if (Reflect.ownKeys(asyncFuncGroup).length > 0) { this.trace.rowsEL?.appendChild(row); } // @ts-ignore - Reflect.ownKeys(asyncFuncGroup).map((key: unknown) => { + Reflect.ownKeys(asyncFuncGroup).map((key: any) => { // @ts-ignore - let asyncFuncGroups: Array = asyncFuncGroup[key]; + let asyncFuncGroups: Array = asyncFuncGroup[key]; if (asyncFuncGroups.length > 0) { //@ts-ignore row.addChildTraceRow(this.createDeliverInputEventRow(row, key, asyncFuncGroups)); @@ -143,7 +180,7 @@ export class SpProcessChart { funcRow.asyncFuncName = asyncFuncGroups[0].funName; funcRow.asyncFuncNamePID = key; funcRow.rowType = TraceRow.ROW_TYPE_FUNC; - funcRow.enableCollapseChart(); //允许折叠泳道图 + funcRow.enableCollapseChart(FOLD_HEIGHT, this.trace); //允许折叠泳道图 funcRow.rowParentId = `${parentRow.rowId}`; funcRow.rowHidden = !parentRow.expansion; funcRow.style.width = '100%'; //@ts-ignore @@ -196,8 +233,8 @@ export class SpProcessChart { }; res.forEach((it, i): void => { //@ts-ignore - res[i].funName = this.funcNameMap.get(res[i].id!); //@ts-ignore - res[i].threadName = Utils.THREAD_MAP.get(res[i].tid!); //@ts-ignore + res[i].funName = this.traceId ? Utils.getInstance().getCallStatckMap().get(`${this.traceId}_${res[i].id!}`) : Utils.getInstance().getCallStatckMap().get(res[i].id!); //@ts-ignore + res[i].threadName = Utils.getInstance().getThreadMap().get(res[i].tid!); //@ts-ignore if (it.dur === -1 || it.dur === null || it.dur === undefined) { //@ts-ignore it.dur = (TraceRow.range?.endNS || 0) - it.startTs; //@ts-ignore @@ -214,8 +251,114 @@ export class SpProcessChart { } } - async init(): Promise { - await this.prepareData(); + initTouchEventDispatch = async (): Promise => { + let row = TraceRow.skeleton() as TraceRow; + row.rowId = 'TouchEventDispatch'; + row.index = 0; + row.rowType = TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH; + row.rowParentId = ''; + row.folder = true; + row.style.height = '40px'; + row.name = 'TouchEventDispatch'; + //@ts-ignore + row.supplier = folderSupplier(); + row.onThreadHandler = folderThreadHandler(row, this.trace); + + let asyncFuncGroup = Utils.groupBy( + //@ts-ignore + this.processAsyncFuncArray.filter((it) => it.funName === 'H:touchEventDispatch' || it.funName === 'H:TouchEventDispatch'), + 'pid' + ); + //@ts-ignore + if (Reflect.ownKeys(asyncFuncGroup).length > 0) { + this.trace.rowsEL?.appendChild(row); + } + //@ts-ignore + Reflect.ownKeys(asyncFuncGroup).map((key: any) => { + //@ts-ignore + let asyncFuncGroups: Array = asyncFuncGroup[key]; + if (asyncFuncGroups.length > 0) { + row.addChildTraceRow(this.createTouchEventDispatchRow(row, key, asyncFuncGroups)); + } + }); + }; + + private createTouchEventDispatchRow( + parentRow: TraceRow, + key: number, + asyncFuncGroups: Array + ): TraceRow { + let funcRow = TraceRow.skeleton(); + funcRow.rowId = `${asyncFuncGroups[0].funName}-${key}`; + funcRow.asyncFuncName = asyncFuncGroups[0].funName; + funcRow.asyncFuncNamePID = key; + funcRow.rowType = TraceRow.ROW_TYPE_FUNC; + funcRow.enableCollapseChart(FOLD_HEIGHT, this.trace); //允许折叠泳道图 + funcRow.rowParentId = `${parentRow.rowId}`; + funcRow.rowHidden = !parentRow.expansion; + funcRow.style.width = '100%'; + funcRow.style.height = '24px'; + funcRow.name = `${asyncFuncGroups[0].funName} ${key}`; + funcRow.setAttribute('children', ''); + funcRow.supplierFrame = () => { + return processTouchEventDispatchDataSender(key, funcRow!).then((res: Array) => { + this.touchEventDispatchSendCallback(res, funcRow, asyncFuncGroups); + return res; + }); + }; + + funcRow.findHoverStruct = (): void => { + FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); + }; + funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + funcRow.selectChangeHandler = this.trace.selectChangeHandler; + funcRow.onThreadHandler = rowThreadHandler( + 'func', + 'context', + { + type: `func-${asyncFuncGroups[0].funName}-${key}`, + }, + funcRow, + this.trace + ); + return funcRow; + } + + private touchEventDispatchSendCallback(res: Array, funcRow: TraceRow, asyncFuncGroups: Array): void { + let isIntersect = (left: any, right: any): boolean => + Math.max(left.startTs + left.dur, right.startTs + right.dur) - Math.min(left.startTs, right.startTs) < + left.dur + right.dur; + let depths: any = []; + let createDepth = (currentDepth: number, index: number): void => { + if (depths[currentDepth] == undefined || !isIntersect(depths[currentDepth], res[index])) { + res[index].depth = currentDepth; + depths[currentDepth] = res[index]; + } else { + createDepth(++currentDepth, index); + } + }; + res.forEach((it, i) => { + res[i].funName = this.traceId ? Utils.getInstance().getCallStatckMap().get(`${this.traceId}_${res[i].id!}`) : Utils.getInstance().getCallStatckMap().get(res[i].id!); + res[i].threadName = Utils.getInstance().getThreadMap().get(res[i].tid!); + if (it.dur == -1 || it.dur === null || it.dur === undefined) { + it.dur = (TraceRow.range?.endNS || 0) - it.startTs; + it.flag = 'Did not end'; + } + createDepth(0, i); + }); + if (funcRow && !funcRow.isComplete) { + let max = Math.max(...asyncFuncGroups.map((it) => it.depth || 0)) + 1; + let maxHeight = max * 18 + 6; + funcRow.style.height = `${maxHeight}px`; + funcRow.setAttribute('height', `${maxHeight}`); + } + } + + async init(isDistributed: boolean, parentRow?: TraceRow, traceId?: string): Promise { + this.traceId = traceId; + this.parentRow = parentRow; + this.isDistributed = isDistributed; + await this.prepareData(traceId); if ( //@ts-ignore this.eventCountMap.print === 0 && //@ts-ignore @@ -225,51 +368,70 @@ export class SpProcessChart { return; } let time = new Date().getTime(); - let processes = await queryProcess(); - let processFromTable = await queryProcessByTable(); - let processList = Utils.removeDuplicates(processes, processFromTable, 'pid'); - let allJankProcessData = await queryAllJankProcess(); + let processSortArray = Array.from(SpProcessChart.processRowSortMap); + // @ts-ignore + processSortArray.sort((a: Array, b: Array) => + // @ts-ignore + b[1] - a[1] + ); + let processFromTable = await queryProcessByTable(traceId); + let processList = Utils.sortThreadRow(processSortArray, processFromTable, 'process'); + SpProcessChart.processRowSortMap.clear(); let allJankProcess: Array = []; - if (allJankProcessData.length > 0) { - allJankProcessData.forEach((name, index) => { - allJankProcess.push(name.pid!); - }); - } let allTaskPoolPid: Array<{ pid: number }> = []; - if (FlagsConfig.getFlagsConfigEnableStatus('TaskPool')) { - allTaskPoolPid = await queryTaskPoolProcessIds(); + let renderServiceProcess: unknown[] = []; + if (!this.isDistributed) { + let allJankProcessData = await queryAllJankProcess(); + if (allJankProcessData.length > 0) { + allJankProcessData.forEach((name, index) => { + allJankProcess.push(name.pid!); + }); + } + if (FlagsConfig.getFlagsConfigEnableStatus('TaskPool')) { + allTaskPoolPid = await queryTaskPoolProcessIds(); + } + renderServiceProcess = await queryRsProcess(); } - let renderServiceProcess = await queryRsProcess(); // @ts-ignore + // @ts-ignore info('ProcessList Data size is: ', processList!.length); // @ts-ignore - await this.initProcessRow(processList, allTaskPoolPid, allJankProcess, renderServiceProcess); + await this.initProcessRow(processList, allTaskPoolPid, allJankProcess, renderServiceProcess, traceId); let durTime = new Date().getTime() - time; info('The time to load the Process data is: ', durTime); } - private async prepareData(): Promise { - let maxValues = await queryMemFilterIdMaxValue(); - maxValues.forEach((it) => { - this.filterIdMaxValue.set(it.filterId, it.maxValue); - }); - - let soInitNamesArray = await queryAllSoInitNames(); - soInitNamesArray.forEach((it) => { - //@ts-ignore - this.soInitNameMap.set(it.id, it.name); - }); - let processSrcSliceArray = await queryAllSrcSlices(); - processSrcSliceArray.forEach((it) => { - //@ts-ignore - this.processSrcSliceMap.set(it.id, it.src); - }); - let threadFuncMaxDepthArray = await getMaxDepthByTid(); + private async prepareData(traceId?: string): Promise { + if (!this.isDistributed) { + let maxValues = await queryMemFilterIdMaxValue(); + maxValues.forEach((it) => { + this.filterIdMaxValue.set(it.filterId, it.maxValue); + }); + let soInitNamesArray = await queryAllSoInitNames(); + soInitNamesArray.forEach((it) => { + // @ts-ignore + this.soInitNameMap.set(it.id, it.name); + }); + let processSrcSliceArray = await queryAllSrcSlices(); + processSrcSliceArray.forEach((it) => { + // @ts-ignore + this.processSrcSliceMap.set(it.id, it.src); + }); + this.processMem = await queryProcessMem(); + info('The amount of initialized process memory data is : ', this.processMem!.length); + this.loadAppStartup = FlagsConfig.getFlagsConfigEnableStatus('AppStartup'); + info('Prepare App startup data '); + if (this.loadAppStartup) { + this.startupProcessArr = await queryStartupPidArray(); + this.processSoMaxDepth = await queryProcessSoMaxDepth(); + } + } + let threadFuncMaxDepthArray = await getMaxDepthByTid(traceId); info('Gets the maximum tier per thread , tid and maxDepth'); threadFuncMaxDepthArray.forEach((it) => { //@ts-ignore this.threadFuncMaxDepthMap.set(`${it.ipid}-${it.tid}`, it.maxDepth); }); info('convert tid and maxDepth array to map'); - let pidCountArray = await queryProcessContentCount(); + let pidCountArray = await queryProcessContentCount(traceId); info('fetch per process pid,switch_count,thread_count,slice_count,mem_count'); pidCountArray.forEach((it) => { //@ts-ignore @@ -278,23 +440,33 @@ export class SpProcessChart { this.processFuncDataCountMap.set(it.pid, it.slice_count); //@ts-ignore this.processMemDataCountMap.set(it.pid, it.mem_count); }); - this.processMem = await queryProcessMem(); - info('The amount of initialized process memory data is : ', this.processMem!.length); - this.loadAppStartup = FlagsConfig.getFlagsConfigEnableStatus('AppStartup'); - info('Prepare App startup data '); - if (this.loadAppStartup) { - this.startupProcessArr = await queryStartupPidArray(); - this.processSoMaxDepth = await queryProcessSoMaxDepth(); - } - let eventCountList: Array = await queryEventCountMap(); + let eventCountList: Array = await queryEventCountMap(traceId); this.eventCountMap = eventCountList.reduce((pre, current) => { //@ts-ignore pre[`${current.eventName}`] = current.count; return pre; }, {}); - let queryProcessThreadResult = await queryProcessThreads(); - let queryProcessThreadsByTableResult = await queryProcessThreadsByTable(); // @ts-ignore - this.processThreads = Utils.removeDuplicates(queryProcessThreadResult, queryProcessThreadsByTableResult, 'tid'); + // threadStateList转数组 + let threadArray = Array.from(SpProcessChart.threadStateList); // [['1235-1235',12312321312],['12-12',4546465]] + // @ts-ignore 排序 + threadArray.sort((a: Array, b: Array) => + // @ts-ignore + b[1] - a[1]); + let queryProcessThreadsByTableResult = await queryProcessThreadsByTable(traceId); // @ts-ignore + // 全量threads排序 + // @ts-ignore + this.processThreads = Utils.sortThreadRow(threadArray, queryProcessThreadsByTableResult, 'thread'); + SpProcessChart.threadStateList.clear(); + let distributedDataLists = await queryDistributedRelationData(traceId); + distributedDataLists.forEach((item) => { + this.distributedDataMap.set(`${item.id}_${traceId}`, { + chainId: item.chainId, + spanId: item.spanId, + parentSpanId: item.parentSpanId, + chainFlag: item.chainFlag, + traceId: traceId!, + }); + }); info('The amount of initialized process threads data is : ', this.processThreads!.length); } @@ -302,7 +474,8 @@ export class SpProcessChart { pArr: Array, allTaskPoolPid: Array<{ pid: number }>, jankArr: Array, - rsProcess: Array + rsProcess: Array, + traceId?: string ): Promise { for (let i = 0; i < pArr.length; i++) { const it = pArr[i]; @@ -316,50 +489,52 @@ export class SpProcessChart { continue; } let processRow = this.createProcessRow(i, it, allTaskPoolPid); - this.trace.rowsEL?.appendChild(processRow); + if (this.parentRow) { + this.parentRow.addChildTraceRow(processRow); + } else { + this.trace.rowsEL?.appendChild(processRow); + } /* App Startup row*/ let startupRow: TraceRow | undefined = undefined; let soRow: TraceRow | undefined = undefined; - if (this.loadAppStartup) { - //@ts-ignore - if (this.startupProcessArr.find((sp) => sp.pid === it.pid)) { - startupRow = this.addStartUpRow(processRow); - } //@ts-ignore - let maxSoDepth = this.processSoMaxDepth.find((md) => md.pid === it.pid); - if (maxSoDepth) { - soRow = this.addSoInitRow(processRow, maxSoDepth.maxDepth); - } - } - let actualRow: TraceRow | null = null; let expectedRow: TraceRow | null = null; + //@ts-ignore + let currentPid = it.pid; + if (!this.isDistributed) { + if (this.loadAppStartup) { + if (this.startupProcessArr.find((sp) => sp.pid === currentPid)) { + startupRow = this.addStartUpRow(processRow); + } + let maxSoDepth = this.processSoMaxDepth.find((md) => md.pid === currentPid); + if (maxSoDepth) { + soRow = this.addSoInitRow(processRow, maxSoDepth.maxDepth); + } + } + if (jankArr.indexOf(currentPid) > -1) { + expectedRow = this.addExpectedRow(it, processRow, rsProcess); + actualRow = this.addActualRow(it, processRow, rsProcess); + } + } this.renderRow = null; //@ts-ignore if (it.processName === 'render_service') { //@ts-ignore - this.addThreadList(it, processRow, expectedRow, actualRow, soRow, startupRow); //@ts-ignore + this.addThreadList(it, processRow, expectedRow, actualRow, soRow, startupRow, traceId); //@ts-ignore this.addProcessMemInfo(it, processRow); //@ts-ignore - if (jankArr.indexOf(it.pid!) > -1) { - expectedRow = this.addExpectedRow(it, processRow, rsProcess); - actualRow = this.addActualRow(it, processRow, rsProcess); - } - this.addProcessRowListener(processRow, actualRow); //@ts-ignore this.addAsyncFunction(it, processRow);//@ts-ignore this.addAsyncCatFunction(it, processRow); } else { //@ts-ignore - if (jankArr.indexOf(it.pid!) > -1) { - expectedRow = this.addExpectedRow(it, processRow, rsProcess); - actualRow = this.addActualRow(it, processRow, rsProcess); - } - this.addProcessRowListener(processRow, actualRow); //@ts-ignore this.addAsyncFunction(it, processRow); //@ts-ignore this.addProcessMemInfo(it, processRow); //@ts-ignore - this.addThreadList(it, processRow, expectedRow, actualRow, soRow, startupRow);//@ts-ignore + this.addThreadList(it, processRow, expectedRow, actualRow, soRow, startupRow, traceId);//@ts-ignore this.addAsyncCatFunction(it, processRow); } - - //@ts-ignore - await this.trace.chartManager?.frameTimeChart.initAnimatedScenesChart(processRow, it, expectedRow!, actualRow!); + this.addProcessRowListener(processRow, actualRow); + if (!this.isDistributed) { + //@ts-ignore + await this.trace.chartManager?.frameTimeChart.initAnimatedScenesChart(processRow, it, expectedRow!, actualRow!); + } } } @@ -368,7 +543,7 @@ export class SpProcessChart { process: unknown, allTaskPoolPid: Array<{ pid: number }> ): TraceRow { - let processRow = TraceRow.skeleton(); //@ts-ignore + let processRow = TraceRow.skeleton(this.traceId); //@ts-ignore processRow.rowId = `${process.pid}`; processRow.index = index; processRow.rowType = TraceRow.ROW_TYPE_PROCESS; @@ -388,7 +563,7 @@ export class SpProcessChart { processRow.name = `${process.processName || 'Process'} ${process.pid}`; //@ts-ignore processRow.supplierFrame = (): Promise> => { //@ts-ignore - return processDataSender(process.pid || -1, processRow); + return processDataSender(process.pid || -1, processRow, this.traceId); }; processRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; processRow.selectChangeHandler = this.trace.selectChangeHandler; @@ -428,6 +603,22 @@ export class SpProcessChart { this.trace.linkNodes?.forEach((linkProcessItem) => this.handler2(e, linkProcessItem, processRow)); }, 300); } + } else if (FuncStruct.selectFuncStruct) { //@ts-ignore + if (e.detail.expansion) { + offsetYTimeOut = setTimeout(() => { + this.trace.linkNodes.forEach((linkNodeItem) => this.handler3(e, linkNodeItem)); + }, 300); + } else { + FuncStruct.selectLineFuncStruct.push(FuncStruct.selectFuncStruct); + offsetYTimeOut = setTimeout(() => { + this.trace.linkNodes?.forEach((linkProcessItem) => { + this.handler4(e, linkProcessItem, processRow); + JankStruct.selectJankStructList = []; + }); + }, 300); + } + this.trace.resetDistributedLine(); + } else { //@ts-ignore if (e.detail.expansion) { @@ -552,6 +743,7 @@ export class SpProcessChart { pair.rowEL = processRow!; } } + /* Janks Frames */ //@ts-ignore addExpectedRow( @@ -650,12 +842,12 @@ export class SpProcessChart { if (type === 'actual') { struct.src_slice = this.processSrcSliceMap.get(res[j].id!); } - struct.cmdline = Utils.PROCESS_MAP.get(res[j].pid!); //@ts-ignore + struct.cmdline = Utils.getInstance().getProcessMap().get(res[j].pid!); //@ts-ignore if (res[j].pid! === renderServiceProcess[0].pid) { struct.cmdline = 'render_service'; - struct.frame_type = struct.cmdline; + struct.frameType = struct.cmdline; } else { - struct.frame_type = 'app'; + struct.frameType = 'app'; } } if (row && !row.isComplete && res.length > 0) { @@ -665,7 +857,7 @@ export class SpProcessChart { if (res[0]) { let timeLineType = res[0].type; //@ts-ignore row.rowId = `${timeLineType}-${process.pid}`; - row.setAttribute('frame_type', res[0].frame_type || ''); + row.setAttribute('frame_type', res[0].frameType || ''); if (type === 'actual') { row.dataList = res; } @@ -775,13 +967,14 @@ export class SpProcessChart { expectedRow: TraceRow | null, actualRow: TraceRow | null, soRow: TraceRow | undefined, - startupRow: TraceRow | undefined + startupRow: TraceRow | undefined, + traceId?: string ): void { let threads = this.processThreads.filter((thread) => thread.pid === it.pid && thread.tid !== 0); let tRowArr: Array> = []; for (let j = 0; j < threads.length; j++) { let thread = threads[j]; - let tRow = TraceRow.skeleton(); + let tRow = TraceRow.skeleton(this.traceId); tRow.rowId = `${thread.tid}`; tRow.rowType = TraceRow.ROW_TYPE_THREAD; tRow.rowParentId = `${it.pid}`; @@ -796,16 +989,15 @@ export class SpProcessChart { tRow.selectChangeHandler = this.trace.selectChangeHandler; tRow.findHoverStruct = (): void => this.threadRowFindHoverStruct(tRow); tRow.supplierFrame = async (): Promise> => { - const res = await threadDataSender(thread.tid || 0, it.pid || 0, tRow); + const res = await threadDataSender(thread.tid || 0, it.pid || 0, tRow, this.traceId); if (res === true) { return []; - } else { - let rs = res as ThreadStruct[]; - if (rs.length <= 0 && !tRow.isComplete) { - this.trace.refreshCanvas(true); - } - return rs; } + let rs = res as ThreadStruct[]; + if (rs.length <= 0 && !tRow.isComplete) { + this.trace.refreshCanvas(true); + } + return rs; }; tRow.onThreadHandler = rowThreadHandler( 'thread', @@ -889,17 +1081,17 @@ export class SpProcessChart { threads: Array, threadRowArr: Array, threadRow: TraceRow, - processRow: TraceRow + processRow: TraceRow, ): void { //@ts-ignore if (this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) !== undefined) { //@ts-ignore let max = this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) || 1; let maxHeight = max * 18 + 6; - let funcRow = TraceRow.skeleton(); //@ts-ignore + let funcRow = TraceRow.skeleton(this.traceId); //@ts-ignore funcRow.rowId = `${thread.tid}`; funcRow.rowType = TraceRow.ROW_TYPE_FUNC; - funcRow.enableCollapseChart(); //允许折叠泳道图 + funcRow.enableCollapseChart(FOLD_HEIGHT, this.trace); //允许折叠泳道图 //@ts-ignore funcRow.rowParentId = `${process.pid}`; funcRow.rowHidden = !processRow.expansion; @@ -911,7 +1103,7 @@ export class SpProcessChart { funcRow.setAttribute('children', ''); funcRow.supplierFrame = async (): Promise> => { //@ts-ignore - const rs = await funcDataSender(thread.tid || 0, thread.upid || 0, funcRow); //@ts-ignore + const rs = await funcDataSender(thread.tid || 0, thread.upid || 0, funcRow, this.traceId); //@ts-ignore return this.funDataSenderCallback(rs, funcRow, thread); }; funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; @@ -952,13 +1144,23 @@ export class SpProcessChart { funs.forEach((fun, index) => { funs[index].itid = thread.utid; funs[index].ipid = thread.upid; - funs[index].funName = this.funcNameMap.get(funs[index].id!); + funs[index].tid = thread.tid; + funs[index].pid = thread.pid; + funs[index].funName = this.traceId ? Utils.getInstance().getCallStatckMap().get(`${this.traceId}_${funs[index].id}`) : Utils.getInstance().getCallStatckMap().get(funs[index].id!); if (Utils.isBinder(fun)) { } else { if (fun.nofinish) { fun.flag = 'Did not end'; } } + if (fun.id && this.distributedDataMap.has(`${fun.id}_${this.traceId}`)) { + let distributedData = this.distributedDataMap.get(`${fun.id}_${this.traceId}`); + funs[index].chainId = distributedData!.chainId; + funs[index].spanId = distributedData!.spanId; + funs[index].parentSpanId = distributedData!.parentSpanId; + funs[index].chainFlag = distributedData!.chainFlag; + funs[index].traceId = this.traceId; + } }); } else { this.trace.refreshCanvas(true); @@ -984,6 +1186,9 @@ export class SpProcessChart { row.favoriteChangeHandler = this.trace.favoriteChangeHandler; row.selectChangeHandler = this.trace.selectChangeHandler; row.focusHandler = (): void => { + if (row.hoverY <= 5 || row.hoverY >= 35) { + ProcessMemStruct.hoverProcessMemStruct = undefined; + } this.trace.displayTip( row, ProcessMemStruct.hoverProcessMemStruct, @@ -1041,81 +1246,225 @@ export class SpProcessChart { max += 1; return max * 18 + 6; } - + //处理缓存数据的'startTs'字段统一成'startTime' + private toAsyncFuncCache(object: any, name: string): void { + let modifiedObject = { ...object }; + modifiedObject['startTime'] = modifiedObject['startTs']; + delete modifiedObject['startTs']; + modifiedObject.rowId = name; + modifiedObject.type = 'func'; + SpProcessChart.asyncFuncCache.push({ ...modifiedObject }); + } //Async Function addAsyncFunction(it: { pid: number; processName: string | null }, processRow: TraceRow): void { + let isCategoryAsyncfunc: boolean = FlagsConfig.getFlagsConfigEnableStatus('Start&Finish Trace Category'); //@ts-ignore let asyncFuncList = this.processAsyncFuncMap[it.pid] || []; - let asyncFuncGroup = Utils.groupBy(asyncFuncList, 'funName'); // @ts-ignore - Reflect.ownKeys(asyncFuncGroup).map((key: unknown) => { - // @ts-ignore - let asyncFunctions: Array = asyncFuncGroup[key]; - if (asyncFunctions.length > 0) { - let isIntersect = (a: unknown, b: unknown): boolean => - //@ts-ignore - Math.max(a.startTs + a.dur, b.startTs + b.dur) - Math.min(a.startTs, b.startTs) < a.dur + b.dur; - let depthArray: unknown = []; - asyncFunctions.forEach((it, i) => { - //@ts-ignore + if (!asyncFuncList.length) { + return; + } + if (isCategoryAsyncfunc) {//聚合异步trace + let { asyncRemoveCatArr, asyncCatMap } = this.hanldCategoryAsyncFunc(asyncFuncList); + let { setArrayLenThanOne, setArrayLenOnlyOne } = this.hanldAsyncFunc(it, asyncRemoveCatArr); + //处理cat不为null和length等于1的数据 + let aggregateData = { ...Object.fromEntries(asyncCatMap), ...setArrayLenOnlyOne }; + Reflect.ownKeys(aggregateData).map((key: any) => { + let param: Array = aggregateData[key]; + this.makeAddAsyncFunction(param, it, processRow, key); + }) + //处理length大于1的数据,不传key值 + Reflect.ownKeys(setArrayLenThanOne).map((key: any) => { + let param: Array = setArrayLenThanOne[key]; + this.makeAddAsyncFunction(param, it, processRow); + }) + } else { + //不聚合异步trace + let asyncFuncGroup = Utils.groupBy(asyncFuncList, 'funName'); + //@ts-ignore + Reflect.ownKeys(asyncFuncGroup).map((key: any) => { + //@ts-ignore + let asyncFunctions: Array = asyncFuncGroup[key]; + if (asyncFunctions.length > 0) { + let isIntersect = (a: any, b: any): boolean => + Math.max(a.startTs + a.dur, b.startTs + b.dur) - Math.min(a.startTs, b.startTs) < a.dur + b.dur; + let depthArray: any = []; + asyncFunctions.forEach((it, i) => { + if (it.dur === -1 || it.dur === null || it.dur === undefined) { + it.dur = (TraceRow.range?.endNS || 0) - it.startTs; + it.flag = 'Did not end'; + } + let currentDepth = 0; + let index = i; + while ( + depthArray[currentDepth] !== undefined && + isIntersect(depthArray[currentDepth], asyncFunctions[index]) + ) { + currentDepth++; + } + asyncFunctions[index].depth = currentDepth; + depthArray[currentDepth] = asyncFunctions[index]; + this.toAsyncFuncCache(asyncFunctions[index], `${asyncFunctions[i].funName}-${it.pid}`);//处理缓存的异步trace数据缺失的字段 + }); + } + this.lanesConfig(asyncFunctions, it, processRow); + }); + } + } + //处理CategoryAsyncFunc + hanldCategoryAsyncFunc( + asyncFuncList: Array + ): { asyncRemoveCatArr: Array, asyncCatMap: Map> } { + let asyncCatMap: Map = new Map(); + let asyncRemoveCatArr = new Array(); + //取出cat字段(category)不为null的数据 + for (let i = 0; i < asyncFuncList.length; i++) { + const el = asyncFuncList[i]; + if (el.cat !== null) { + if (asyncCatMap.has(`${el.cat}:${el.threadName} ${el.tid}`)) { + let item: Array = asyncCatMap.get(`${el.cat}:${el.threadName} ${el.tid}`); + item.push(el); + } else { + asyncCatMap.set(`${el.cat}:${el.threadName} ${el.tid}`, [el]); + } + } else { + //取cat字段为null的数据 + asyncRemoveCatArr.push(el); + } + } + return { asyncRemoveCatArr, asyncCatMap }; + } + //处理cat字段为null的数据,按funname分类,分别按len>1和=1去处理 + hanldAsyncFunc( + it: { pid: number; processName: string | null }, + asyncRemoveCatList: Array + ): { setArrayLenThanOne: any, setArrayLenOnlyOne: any } { + let asyncFuncGroup = Utils.groupBy(asyncRemoveCatList, 'funName'); + let funcArr: unknown[] = []; + let setArrayLenThanOne: unknown = {}; + let setArrayLenOnlyOne: unknown = {}; + //@ts-ignore + Reflect.ownKeys(asyncFuncGroup).map((key: any) => { + //@ts-ignore + let asyncFunctions: Array = asyncFuncGroup[key]; + if (asyncFunctions.length > 1) { + //@ts-ignore + setArrayLenThanOne[`${asyncFunctions[0].funName}-${it.pid}`] = asyncFunctions; + } else if (asyncFunctions.length === 1) { + funcArr.push(...asyncFunctions); + } + }); + //len=1的数据继续按tid分类 + let asyncFuncTidGroup = Utils.groupBy(funcArr, 'tid'); + //@ts-ignore + Reflect.ownKeys(asyncFuncTidGroup).map((key: any) => { + //@ts-ignore + let asyncTidFunc: Array = asyncFuncTidGroup[key]; + //@ts-ignore + setArrayLenOnlyOne[`H:${asyncTidFunc[0].threadName} ${asyncTidFunc[0].tid}`] = asyncTidFunc; + }); + return { setArrayLenThanOne, setArrayLenOnlyOne } + } + makeAddAsyncFunction( + asyncFunctions: any[], + it: { pid: number; processName: string | null }, + processRow: TraceRow, + key?: string + ) { + let maxDepth: number = -1; + let i = 0; + let mapDepth = new Map(); + let noEndData = new Array(); + let normalData = new Array(); + if (asyncFunctions.length) { + while (i < asyncFunctions.length) { + let param = asyncFunctions[i]; + if (param.dur !== null) { + let itemEndTime = param.startTs + param.dur; + let flag = false; + for (let [key, val] of mapDepth.entries()) { + if (val.et < param.startTs) { + flag = true; + val.et = itemEndTime;//更新endts + param.depth = Number(key); + break; + } + } + if (!flag) {//depth增加 + maxDepth++; + mapDepth.set(`${maxDepth}`, { et: itemEndTime }); + param.depth = maxDepth; + } + this.toAsyncFuncCache(param, key ? key : `${asyncFunctions[i].funName}-${it.pid}`); + normalData.push(param); + } else { + noEndData.push(param); + } + i++; + } + if (noEndData.length) { + noEndData.forEach((it: any, i: any) => { if (it.dur === -1 || it.dur === null || it.dur === undefined) { - //@ts-ignore - it.dur = (TraceRow.range?.endNS || 0) - it.startTs; //@ts-ignore + it.dur = (TraceRow.range?.endNS || 0) - it.startTs; + it.nofinish = true; it.flag = 'Did not end'; } - let currentDepth = 0; let index = i; - while ( - //@ts-ignore - depthArray[currentDepth] !== undefined && //@ts-ignore - isIntersect(depthArray[currentDepth], asyncFunctions[index]) - ) { - currentDepth++; - } //@ts-ignore - asyncFunctions[index].depth = currentDepth; //@ts-ignore - depthArray[currentDepth] = asyncFunctions[index]; + maxDepth++; + noEndData[index].depth = maxDepth; + this.toAsyncFuncCache(noEndData[index], key ? key : `${asyncFunctions[i].funName}-${it.pid}`); }); - const maxHeight = this.calMaxHeight(asyncFunctions); - let funcRow = TraceRow.skeleton(); //@ts-ignore - funcRow.rowId = `${asyncFunctions[0].funName}-${it.pid}`; //@ts-ignore - funcRow.asyncFuncName = asyncFunctions[0].funName; - funcRow.asyncFuncNamePID = it.pid; - funcRow.rowType = TraceRow.ROW_TYPE_FUNC; - funcRow.enableCollapseChart(); //允许折叠泳道图 - funcRow.rowParentId = `${it.pid}`; - funcRow.rowHidden = !processRow.expansion; - funcRow.style.width = '100%'; - funcRow.style.height = `${maxHeight}px`; - funcRow.setAttribute('height', `${maxHeight}`); //@ts-ignore - funcRow.name = `${asyncFunctions[0].funName}`; - funcRow.setAttribute('children', ''); - funcRow.findHoverStruct = (): void => { - FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); - }; //@ts-ignore - funcRow.supplier = (): Promise => new Promise((resolve) => resolve(asyncFunctions)); - funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - funcRow.selectChangeHandler = this.trace.selectChangeHandler; - funcRow.onThreadHandler = rowThreadHandler( - 'func', - 'context', - { - //@ts-ignore - type: `func-${asyncFunctions[0].funName}-${it.pid}`, - }, - funcRow, - this.trace - ); - processRow.addChildTraceRow(funcRow); } - }); + this.lanesConfig([...normalData, ...noEndData], it, processRow, key); + } + } + //初始化异步泳道信息 + lanesConfig( + asyncFunctions: any[], + it: { pid: number; processName: string | null }, + processRow: TraceRow, + key?: string + ) { + const maxHeight = this.calMaxHeight(asyncFunctions); + const namesSet = new Set(asyncFunctions.map((item) => item.funName)); + const asyncFuncName = Array.from(namesSet); + let funcRow = TraceRow.skeleton(); + funcRow.rowId = key ? key : `${asyncFunctions[0].funName}-${it.pid}`; + funcRow.asyncFuncName = asyncFuncName; + funcRow.asyncFuncNamePID = it.pid; + funcRow.rowType = TraceRow.ROW_TYPE_FUNC; + funcRow.enableCollapseChart(FOLD_HEIGHT, this.trace); //允许折叠泳道图 + funcRow.rowParentId = `${it.pid}`; + funcRow.rowHidden = !processRow.expansion; + funcRow.style.width = '100%'; + funcRow.style.height = `${maxHeight}px`; + funcRow.setAttribute('height', `${maxHeight}`); + funcRow.name = key ? key : `${asyncFunctions[0].funName}`; + funcRow.setAttribute('children', ''); + funcRow.findHoverStruct = (): void => { + FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); + }; + funcRow.supplier = (): Promise => new Promise((resolve) => resolve(asyncFunctions)); + funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + funcRow.selectChangeHandler = this.trace.selectChangeHandler; + funcRow.onThreadHandler = rowThreadHandler( + 'func', + 'context', + { + type: `func-${funcRow.rowId}`, + }, + funcRow, + this.trace + ); + processRow.addChildTraceRow(funcRow); } addAsyncCatFunction(it: { pid: number; processName: string | null }, processRow: TraceRow): void {//@ts-ignore let asyncFuncCatList = this.processAsyncFuncCatMap[it.pid] || []; - let asyncFuncGroup: unknown = Utils.groupBy(asyncFuncCatList, 'threadName');//@ts-ignore - Reflect.ownKeys(asyncFuncGroup).map((key: unknown) => {//@ts-ignore + let asyncFuncGroup: unknown = Utils.groupBy(asyncFuncCatList, 'threadName'); //@ts-ignore + Reflect.ownKeys(asyncFuncGroup).map((key: unknown) => { //@ts-ignore let asyncFunctions: Array = asyncFuncGroup[key]; if (asyncFunctions.length > 0) { - let isIntersect = (a: unknown, b: unknown): boolean =>//@ts-ignore + let isIntersect = (a: unknown, b: unknown): boolean => //@ts-ignore Math.max(a.startTs + a.dur, b.startTs + b.dur) - Math.min(a.startTs, b.startTs) < a.dur + b.dur; let depthArray: unknown = []; asyncFunctions.forEach((it, i) => {//@ts-ignore @@ -1130,7 +1479,8 @@ export class SpProcessChart { currentDepth++; }//@ts-ignore asyncFunctions[index].depth = currentDepth;//@ts-ignore - depthArray[currentDepth] = asyncFunctions[index]; + depthArray[currentDepth] = asyncFunctions[index];//@ts-ignore + this.toAsyncFuncCache(asyncFunctions[index], `${asyncFunctions[0].threadName}`); }); const maxHeight = this.calMaxHeight(asyncFunctions); let funcRow = TraceRow.skeleton();//@ts-ignore @@ -1138,7 +1488,7 @@ export class SpProcessChart { funcRow.asyncFuncThreadName = asyncFunctions[0].threadName; funcRow.asyncFuncNamePID = it.pid; funcRow.rowType = TraceRow.ROW_TYPE_FUNC; - funcRow.enableCollapseChart(); //允许折叠泳道图 + funcRow.enableCollapseChart(FOLD_HEIGHT, this.trace); //允许折叠泳道图 funcRow.rowParentId = `${it.pid}`; funcRow.rowHidden = !processRow.expansion; funcRow.style.width = '100%'; @@ -1148,11 +1498,11 @@ export class SpProcessChart { funcRow.setAttribute('children', ''); funcRow.findHoverStruct = (): void => { FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); - }; //@ts-ignore + }; //@ts-ignore funcRow.supplier = (): Promise => new Promise((resolve) => resolve(asyncFunctions)); funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; funcRow.selectChangeHandler = this.trace.selectChangeHandler; - funcRow.onThreadHandler = rowThreadHandler('func', 'context', {//@ts-ignore + funcRow.onThreadHandler = rowThreadHandler('func', 'context', { //@ts-ignore type: `func-${asyncFunctions[0].threadName}-${it.pid}`, }, funcRow, this.trace); processRow.addChildTraceRow(funcRow); diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index 98cbb2e31be2131275882ae32f5834c968e8ed77..d0c862de9dcbd15bc70f01cee48e27b0d7ae7fd2 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -1,3 +1,4 @@ + /* * Copyright (C) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +19,11 @@ import { renders } from '../../database/ui-worker/ProcedureWorker'; import { type EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { type FreqExtendRender, CpuFreqExtendStruct } from '../../database/ui-worker/ProcedureWorkerFreqExtend'; import { type BinderRender, BinderStruct } from '../../database/ui-worker/procedureWorkerBinder'; -import { queryIrqList } from '../../database/sql/Irq.sql'; import { type BaseStruct } from '../../bean/BaseStruct'; -import { type ThreadRender, ThreadStruct } from '../../database/ui-worker/ProcedureWorkerThread'; +import { type AllStatesRender, AllstatesStruct } from '../../database/ui-worker/ProcedureWorkerAllStates'; import { StateGroup } from '../../bean/StateModle'; import { queryAllFuncNames } from '../../database/sql/Func.sql'; +import { Utils } from '../trace/base/Utils'; const UNIT_HEIGHT: number = 20; const MS_TO_US: number = 1000000; const MIN_HEIGHT: number = 2; @@ -33,11 +34,15 @@ export class SpSegmentationChart { static binderRow: TraceRow | undefined; static schedRow: TraceRow | undefined; static freqInfoMapData = new Map>(); + static hoverLine: Array = []; + static tabHoverObj: { key: string, cycle: number }; private rowFolder!: TraceRow; static chartData: Array = []; - static statesRow: TraceRow | undefined; + static statesRow: TraceRow | undefined; // 数据切割联动 static setChartData(type: string, data: Array): void { + SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; if (type === 'CPU-FREQ') { setCpuData(data); } else if (type === 'GPU-FREQ') { @@ -50,20 +55,22 @@ export class SpSegmentationChart { // state泳道联动 static setStateChartData(data: Array) { + SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; let stateChartData = new Array(); - stateChartData = data.map((v) => { + stateChartData = data.map(v => { return { dur: v.dur, + chartDur: v.chartDur, pid: v.pid, tid: v.tid, - end_ts: v.ts + v.dur!, + end_ts: v.startTs! + v.chartDur!, id: v.id, name: 'all-state', - startTime: v.ts, - start_ts: v.ts, + startTime: v.startTs, + start_ts: v.startTs, state: v.state, type: v.type, - cpu: v.cpu, cycle: v.cycle, }; }); @@ -72,18 +79,21 @@ export class SpSegmentationChart { SpSegmentationChart.statesRow!.isComplete = false; // @ts-ignore SpSegmentationChart.statesRow!.supplier = (): Promise> => - new Promise>((resolve) => resolve(stateChartData)); + new Promise>((resolve) => resolve(stateChartData)); SpSegmentationChart.trace.refreshCanvas(false); - } + }; // binder联动调用 static setBinderChartData(data: Array>): void { + SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; BinderStruct.maxHeight = 0; SpSegmentationChart.binderRow!.dataList = []; SpSegmentationChart.binderRow!.dataListCache = []; SpSegmentationChart.binderRow!.isComplete = false; if (data.length === 0) { SpSegmentationChart.binderRow!.style.height = `40px`; + SpSegmentationChart.binderRow!.funcMaxHeight = 40; // @ts-ignore SpSegmentationChart.binderRow!.supplier = (): Promise> => new Promise>((resolve) => resolve([])); @@ -97,10 +107,10 @@ export class SpSegmentationChart { v.name === 'binder transaction' ? 0 : v.name === 'binder transaction async' - ? 1 - : v.name === 'binder reply' - ? MS_TO_US - : 3, + ? 1 + : v.name === 'binder reply' + ? MS_TO_US + : 3, startNS: v.startNS, dur: v.dur, name: `${v.name}`, @@ -109,74 +119,43 @@ export class SpSegmentationChart { cycle: v.cycle, }; }); - SpSegmentationChart.binderRow!.style.height = `${ - BinderStruct.maxHeight > MIN_HEIGHT ? BinderStruct.maxHeight * UNIT_HEIGHT + UNIT_HEIGHT : 40 - }px`; // @ts-ignore SpSegmentationChart.binderRow!.supplier = (): Promise> => new Promise>((resolve) => resolve(chartData)); + SpSegmentationChart.binderRow!.style.height = `${BinderStruct.maxHeight > MIN_HEIGHT ? BinderStruct.maxHeight * UNIT_HEIGHT + UNIT_HEIGHT : 40}px`; + SpSegmentationChart.binderRow!.funcMaxHeight = BinderStruct.maxHeight > MIN_HEIGHT ? BinderStruct.maxHeight * UNIT_HEIGHT + UNIT_HEIGHT : 40; } - + TraceRow.range!.refresh = true; + SpSegmentationChart.binderRow!.needRefresh = true; + SpSegmentationChart.binderRow!.draw(false); + if (SpSegmentationChart.binderRow!.collect) { + window.publish(window.SmartEvent.UI.RowHeightChange, { + expand: SpSegmentationChart.binderRow!.funcExpand, + value: SpSegmentationChart.binderRow!.funcMaxHeight - 40, + }); + } + SpSegmentationChart.trace.favoriteChartListEL?.scrollTo(0,0); SpSegmentationChart.trace.refreshCanvas(false); } // 悬浮联动 static tabHover(type: string, tableIsHover: boolean = false, cycle: number = -1): void { - CpuFreqExtendStruct.isTabHover = tableIsHover; - if (type === 'CPU-FREQ' || type === 'GPU-FREQ' || type === 'SCHED-SWITCH') { - // 竖线显示处理 - if (type === 'SCHED-SWITCH') { - CpuFreqExtendStruct.cpuCycle = -1; - CpuFreqExtendStruct.gpuCycle = -1; - if (cycle === CpuFreqExtendStruct.schedCycle) { - CpuFreqExtendStruct.isTabHover = false; - CpuFreqExtendStruct.schedCycle = -1; - } else { - CpuFreqExtendStruct.isTabHover = true; - CpuFreqExtendStruct.schedCycle = cycle; - BinderStruct.isTabHover = false; - } - } else if (type === 'CPU-FREQ') { - CpuFreqExtendStruct.gpuCycle = -1; - CpuFreqExtendStruct.schedCycle = -1; - if (cycle === CpuFreqExtendStruct.cpuCycle) { - CpuFreqExtendStruct.isTabHover = false; - CpuFreqExtendStruct.cpuCycle = -1; - } else { - CpuFreqExtendStruct.isTabHover = true; - CpuFreqExtendStruct.cpuCycle = cycle; - BinderStruct.isTabHover = false; - } - } else if (type === 'GPU-FREQ') { - CpuFreqExtendStruct.cpuCycle = -1; - CpuFreqExtendStruct.schedCycle = -1; - if (cycle === CpuFreqExtendStruct.gpuCycle) { - CpuFreqExtendStruct.gpuCycle = -1; - CpuFreqExtendStruct.isTabHover = false; - } else { - CpuFreqExtendStruct.gpuCycle = cycle; - CpuFreqExtendStruct.isTabHover = true; - BinderStruct.isTabHover = false; - } - } - CpuFreqExtendStruct.hoverType = type; - } else if (type === 'BINDER') { - if (cycle === BinderStruct.hoverCycle) { - BinderStruct.hoverCycle = -1; - BinderStruct.isTabHover = false; - CpuFreqExtendStruct.isTabHover = false; + if (tableIsHover) { + if (SpSegmentationChart.tabHoverObj.cycle === cycle && SpSegmentationChart.tabHoverObj.key === type) { + SpSegmentationChart.tabHoverObj = { cycle: -1, key: '' } } else { - BinderStruct.hoverCycle = cycle; - BinderStruct.isTabHover = true; + SpSegmentationChart.tabHoverObj = { cycle, key: type } } + } else { + SpSegmentationChart.tabHoverObj = { cycle: -1, key: '' } } + SpSegmentationChart.trace.refreshCanvas(false); } constructor(trace: SpSystemTrace) { SpSegmentationChart.trace = trace; } async init() { - let funArr = await queryAllFuncNames(); - if (funArr.length > 0) { + if (Utils.getInstance().getCallStatckMap().size > 0) { await this.initFolder(); await this.initCpuFreq(); await this.initGpuTrace(); @@ -184,12 +163,11 @@ export class SpSegmentationChart { await this.initBinderTrace(); await this.initAllStates(); } else { - return; + return } } async initFolder() { let row = TraceRow.skeleton(); - row.setAttribute('disabled-check', ''); row.rowId = 'segmentation'; row.index = 0; row.rowType = TraceRow.ROW_TYPE_SPSEGNENTATION; @@ -201,7 +179,6 @@ export class SpSegmentationChart { row.onThreadHandler = (useCache): void => { row.canvasSave(SpSegmentationChart.trace.canvasPanelCtx!); if (row.expansion) { - // @ts-ignore SpSegmentationChart.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); } else { (renders['empty'] as EmptyRender).renderMainThread( @@ -249,14 +226,13 @@ export class SpSegmentationChart { SpSegmentationChart.cpuRow.focusHandler = (ev): void => { SpSegmentationChart.trace?.displayTip( SpSegmentationChart.cpuRow!, - CpuFreqExtendStruct.hoverCpuFreqStruct, - `${ - CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value! + CpuFreqExtendStruct.hoverStruct, + `${CpuFreqExtendStruct.hoverStruct === undefined ? 0 : CpuFreqExtendStruct.hoverStruct.value! }` ); }; SpSegmentationChart.cpuRow.findHoverStruct = (): void => { - CpuFreqExtendStruct.hoverCpuFreqStruct = SpSegmentationChart.cpuRow!.getHoverStruct(); + CpuFreqExtendStruct.hoverStruct = SpSegmentationChart.cpuRow!.getHoverStruct(); }; // @ts-ignore SpSegmentationChart.cpuRow.supplier = (): Promise> => @@ -299,14 +275,13 @@ export class SpSegmentationChart { SpSegmentationChart.GpuRow.focusHandler = (ev): void => { SpSegmentationChart.trace?.displayTip( SpSegmentationChart.GpuRow!, - CpuFreqExtendStruct.hoverCpuFreqStruct, - `${ - CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value! + CpuFreqExtendStruct.hoverStruct, + `${CpuFreqExtendStruct.hoverStruct === undefined ? 0 : CpuFreqExtendStruct.hoverStruct.value! }` ); }; SpSegmentationChart.GpuRow.findHoverStruct = (): void => { - CpuFreqExtendStruct.hoverCpuFreqStruct = SpSegmentationChart.GpuRow!.getHoverStruct(); + CpuFreqExtendStruct.hoverStruct = SpSegmentationChart.GpuRow!.getHoverStruct(); }; SpSegmentationChart.GpuRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; @@ -343,12 +318,12 @@ export class SpSegmentationChart { SpSegmentationChart.schedRow.focusHandler = (ev): void => { SpSegmentationChart.trace?.displayTip( SpSegmentationChart.schedRow!, - CpuFreqExtendStruct.hoverCpuFreqStruct, - `${CpuFreqExtendStruct.hoverCpuFreqStruct?.value!}` + CpuFreqExtendStruct.hoverStruct, + `${CpuFreqExtendStruct.hoverStruct?.value!}` ); }; SpSegmentationChart.schedRow.findHoverStruct = (): void => { - CpuFreqExtendStruct.hoverCpuFreqStruct = SpSegmentationChart.schedRow!.getHoverStruct(); + CpuFreqExtendStruct.hoverStruct = SpSegmentationChart.schedRow!.getHoverStruct(); }; // @ts-ignore SpSegmentationChart.schedRow.supplier = (): Promise> => @@ -378,7 +353,7 @@ export class SpSegmentationChart { } async initAllStates() { - SpSegmentationChart.statesRow = TraceRow.skeleton(); + SpSegmentationChart.statesRow = TraceRow.skeleton(); SpSegmentationChart.statesRow.rowId = `statesrow`; SpSegmentationChart.statesRow.rowType = TraceRow.ROW_TYPE_THREAD; SpSegmentationChart.statesRow.rowParentId = ''; @@ -394,12 +369,10 @@ export class SpSegmentationChart { if (SpSegmentationChart.statesRow!.currentContext) { context = SpSegmentationChart.statesRow!.currentContext; } else { - context = SpSegmentationChart.statesRow!.collect - ? SpSegmentationChart.trace.canvasFavoritePanelCtx! - : SpSegmentationChart.trace.canvasPanelCtx!; + context = SpSegmentationChart.statesRow!.collect ? SpSegmentationChart.trace.canvasFavoritePanelCtx! : SpSegmentationChart.trace.canvasPanelCtx!; } SpSegmentationChart.statesRow!.canvasSave(context); - (renders['thread'] as ThreadRender).renderMainThread( + (renders.stateCut as AllStatesRender).renderMainThread( { context: context, useCache: useCache, @@ -418,6 +391,7 @@ export class SpSegmentationChart { SpSegmentationChart.binderRow = TraceRow.skeleton(); SpSegmentationChart.binderRow.rowId = 'binderrow'; SpSegmentationChart.binderRow.rowType = TraceRow.ROW_TYPE_BINDER_COUNT; + SpSegmentationChart.binderRow.enableCollapseChart(40, SpSegmentationChart.trace); SpSegmentationChart.binderRow.rowParentId = ''; SpSegmentationChart.binderRow.name = 'Binder Count'; SpSegmentationChart.binderRow.style.height = '40px'; @@ -426,17 +400,28 @@ export class SpSegmentationChart { SpSegmentationChart.binderRow.findHoverStruct = () => { BinderStruct.hoverCpuFreqStruct = SpSegmentationChart.binderRow!.dataListCache.find((v: BinderStruct) => { if (SpSegmentationChart.binderRow!.isHover) { - if ( - v.frame!.x < SpSegmentationChart.binderRow!.hoverX && - v.frame!.x + v.frame!.width > SpSegmentationChart.binderRow!.hoverX && - BinderStruct.maxHeight * 20 - v.depth * 20 + 20 < SpSegmentationChart.binderRow!.hoverY && - BinderStruct.maxHeight * 20 - v.depth * 20 + v.value * 20 + 20 > SpSegmentationChart.binderRow!.hoverY - ) { + if (v.frame!.x < SpSegmentationChart.binderRow!.hoverX + 1 + && v.frame!.x + v.frame!.width > SpSegmentationChart.binderRow!.hoverX - 1 + && (BinderStruct.maxHeight * 20 - v.depth * 20 + 20) < SpSegmentationChart.binderRow!.hoverY + && BinderStruct.maxHeight * 20 - v.depth * 20 + v.value * 20 + 20 > SpSegmentationChart.binderRow!.hoverY) { return v; } } - }); + }) }; + SpSegmentationChart.binderRow.focusHandler = (ev): void => { + SpSegmentationChart.trace!.displayTip( + SpSegmentationChart.binderRow!, + BinderStruct.hoverCpuFreqStruct, + `Cycle: ${BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.cycle : 0 + }
+ Name: ${BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.name : '' + }
+ Count: ${BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.value : 0 + }` + ); + }; + SpSegmentationChart.binderRow.supplier = (): Promise> => new Promise>((resolve) => resolve([])); SpSegmentationChart.binderRow.onThreadHandler = (useCache): void => { @@ -453,27 +438,12 @@ export class SpSegmentationChart { { context: context, useCache: useCache, - type: 'binder', + type: 'BINDER', }, SpSegmentationChart.binderRow! ); SpSegmentationChart.binderRow!.canvasRestore(context); }; - SpSegmentationChart.binderRow.focusHandler = (ev): void => { - SpSegmentationChart.trace!.displayTip( - SpSegmentationChart.binderRow!, - BinderStruct.hoverCpuFreqStruct, - `Cycle: ${ - BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.cycle : 0 - }
- Name: ${ - BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.name : '' - }
- Count: ${ - BinderStruct.hoverCpuFreqStruct ? BinderStruct.hoverCpuFreqStruct.value : 0 - }` - ); - }; SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.binderRow); this.rowFolder!.addChildTraceRow(SpSegmentationChart.binderRow); } @@ -552,8 +522,8 @@ function setBinderData(data: Array>, binderList: Arra return i.name === 'binder transaction'; }).length > 0 ? v.filter((i: FreqChartDataStruct) => { - return i.name === 'binder transaction'; - })[0].value + return i.name === 'binder transaction'; + })[0].value : 0); } if (t.name === 'binder reply') { @@ -563,15 +533,15 @@ function setBinderData(data: Array>, binderList: Arra return i.name === 'binder transaction'; }).length > 0 ? v.filter((i: FreqChartDataStruct) => { - return i.name === 'binder transaction'; - })[0].value + return i.name === 'binder transaction'; + })[0].value : 0) + (v.filter((i: FreqChartDataStruct) => { return i.name === 'binder transaction async'; }).length > 0 ? v.filter((i: FreqChartDataStruct) => { - return i.name === 'binder transaction async'; - })[0].value + return i.name === 'binder transaction async'; + })[0].value : 0); } if (t.name === 'binder async rcv') { @@ -581,22 +551,22 @@ function setBinderData(data: Array>, binderList: Arra return i.name === 'binder transaction'; }).length > 0 ? v.filter((i: FreqChartDataStruct) => { - return i.name === 'binder transaction'; - })[0].value + return i.name === 'binder transaction'; + })[0].value : 0) + (v.filter((i: FreqChartDataStruct) => { return i.name === 'binder transaction async'; }).length > 0 ? v.filter((i: FreqChartDataStruct) => { - return i.name === 'binder transaction async'; - })[0].value + return i.name === 'binder transaction async'; + })[0].value : 0) + (v.filter((i: FreqChartDataStruct) => { return i.name === 'binder reply'; }).length > 0 ? v.filter((i: FreqChartDataStruct) => { - return i.name === 'binder reply'; - })[0].value + return i.name === 'binder reply'; + })[0].value : 0); } binderList.push(t); @@ -606,3 +576,8 @@ function setBinderData(data: Array>, binderList: Arra listCount = 0; }); } + +class heightLine { + key: string = ''; + cycle: number = -1 +} diff --git a/ide/src/trace/component/chart/SpUserPluginChart.ts b/ide/src/trace/component/chart/SpUserPluginChart.ts index b2116110aab74b68128772176f194ac935f21bf7..07ff621c8c730edfb87e1fa46b25d1022cbc2c71 100644 --- a/ide/src/trace/component/chart/SpUserPluginChart.ts +++ b/ide/src/trace/component/chart/SpUserPluginChart.ts @@ -102,6 +102,32 @@ export class SpUserFileChart { }; traceRow.style.height = `${height}px`; }) + } else { + traceRow.supplier = () => + new Promise((resolve): void => { + resolve([]); + }); + traceRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (traceRow.currentContext) { + context = traceRow.currentContext; + } else { + context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + traceRow.canvasSave(context); + (renders.sample as SampleRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'bpftrace', + start_ts: 0, + uniqueProperty: [], + flattenTreeArray: [], + }, + traceRow + ); + traceRow.canvasRestore(context); + }; } return traceRow; } diff --git a/ide/src/trace/component/chart/VSync.ts b/ide/src/trace/component/chart/VSync.ts index d53f17e590cc033d8e07591b1e082fd4f7cf67fb..7165596bac2e7b2181a1e727d3844fc3fa3fa659 100644 --- a/ide/src/trace/component/chart/VSync.ts +++ b/ide/src/trace/component/chart/VSync.ts @@ -48,27 +48,28 @@ export const querySfVSyncData = (): Promise> => })` ); -export const querySingleVSyncData = (): Promise> => { - let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); - let flagsItemJson = JSON.parse(flagsItem!); - let vsyncValue = flagsItemJson.vsyncValue; - let vsyncCondition = ''; - if (vsyncValue === 'H:VsyncGenerator' || vsyncValue === '') { - vsyncCondition = ` AND (callstack.name like 'H:GenerateVsyncCount%' or callstack.name like 'H:VSyncGenerator::ThreadLoop::Continue%'))`; - } else { - vsyncCondition = ` AND callstack.name like '${vsyncValue}%' )`; - } - - let sql = - `SELECT c.ts - tb.start_ts startTime + export const querySingleVSyncData = (): Promise> => { + let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); + let flagsItemJson = JSON.parse(flagsItem!); + let vsyncValue = flagsItemJson.vsyncValue; + let vsyncCondition = ''; + if (vsyncValue === 'H:VsyncGenerator' || vsyncValue === '') { + vsyncCondition = ` AND (callstack.name like 'H:GenerateVsyncCount%'))`; + } else { + vsyncCondition = ` AND callstack.name like '${vsyncValue}%' )`; + } + + let sql = + `SELECT 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 = 'render_service'` + vsyncCondition; - return query('querySingleVSyncData', sql); -}; + WHERE process.name = 'render_service'` + + vsyncCondition; + return query('querySingleVSyncData', sql); + } /** * load single vsync data diff --git a/ide/src/trace/component/schedulingAnalysis/SpSchedulingAnalysis.ts b/ide/src/trace/component/schedulingAnalysis/SpSchedulingAnalysis.ts index 90ffcb03605c45ecc263a0b5a361698f2df6170b..4257627db0dda5ad8c013dd9819442b4ffe9e30b 100644 --- a/ide/src/trace/component/schedulingAnalysis/SpSchedulingAnalysis.ts +++ b/ide/src/trace/component/schedulingAnalysis/SpSchedulingAnalysis.ts @@ -22,6 +22,7 @@ import { LitTabs } from '../../../base-ui/tabs/lit-tabs'; import { CheckCpuSetting } from './CheckCpuSetting'; import { Top20FrequencyThread } from './Top20FrequencyThread'; import { procedurePool } from '../../database/Procedure'; +import { Utils } from '../trace/base/Utils'; @element('sp-scheduling-analysis') export class SpSchedulingAnalysis extends BaseElement { @@ -54,7 +55,7 @@ export class SpSchedulingAnalysis extends BaseElement { SpSchedulingAnalysis.startTs = (window as unknown).recordStartNS; //@ts-ignore SpSchedulingAnalysis.endTs = (window as unknown).recordEndNS; SpSchedulingAnalysis.totalDur = SpSchedulingAnalysis.endTs - SpSchedulingAnalysis.startTs; //@ts-ignore - SpSchedulingAnalysis.cpuCount = (window as unknown).cpuCount; + SpSchedulingAnalysis.cpuCount = Utils.getInstance().getWinCpuCount(); this.tabCpuAnalysis?.init(); this.tabThreadAnalysis?.init(); } diff --git a/ide/src/trace/component/schedulingAnalysis/TabCpuDetailsThreads.ts b/ide/src/trace/component/schedulingAnalysis/TabCpuDetailsThreads.ts index f6fecfa9a693b9af836f62c5b62471e9e0a00cf1..741b1f3989f4e5737f37d234d0592c063de24031 100644 --- a/ide/src/trace/component/schedulingAnalysis/TabCpuDetailsThreads.ts +++ b/ide/src/trace/component/schedulingAnalysis/TabCpuDetailsThreads.ts @@ -124,29 +124,29 @@ export class TabCpuDetailsThreads extends BaseElement { tip: (obj): string => { return `
t_name:${ - // @ts-ignore - obj.obj.tName - }
+ // @ts-ignore + obj.obj.tName + }
tid:${ - // @ts-ignore - obj.obj.tid - }
+ // @ts-ignore + obj.obj.tid + }
p_name:${ - // @ts-ignore - obj.obj.pName - }
+ // @ts-ignore + obj.obj.pName + }
p_pid:${ - // @ts-ignore - obj.obj.pid - }
+ // @ts-ignore + obj.obj.pid + }
duration:${ - // @ts-ignore - obj.obj.durStr - }
+ // @ts-ignore + obj.obj.durStr + }
ratio:${ - // @ts-ignore - obj.obj.ratio - }%
+ // @ts-ignore + obj.obj.ratio + }% `; }, @@ -182,51 +182,37 @@ export class TabCpuDetailsThreads extends BaseElement { this.noData(false); } - sortByColumn(detail: unknown): void { + sortByColumn(detail: any): void { // @ts-ignore function compare(cpuDetailsThreadProperty, sort, type) { - return function (a: unknown, b: unknown) { + return function (a: any, b: any) { if (type === 'number') { // @ts-ignore return sort === 2 - // @ts-ignore ? parseFloat(b[cpuDetailsThreadProperty]) - parseFloat(a[cpuDetailsThreadProperty]) - // @ts-ignore : parseFloat(a[cpuDetailsThreadProperty]) - parseFloat(b[cpuDetailsThreadProperty]); } else { if (sort === 2) { - // @ts-ignore return b[cpuDetailsThreadProperty].toString().localeCompare(a[cpuDetailsThreadProperty].toString()); } else { - // @ts-ignore return a[cpuDetailsThreadProperty].toString().localeCompare(b[cpuDetailsThreadProperty].toString()); } } }; } - // @ts-ignore if (detail.key === 'durStr') { - // @ts-ignore detail.key = 'dur'; - // @ts-ignore this.data.sort(compare(detail.key, detail.sort, 'number')); } else if ( - // @ts-ignore detail.key === 'value' || - // @ts-ignore detail.key === 'ratio' || - // @ts-ignore detail.key === 'index' || - // @ts-ignore detail.key === 'tid' || - // @ts-ignore detail.key === 'pid' ) { - // @ts-ignore this.data.sort(compare(detail.key, detail.sort, 'number')); } else { - // @ts-ignore this.data.sort(compare(detail.key, detail.sort, 'string')); } this.cpuDetailsThreadUsageTbl!.recycleDataSource = this.data; diff --git a/ide/src/trace/component/schedulingAnalysis/Top20FrequencyThread.ts b/ide/src/trace/component/schedulingAnalysis/Top20FrequencyThread.ts index 0733b921855dfacfe8bf626e0773ab189e731b21..8005a908181bdaf4ceab9d18c87b154c08370b70 100644 --- a/ide/src/trace/component/schedulingAnalysis/Top20FrequencyThread.ts +++ b/ide/src/trace/component/schedulingAnalysis/Top20FrequencyThread.ts @@ -54,8 +54,9 @@ export class Top20FrequencyThread extends BaseElement { this.threadSelect!.onchange = (e): void => { //@ts-ignore - this.currentThread!.textContent = (e as unknown).detail.text; //@ts-ignore - this.currentTid = parseInt((e as unknown).detail.value); + this.currentThread!.textContent = (e as unknown).detail.text; + //@ts-ignore + this.currentTid = parseInt(e.detail.selectValue); this.frequencyThreadProgress!.loading = true; this.queryData(); }; diff --git a/ide/src/trace/component/setting/SpAllocation.html.ts b/ide/src/trace/component/setting/SpAllocation.html.ts index 7bc6aedb499a98407b83719f2ac191c23f757966..6391ec4e48acbf2ae0e7232f4cd6b62fe4745638 100644 --- a/ide/src/trace/component/setting/SpAllocation.html.ts +++ b/ide/src/trace/component/setting/SpAllocation.html.ts @@ -343,9 +343,9 @@ input:disabled {
Sample Interval (Available on recent OpenHarmony 4.0) - Rang is 0 - 65535, default 10 byte + Rang is 0 - 65535, default 0 byte + placeholder="Enter the interval" value="0">
diff --git a/ide/src/trace/component/setting/SpAllocations.ts b/ide/src/trace/component/setting/SpAllocations.ts index a649cf8213434dd02e96a45277c73ead67d13485..52bda968653a19e998d0c602b736c9df8648776f 100644 --- a/ide/src/trace/component/setting/SpAllocations.ts +++ b/ide/src/trace/component/setting/SpAllocations.ts @@ -421,15 +421,15 @@ export class SpAllocations extends BaseElement { this.intervalResultInput!.value = '10'; this.statisticsIntervalHandle(); this.statisticsIntervalName!.textContent = 'Sample Interval'; - this.statisticsIntervalRange!.textContent = 'Rang is 0 - 65535, default 10 byte'; - this.statisticsIntervalInput!.value = '10'; + this.statisticsIntervalRange!.textContent = 'Rang is 0 - 65535, default 0 byte'; + this.statisticsIntervalInput!.value = '0'; this.statisticsSlider!.disabled = false; this.intervalResultInput!.disabled = false; } else { this.intervalResultInput!.value = '0'; this.statisticsIntervalHandle(); this.statisticsIntervalName!.textContent = 'Malloc Free Matching Interval'; - this.statisticsIntervalRange!.textContent = 'Rang is 0 - 65535, default 10 byte'; + this.statisticsIntervalRange!.textContent = 'Rang is 0 - 65535, default 10 s'; this.statisticsIntervalInput!.value = '10'; this.statisticsSlider!.disabled = true; this.intervalResultInput!.disabled = true; @@ -537,8 +537,9 @@ export class SpAllocations extends BaseElement { private packageMouseDownHandler(packageInput: HTMLInputElement): void { if (this.startSamp && this.startup_mode) { Cmd.getPackage().then((packageList: string[]): void => { - if (packageList.length > 0) { - this.packageName!.dataSource = packageList; + let finalDataList = packageList.map(str => str.replace(/\t/g, '')); + if (finalDataList.length > 0) { + this.packageName!.dataSource = finalDataList; } else { this.packageName!.dataSource = []; } diff --git a/ide/src/trace/component/setting/SpFFRTConfig.html.ts b/ide/src/trace/component/setting/SpFFRTConfig.html.ts new file mode 100644 index 0000000000000000000000000000000000000000..4d8b1e463a2b72b1803fee37bbbd48de322c81cf --- /dev/null +++ b/ide/src/trace/component/setting/SpFFRTConfig.html.ts @@ -0,0 +1,219 @@ +/* + * 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 { ffrtEnumList } from './utils/PluginConvertUtils'; + +export const SpFFRTConfigHtml = ` + +
+
+ Start FFRT Record + +
+ +
+
+ Process + Record process id +
+ + +
+ +
+
+ Startup Process + Record startup package name +
+ + +
+ +
+
+ Restart Process + Record restart process name +
+ + +
+ +
+ Use Block + +
+ +
+ Smb Pages Size + Range is 0 - 131072, default 16384 page (One page equals 4 KB) + +
+ +
+ flush interval + Rang is 0 - 20, default 5 + +
+ +
+
+ Clock Id + Record clock type id +
+ + ${ffrtEnumList.map((clockId): string => `${clockId}`).join('')} + +
+
+`; + diff --git a/ide/src/trace/component/setting/SpFFRTConfig.ts b/ide/src/trace/component/setting/SpFFRTConfig.ts new file mode 100644 index 0000000000000000000000000000000000000000..86c6e66c53c55c1d162aa7724b5d3c98161d9aa8 --- /dev/null +++ b/ide/src/trace/component/setting/SpFFRTConfig.ts @@ -0,0 +1,279 @@ +/* + * 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'; +import { SpFFRTConfigHtml } from './SpFFRTConfig.html'; +import { log } from '../../../log/Log'; +import { NUM_16384, NUM_5 } from '../../bean/NumBean'; +import { LitSelectV } from '../../../base-ui/select/LitSelectV'; +import LitSwitch from '../../../base-ui/switch/lit-switch'; +import { LitSelect } from '../../../base-ui/select/LitSelect'; +import { Cmd } from '../../../command/Cmd'; +import { SpRecordTrace } from '../SpRecordTrace'; + +@element('sp-record-ffrt') +export class SpFFRTConfig extends BaseElement { + private processIdEl: LitSelectV | undefined; + private processIdInputEl: HTMLInputElement | undefined; + private startupProcessNameEl: LitSelectV | undefined; + private restartProcessNameEl: LitSelectV | undefined; + private restartProcessNameInputEl: HTMLInputElement | undefined; + private useBlockSwitchEl: LitSwitch | undefined; + private smbPagesInputEl: HTMLInputElement | undefined; + private flushIntervalInputEl: HTMLInputElement | undefined; + private clockTypeSelectEl: LitSelect | undefined; + private selectProcessNameList: Array = []; + + set startSamp(allocationStart: boolean) { + if (allocationStart) { + this.setAttribute('startSamp', ''); + } else { + this.removeAttribute('startSamp'); + } + } + + get startSamp(): boolean { + return this.hasAttribute('startSamp'); + } + + get processList(): string { + return this.processIdEl!.value || ''; + } + + get processIds(): number[] { + let allPidList: number[] = []; + if (this.processIdEl!.value.trim() !== '') { + let result = this.processIdEl?.value.match(/\((.+?)\)/g); + if (result) { + for (let index = 0; index < result.length; index++) { + let item = result[index]; + let currentPid = item!.replace('(', '').replace(')', ''); + allPidList.push(Number(currentPid)); + } + } + } + return allPidList; + } + + get processNames(): string[] { + let allPNameList: string[] = []; + if (this.processIdEl!.value.trim() !== '') { + let result = this.processIdEl?.value.replace(/[$(\d+)$]/g, ''); + if (result) { + allPNameList = result.split(','); + } + } + if (this.restartProcessNameEl!.value.trim() !== '') { + let result = this.restartProcessNameEl?.value.replace(/[$(\d+)$]/g, ''); + if (result) { + allPNameList.push(...result.split(',')); + } + } + return allPNameList; + } + + get startupProcessNames(): string[] { + let allPNameList: string[] = []; + if (this.startupProcessNameEl!.value.trim() !== '') { + allPNameList = this.startupProcessNameEl!.value.trim().split(','); + if (allPNameList.length === 0) { + allPNameList = this.startupProcessNameEl!.value.trim().split(';'); + } + } + return allPNameList; + } + + get restartProcessNames(): string[] { + let allPNameList: string[] = []; + if (this.restartProcessNameEl!.value.trim() !== '') { + let result = this.restartProcessNameEl?.value.replace(/[$(\d+)$]/g, ''); + if (result) { + allPNameList = result.split(','); + } + } + return allPNameList; + } + + get useBlock(): boolean { + let value = this.useBlockSwitchEl?.checked; + if (value !== undefined) { + return value; + } + return true; + } + + get smbPages(): number { + let value = this.smbPagesInputEl?.value || ''; + log(`smbPages value is :${value}`); + if (value !== '') { + return Number(this.smbPagesInputEl?.value) || NUM_16384; + } + return NUM_16384; + } + + get flushInterval(): number { + let value = this.flushIntervalInputEl?.value || ''; + log(`flushInterval value is :${value}`); + if (value !== '') { + return Number(this.flushIntervalInputEl?.value) || NUM_5; + } + return NUM_5; + } + + get clockType(): string { + return this.clockTypeSelectEl?.value || 'BOOTTIME'; + } + + initElements(): void { + this.processIdEl = this.shadowRoot?.getElementById('process-ids') as LitSelectV; + this.startupProcessNameEl = this.shadowRoot?.getElementById('startup-process-names') as LitSelectV; + this.restartProcessNameEl = this.shadowRoot?.getElementById('restart-process-names') as LitSelectV; + this.useBlockSwitchEl = this.shadowRoot?.getElementById('use_block_switch') as LitSwitch; + this.smbPagesInputEl = this.shadowRoot?.getElementById('smb-pages') as HTMLInputElement; + this.flushIntervalInputEl = this.shadowRoot?.getElementById('flush-interval') as HTMLInputElement; + this.clockTypeSelectEl = this.shadowRoot?.getElementById('clock-type') as LitSelect; + this.processIdInputEl = this.processIdEl!.shadowRoot?.querySelector('input') as HTMLInputElement; + this.restartProcessNameInputEl = this.restartProcessNameEl!.shadowRoot?.querySelector('input') as HTMLInputElement; + let litSwitch = this.shadowRoot?.querySelector('#switch-disabled') as LitSwitch; + litSwitch.addEventListener('change', (event: Event): void => { + // @ts-ignore + let detail = event.detail; + if (detail.checked) { + this.unDisable(); + } else { + this.disable(); + } + }); + let packageInput = this.startupProcessNameEl!.shadowRoot?.querySelector('input') as HTMLInputElement; + packageInput.addEventListener('mousedown', (): void => { + this.startupProcessMouseDownHandler(this.startupProcessNameEl, packageInput); + }); + packageInput.value = ''; + this.disable(); + } + + initHtml(): string { + return SpFFRTConfigHtml; + } + + connectedCallback(): void { + this.processIdInputEl?.addEventListener('mousedown', this.processMouseDownHandler); + this.restartProcessNameInputEl?.addEventListener('mousedown', this.restartProcessMouseDownHandler); + this.smbPagesInputEl?.addEventListener('keydown', this.handleInputChangeEvent); + this.flushIntervalInputEl?.addEventListener('keydown', this.handleInputChangeEvent); + } + + disconnectedCallback(): void { + this.processIdInputEl?.removeEventListener('mousedown', this.processMouseDownHandler); + this.restartProcessNameInputEl?.removeEventListener('mousedown', this.restartProcessMouseDownHandler); + this.smbPagesInputEl?.removeEventListener('keydown', this.handleInputChangeEvent); + this.flushIntervalInputEl?.removeEventListener('keydown', this.handleInputChangeEvent); + } + + processMouseDownHandler = (): void => { + this.setData(this.processIdEl); + }; + + startupProcessMouseDownHandler(startupPNameEl: LitSelectV | undefined, packageInput: HTMLInputElement): void { + if (!startupPNameEl) { + return; + } + let processInputEl = startupPNameEl.shadowRoot?.querySelector('input') as HTMLInputElement; + if (this.startSamp) { + Cmd.getPackage().then((packageList: string[]): void => { + let finalDataList = packageList.map(str => str.replace(/\t/g, '')); + if (finalDataList.length > 0) { + processInputEl.readOnly = true; + startupPNameEl.dataSource(finalDataList, 'ALL-Process'); + } else { + startupPNameEl.dataSource([], ''); + } + }); + processInputEl.readOnly = false; + } else { + processInputEl.readOnly = true; + return; + } + if (this.startSamp && (SpRecordTrace.serialNumber === '')) { + startupPNameEl.dataSource([], ''); + } + }; + + restartProcessMouseDownHandler = (): void => { + this.setData(this.restartProcessNameEl); + }; + + handleInputChangeEvent = (ev: KeyboardEvent): void => { + // @ts-ignore + if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + ev.preventDefault(); + } + }; + + private unDisable(): void { + this.startSamp = true; + if (this.useBlockSwitchEl) { + this.useBlockSwitchEl.disabled = false; + } + this.processIdEl!.removeAttribute('disabled'); + this.startupProcessNameEl!.removeAttribute('disabled'); + this.restartProcessNameEl!.removeAttribute('disabled'); + this.clockTypeSelectEl!.removeAttribute('disabled'); + let inputBoxes = this.shadowRoot?.querySelectorAll('.input-content'); + inputBoxes!.forEach((item: HTMLInputElement): void => { + item.disabled = false; + }); + } + + private disable(): void { + this.startSamp = false; + if (this.useBlockSwitchEl) { + this.useBlockSwitchEl.disabled = true; + } + this.processIdEl!.setAttribute('disabled', ''); + this.startupProcessNameEl!.setAttribute('disabled', ''); + this.restartProcessNameEl!.setAttribute('disabled', ''); + this.clockTypeSelectEl!.setAttribute('disabled', ''); + let inputBoxes = this.shadowRoot?.querySelectorAll('.input-content'); + inputBoxes!.forEach((item: HTMLInputElement): void => { + item.disabled = true; + }); + } + + private setData(selectInputEl: LitSelectV | undefined): void { + if (!selectInputEl) { + return; + } + let processInputEl = selectInputEl.shadowRoot?.querySelector('input') as HTMLInputElement; + if (this.startSamp) { + Cmd.getProcess().then((processList: string[]): void => { + selectInputEl.dataSource(processList, ''); + if (processList.length > 0) { + processInputEl.readOnly = true; + selectInputEl.dataSource(processList, 'ALL-Process'); + } else { + selectInputEl.dataSource([], ''); + } + }); + processInputEl.readOnly = false; + } else { + processInputEl.readOnly = true; + return; + } + if (this.startSamp && (SpRecordTrace.serialNumber === '')) { + selectInputEl.dataSource([], ''); + } + } +} diff --git a/ide/src/trace/component/setting/SpRecordPerf.ts b/ide/src/trace/component/setting/SpRecordPerf.ts index 1e08f1d640dbe0bc4fadf37adcd92bb0285b723a..8b4b3631b630b76e708be0ed4e2a0822b0c8d1c2 100644 --- a/ide/src/trace/component/setting/SpRecordPerf.ts +++ b/ide/src/trace/component/setting/SpRecordPerf.ts @@ -349,6 +349,7 @@ export class SpRecordPerf extends BaseElement { }; eventSelectClickHandler = (): void => { + let that = this; if (SpRecordTrace.serialNumber === '') { this.eventSelect?.dataSource(eventSelect, ''); } else { @@ -359,8 +360,8 @@ export class SpRecordPerf extends BaseElement { if (SpRecordTrace.isVscode) { let cmd = Cmd.formatString(CmdConstant.CMD_GET_HIPERF_EVENTS_DEVICES, [SpRecordTrace.serialNumber]); Cmd.execHdcCmd(cmd, (res: string) => { - let eventMap = this.parseEvent(res); - let eventList = this.getSoftHardWareEvents(eventMap); + let eventMap = that.parseEvent(res); + let eventList = that.getSoftHardWareEvents(eventMap); if (eventList) { for (let eventListElement of eventList) { this.eventData.push(eventListElement.trim()); @@ -374,8 +375,8 @@ export class SpRecordPerf extends BaseElement { if (conn) { HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_HIPERF_EVENTS, false).then((res) => { if (res) { - let eventMap = this.parseEvent(res); - let eventList = this.getSoftHardWareEvents(eventMap); + let eventMap = that.parseEvent(res); + let eventList = that.getSoftHardWareEvents(eventMap); if (eventList) { for (let eventListElement of eventList) { this.eventData.push(eventListElement.trim()); diff --git a/ide/src/trace/component/setting/SpRecordTemplate.ts b/ide/src/trace/component/setting/SpRecordTemplate.ts index ce5fba5375a400bfdb4733ca40e1af46ac9ef5ff..85265cb343364809183c9bf19712a409d2da243c 100644 --- a/ide/src/trace/component/setting/SpRecordTemplate.ts +++ b/ide/src/trace/component/setting/SpRecordTemplate.ts @@ -143,7 +143,7 @@ export class SpRecordTemplate extends BaseElement { hitraceCategories: hiTraceCategories, flushIntervalMs: 1000, hitraceApps: [], - bufferSizeKb: 2048, + bufferSizeKb: 20480, debugOn: false, flushThresholdKb: 4096, clock: 'boot', diff --git a/ide/src/trace/component/setting/SpWebHdcShell.ts b/ide/src/trace/component/setting/SpWebHdcShell.ts index ba79b1b1bf3eeab53b8864aa176e1b561d723908..45306711b72fd7005288a94ec8e09ac14b4b5423 100644 --- a/ide/src/trace/component/setting/SpWebHdcShell.ts +++ b/ide/src/trace/component/setting/SpWebHdcShell.ts @@ -67,11 +67,12 @@ export class SpWebHdcShell extends BaseElement { event.preventDefault(); event.stopPropagation(); }); + let listenerThis = this; this.shellCanvas!.addEventListener('keydown', async (keyboardEvent) => { keyboardEvent.preventDefault(); - if (keyboardEvent.ctrlKey && keyboardEvent.code === 'KeyC' && this.points) { - let rowText: string = this.getSelectedText(); - this.points = undefined; + if (keyboardEvent.ctrlKey && keyboardEvent.code === 'KeyC' && listenerThis.points) { + let rowText: string = listenerThis.getSelectedText(); + listenerThis.points = undefined; await navigator.clipboard.writeText(rowText); } else { if (this.sendCallBack) { @@ -87,11 +88,12 @@ export class SpWebHdcShell extends BaseElement { window.subscribe(window.SmartEvent.UI.DeviceDisConnect, () => { this.clear(); }); - this.shellCanvas!.addEventListener('blur', () => { - if (this.intervalId) { - window.clearInterval(this.intervalId); + let that = this; + this.shellCanvas!.addEventListener('blur', function () { + if (that.intervalId) { + window.clearInterval(that.intervalId); } - this.shellCanvasCtx!.clearRect(this.shellStrLength, this.textY, 12, 3); + that.shellCanvasCtx!.clearRect(that.shellStrLength, that.textY, 12, 3); }); new ResizeObserver(() => { this.resizeCanvas(); @@ -158,40 +160,24 @@ export class SpWebHdcShell extends BaseElement { getSelectedText(): string { let selectedText = ''; let textLines = [...this.finalArr]; - let startX = this.points!.startX!; - let startY = this.points!.startY!; - let endX = this.points!.endX!; - let endY = this.points!.endY!; - let depth = Math.ceil((endY - startY) / 16); - let index = 0; - for (let i = 0; i < textLines.length; i++) { - let line = textLines[i]; - let x = SpWebHdcShell.LEFT_OFFSET; - let textFirstRowY = 16 * i + SpWebHdcShell.FIRST_ROW_OFFSET; - let textLastRowY = 16 * i + SpWebHdcShell.LAST_ROW_OFFSET; - let textEndY = 16 * i + SpWebHdcShell.TOP_OFFSET; - let w = this.shellCanvasCtx!.measureText(line).width; - if ( - (startY < textEndY && endY >= textEndY) || - (startY > textFirstRowY && startY < textEndY) || - (endY > textLastRowY && endY < textEndY) - ) { - index++; - if (index === 1) { - if (depth > 1) { - selectedText += - line.slice(this.getCurrentLineBackSize(line, startX - x, true)) + (endX < x + w ? '\n' : ''); - } else { - selectedText += `${line.slice( - this.getCurrentLineBackSize(line, startX - x, true), - this.getCurrentLineBackSize(line, endX - x, false) - )}\n`; - } - } else if (index === depth) { - selectedText += `${line.slice(0, this.getCurrentLineBackSize(line, endX - x, false))}\n`; - } else { - selectedText += `${line}\n`; - } + let startX = this.points!.startX < SpWebHdcShell.LEFT_OFFSET ? SpWebHdcShell.LEFT_OFFSET : this.points!.startX; + let startY = this.points!.startY; + let endX = this.points!.endX < SpWebHdcShell.LEFT_OFFSET ? SpWebHdcShell.LEFT_OFFSET : this.points!.endX; + let endY = this.points!.endY; + let endTop = Math.ceil((endY - SpWebHdcShell.TOP_OFFSET) / 16); + let startTop = Math.floor((startY - SpWebHdcShell.TOP_OFFSET - 2) / 16); + let selectRangeList = textLines.slice(startTop + 1, endTop); + let charWidth = this.shellCanvasCtx!.measureText(selectRangeList[0].split('')[0]).width; + for (let index = 0; index < selectRangeList.length; index++) { + let currentIndexLine = selectRangeList[index]; + if (index === 0) { + let startNum = Math.floor((startX - SpWebHdcShell.LEFT_OFFSET) / charWidth); + selectedText = currentIndexLine.slice(startNum); + } else if (index === selectRangeList.length - 1) { + let endNum = Math.ceil((endX - SpWebHdcShell.LEFT_OFFSET) / charWidth); + selectedText += currentIndexLine.slice(0, endNum); + } else { + selectedText += `${currentIndexLine}\n`; } } return selectedText.trim(); @@ -239,7 +225,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}; } getCurrentLineBackSize(currentLine: string, maxBackSize: number, isStart: boolean): number { @@ -580,53 +566,55 @@ export class SpWebHdcShell extends BaseElement { let startY: number; let endX: number; let endY: number; - this.shellCanvas!.addEventListener('mousedown', (event) => { - if (this.resultStr.length === 0 && this.cursorRow.length === 0) { + let that = this; + this.shellCanvas!.addEventListener('mousedown', function (event) { + if (that.resultStr.length === 0 && that.cursorRow.length === 0) { return; } - this.isDragging = true; + that.isDragging = true; startX = event.offsetX; startY = event.offsetY; - this.refreshShellPage(false); + that.refreshShellPage(false); }); - this.shellCanvas!.addEventListener('mousemove', (event) => { - if (!this.isDragging) { + this.shellCanvas!.addEventListener('mousemove', function (event) { + if (!that.isDragging) { return; } - if (this.resultStr.length === 0 && this.cursorRow.length === 0) { + if (that.resultStr.length === 0 && that.cursorRow.length === 0) { return; } endX = event.offsetX; endY = event.offsetY; - this.refreshShellPage(false); - this.points = undefined; - this.shellCanvasCtx!.fillStyle = 'rgba(128, 128, 128, 0.5)'; + that.refreshShellPage(false); + that.points = undefined; + that.shellCanvasCtx!.fillStyle = 'rgba(128, 128, 128, 0.5)'; if (endY > startY) { - this.forwardFlag = true; - this.forwardSelected(startX, startY, endX, endY); + that.forwardFlag = true; + that.forwardSelected(startX, startY, endX, endY); } else { - this.forwardFlag = false; - this.reverseSelected(startX, startY, endX, endY); + that.forwardFlag = false; + that.reverseSelected(startX, startY, endX, endY); } }); this.shellCanvasAddMouseUpListener(); } private shellCanvasAddMouseUpListener(): void { - this.shellCanvas!.addEventListener('mouseup', async (event) => { - if (!this.isDragging) { + let that = this; + this.shellCanvas!.addEventListener('mouseup', async function (event) { + if (!that.isDragging) { return; } - if (this.resultStr.length === 0 && this.cursorRow.length === 0) { + if (that.resultStr.length === 0 && that.cursorRow.length === 0) { return; } - this.isDragging = false; + that.isDragging = false; //右键 if (event.button === 2) { let text: string = await navigator.clipboard.readText(); if (text) { - if (this.sendCallBack) { - this.sendCallBack(text); + if (that.sendCallBack) { + that.sendCallBack(text); } return; } @@ -636,8 +624,8 @@ export class SpWebHdcShell extends BaseElement { } export class Point { - startX: number | undefined; - startY: number | undefined; - endX: number | undefined; - endY: number | undefined; + startX: number = 0; + startY: number = 0; + endX: number = 0; + endY: number = 0; } diff --git a/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts b/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts index e1d5d8e2db0696bebb1e4e36abc20b1dd21dd7d7..fc7cfc8387ed30969239f7824245bcb26c19eb15 100644 --- a/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts +++ b/ide/src/trace/component/setting/bean/ProfilerServiceTypes.ts @@ -515,3 +515,13 @@ export interface ArkTSConfig { cpu_profiler_interval: number; splitOutfileName?: string; } + +export interface FFRTConfig { + pid?: number[]; + startupProcessName?: string[]; + restartProcessName?: string[]; + smbPages?: number; + flushInterval?: number; + block?: boolean; + clockId?: string; +} diff --git a/ide/src/trace/component/setting/utils/PluginConvertUtils.ts b/ide/src/trace/component/setting/utils/PluginConvertUtils.ts index af894010fc342e3fcc78eb72379583f72bf8a2ad..b13e7124450398b8be60d83c2cf8ff24420b7c44 100644 --- a/ide/src/trace/component/setting/utils/PluginConvertUtils.ts +++ b/ide/src/trace/component/setting/utils/PluginConvertUtils.ts @@ -132,13 +132,9 @@ export class PluginConvertUtils { indentation: number ): string { //@ts-ignore - if (LevelConfigEnumList.indexOf(value) >= 0 || value.startsWith('IO_REPORT')) { - prefixText = `${prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: - - ${ - //@ts-ignore - value.toString() - }${this.crlf}`; + if (configEnumList.indexOf(value) >= 0 || value.startsWith('IO_REPORT')) { + prefixText = `${prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + //@ts-ignore + this.humpToSnake(key)}: ${value.toString()}${this.crlf}`; } else { prefixText = `${prefixText + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: "${ //@ts-ignore @@ -186,9 +182,8 @@ export class PluginConvertUtils { spacesNumber: number, indentation: number, key: string, - arrValue: unknown + arrValue: any ): string { - // @ts-ignore return `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${arrValue.toString()}${ this.crlf }`; @@ -199,9 +194,8 @@ export class PluginConvertUtils { spacesNumber: number, indentation: number, key: string, - arrValue: unknown + arrValue: any ): string { - // @ts-ignore return `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${arrValue.toString()}${ this.crlf }`; @@ -212,9 +206,8 @@ export class PluginConvertUtils { spacesNumber: number, indentation: number, key: string, - arrValue: unknown + arrValue: any ): string { - // @ts-ignore return `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${arrValue.toString()}${ this.crlf }`; @@ -225,19 +218,16 @@ export class PluginConvertUtils { spacesNumber: number, indentation: number, key: string, - arrValue: unknown + arrValue: any ): string { - // @ts-ignore if (arrValue.startsWith('VMEMINFO') || arrValue.startsWith('PMEM')) { text = `${ text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) - // @ts-ignore }: ${arrValue.toString()}${this.crlf}`; } else { text = `${ text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) - // @ts-ignore - }: "${arrValue.toString()}"${this.crlf}`; + }: "${arrValue.trim().toString()}"${this.crlf}`; } return text; } @@ -247,12 +237,11 @@ export class PluginConvertUtils { spacesNumber: number, indentation: number, key: string, - arrValue: unknown, + arrValue: any, needColon: boolean ): string { if (needColon) { text = `${text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key)}: ${this.handleObj( - // @ts-ignore arrValue, indentation + 1, needColon, @@ -263,7 +252,6 @@ export class PluginConvertUtils { text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + - // @ts-ignore this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) }${this.crlf}`; } @@ -289,3 +277,8 @@ export class PluginConvertUtils { } const LevelConfigEnumList: string[] = ['LEVEL_UNSPECIFIED', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']; + +export const ffrtEnumList: string[] = ['BOOTTIME', 'REALTIME', 'REALTIME_COARSE', 'MONOTONIC', + 'MONOTONIC_COARSE', 'MONOTONIC_RAW']; + +const configEnumList: string[] = [...LevelConfigEnumList, ...ffrtEnumList]; diff --git a/ide/src/trace/component/trace/SpChartList.ts b/ide/src/trace/component/trace/SpChartList.ts index 00532418240bd3c558a13590ca7226a934c116b4..709550f4f41e8da4eb7d60ebe3118f88b1075f51 100644 --- a/ide/src/trace/component/trace/SpChartList.ts +++ b/ide/src/trace/component/trace/SpChartList.ts @@ -152,28 +152,24 @@ export class SpChartList extends BaseElement { }) this.removeCollectIcon1?.addEventListener('click', () => { - for (let i = 0; i < this.collectRowList1.length; i++) { - this.collectRowList1[i].collectEL?.click(); - i--; - } + Array.from(this.collectRowList1).forEach(row => { + row.collectEL?.click(); + }); }); this.removeCollectIcon2?.addEventListener('click', () => { - for (let i = 0; i < this.collectRowList2.length; i++) { - this.collectRowList2[i].collectEL?.click(); - i--; - } + Array.from(this.collectRowList2).forEach(row => { + row.collectEL?.click(); + }); }); } removeAllCollectRow(): void { - for (let i = 0; i < this.collectRowList1.length; i++) { - this.collectRowList1[i].collectEL?.click(); - i--; - } - for (let i = 0; i < this.collectRowList2.length; i++) { - this.collectRowList2[i].collectEL?.click(); - i--; - } + Array.from(this.collectRowList1).forEach(row => { + row.collectEL?.click(); + }); + Array.from(this.collectRowList2).forEach(row => { + row.collectEL?.click(); + }); } private resizeHeight(): void { @@ -244,12 +240,7 @@ export class SpChartList extends BaseElement { return [...this.collectRowList1, ...this.collectRowList2]; } - getCollectRowsInfo(group: string): { - type: string | null | undefined; - name: string; - id: string | null | undefined; - parents: never[]; - }[] { + getCollectRowsInfo(group: string) { return (group === SpChartList.COLLECT_G1 ? this.collectRowList1 : this.collectRowList2).map((row) => { let rowJson = { type: row.rowType, @@ -264,7 +255,7 @@ export class SpChartList extends BaseElement { } // @ts-ignore - getRowParent(obj: unknown, row: TraceRow): void { + getRowParent(obj: unknown, row: TraceRow) { if (row.parentRowEl) { // @ts-ignore if (obj.parents) { diff --git a/ide/src/trace/component/trace/TimerShaftElement.html.ts b/ide/src/trace/component/trace/TimerShaftElement.html.ts index f797266cff7af093c8aa0825aa9d5667904d7be8..1290e42f165f47a445aa5d0cd4ced35c19c8cb74 100644 --- a/ide/src/trace/component/trace/TimerShaftElement.html.ts +++ b/ide/src/trace/component/trace/TimerShaftElement.html.ts @@ -27,6 +27,12 @@ export const TimerShaftElementHtml = ` box-sizing: border-box; user-select: none; } +:host(:not([distributed])) .collect_group{ + display: flex; +} +:host([distributed]) .collect_group{ + display: none; +} .root{ width: 100%; height: 100%; diff --git a/ide/src/trace/component/trace/TimerShaftElement.ts b/ide/src/trace/component/trace/TimerShaftElement.ts index a71d06c6b76735654dad4d77fda1a8b462a62f9d..9317c60c269444173144c5494d20d8ca1f160597 100644 --- a/ide/src/trace/component/trace/TimerShaftElement.ts +++ b/ide/src/trace/component/trace/TimerShaftElement.ts @@ -28,6 +28,7 @@ import './timer-shaft/CollapseButton'; import { TimerShaftElementHtml } from './TimerShaftElement.html'; import { SpChartList } from './SpChartList'; //随机生成十六位进制颜色 +//@ts-ignore export function randomRgbColor(): string { let r = Math.floor(Math.random() * 255); let g = Math.floor(Math.random() * 255); @@ -39,7 +40,7 @@ export function randomRgbColor(): string { let color = '#' + r16 + g16 + b16; return color; } else { - return randomRgbColor(); + randomRgbColor(); } } @@ -570,11 +571,8 @@ export class TimerShaftElement extends BaseElement { this._rangeRuler?.keyUp(ev); } - drawTriangle(time: number, type: string): number { - if (this._sportRuler) { - return this._sportRuler?.drawTriangle(time, type); - } - return 0; + drawTriangle(time: number, type: string): unknown { + return this._sportRuler?.drawTriangle(time, type); } removeTriangle(type: string): void { diff --git a/ide/src/trace/component/trace/base/CommonSql.ts b/ide/src/trace/component/trace/base/CommonSql.ts index 9b9de777a64fe9872dcaac8ae8681841b22e24c0..55da31de7998401dab3404d20ba40f74d2883c36 100644 --- a/ide/src/trace/component/trace/base/CommonSql.ts +++ b/ide/src/trace/component/trace/base/CommonSql.ts @@ -200,12 +200,12 @@ const bioSql: Array = [ const frameTimeSql: Array = [ { sql: - "SELECT sf.id,'frameTime' AS frame_type,fs.ipid,fs.vsync AS name,fs.dur AS app_dur,(sf.ts + sf.dur - fs.ts) " + + "SELECT sf.id,'frameTime' AS frameType,fs.ipid,fs.vsync AS name,fs.dur AS app_dur,(sf.ts + sf.dur - fs.ts) " + 'AS dur,(fs.ts - TR.start_ts) AS ts,fs.type,fs.flag,pro.pid,pro.name AS cmdline,(sf.ts - TR.start_ts) AS rs_ts,' + 'sf.vsync AS rs_vsync,sf.dur AS rs_dur,sf.ipid AS rs_ipid,proc.pid AS rs_pid,proc.name AS rs_name FROM ' + 'frame_slice AS fs LEFT JOIN process AS pro ON pro.id = fs.ipid LEFT JOIN frame_slice AS sf ON fs.dst = sf.id ' + 'LEFT JOIN process AS proc ON proc.id = sf.ipid LEFT JOIN trace_range TR WHERE fs.dst IS NOT NULL AND fs.type ' + - "= 1 UNION SELECT -1 AS id,'frameTime' AS frame_type,fs.ipid,fs.vsync AS name,fs.dur AS app_dur,fs.dur," + + "= 1 UNION SELECT -1 AS id,'frameTime' AS frameType,fs.ipid,fs.vsync AS name,fs.dur AS app_dur,fs.dur," + '(fs.ts - TR.start_ts) AS ts,fs.type,fs.flag, pro.pid,pro.name AS cmdline,NULL AS rs_ts,NULL AS rs_vsync,' + 'NULL AS rs_dur,NULL AS rs_ipid,NULL AS rs_pid,NULL AS rs_name FROM frame_slice AS fs LEFT JOIN process AS pro' + " ON pro.id = fs.ipid LEFT JOIN trace_range TR WHERE fs.dst IS NULL AND pro.name NOT LIKE '%render_service%' " + @@ -214,13 +214,13 @@ const frameTimeSql: Array = [ }, { sql: - "SELECT sf.id,'frameTime' AS frame_type,fs.ipid,fs.vsync AS name,fs.dur AS app_dur,(sf.ts + sf.dur - fs.ts) " + + "SELECT sf.id,'frameTime' AS frameType,fs.ipid,fs.vsync AS name,fs.dur AS app_dur,(sf.ts + sf.dur - fs.ts) " + 'AS dur,(fs.ts - TR.start_ts) AS ts,fs.type,(CASE WHEN (sf.flag == 1 OR fs.flag == 1) THEN 1 WHEN (sf.flag == ' + '3 OR fs.flag == 3 ) THEN 3 ELSE 0 end) AS jank_tag,pro.pid,pro.name AS cmdline,(sf.ts - TR.start_ts) ' + 'AS rs_ts,sf.vsync AS rs_vsync,sf.dur AS rs_dur,sf.ipid AS rs_ipid,proc.pid AS rs_pid, proc.name AS rs_name ' + 'FROM frame_slice AS fs LEFT JOIN process AS pro ON pro.id = fs.ipid LEFT JOIN frame_slice AS sf ON fs.dst = ' + 'sf.id LEFT JOIN process AS proc ON proc.id = sf.ipid LEFT JOIN trace_range TR WHERE fs.dst IS NOT NULL AND ' + - "fs.type = 0 AND fs.flag <> 2 UNION SELECT -1 AS id,'frameTime' AS frame_type,fs.ipid,fs.vsync AS name," + + "fs.type = 0 AND fs.flag <> 2 UNION SELECT -1 AS id,'frameTime' AS frameType,fs.ipid,fs.vsync AS name," + 'fs.dur AS app_dur,fs.dur,(fs.ts - TR.start_ts) AS ts,fs.type,fs.flag AS jank_tag,pro.pid,pro.name AS ' + 'cmdline,NULL AS rs_ts,NULL AS rs_vsync,NULL AS rs_dur,NULL AS rs_ipid,NULL AS rs_pid,NULL AS rs_name FROM ' + 'frame_slice AS fs LEFT JOIN process AS pro ON pro.id = fs.ipid LEFT JOIN trace_range TR WHERE fs.dst IS NULL ' + diff --git a/ide/src/trace/component/trace/base/RangeSelect.ts b/ide/src/trace/component/trace/base/RangeSelect.ts index a7e2b0b023d0ca5ba00fd61fe704bdacd0573163..ddc9c6d7d1d1a9cbfccbf46baf0985850c03e53b 100644 --- a/ide/src/trace/component/trace/base/RangeSelect.ts +++ b/ide/src/trace/component/trace/base/RangeSelect.ts @@ -64,6 +64,11 @@ export class RangeSelect { mouseDown(eventDown: MouseEvent): void { this.startPageX = eventDown.pageX; this.startPageY = eventDown.pageY; + if (TraceRow.rangeSelectObject) { + this.handleTouchMark(eventDown); + } else { + this.isHover = false; + } if (this.isHover) { this.isMouseDown = true; return; @@ -150,6 +155,7 @@ export class RangeSelect { } } this.isMouseDown = false; + this.isHover = false; } // @ts-ignore checkRowsName(rowList: Array>): void { @@ -231,10 +237,9 @@ export class RangeSelect { let avgRate: string = `${(((row.frameRateList.length - 1) / cutres) * CONVERT_SECONDS).toFixed(1)}fps`; let sum: number = hitchTimeList.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // ∑hitchTimeData let hitchRate: number = - sum / ((TraceRow.rangeSelectObject!.endNS! - TraceRow.rangeSelectObject!.startNS!) / 1000000); - let perHitchRate: string = `${(Number(hitchRate) * 100).toFixed(2)}%`; + sum / ((TraceRow.rangeSelectObject!.endNS! - TraceRow.rangeSelectObject!.startNS!) / 1000000000); row.avgRateTxt = - `${avgRate} ` + ',' + ' ' + 'HitchTime:' + ` ${sum.toFixed(1)}ms` + ' ' + ',' + ` ${perHitchRate}`; + `${avgRate} ` + ',' + ' ' + 'HitchTime:' + ` ${sum.toFixed(1)}ms` + ' ' + ',' + ` ${hitchRate.toFixed(2)}ms/s`; } } } @@ -267,6 +272,7 @@ export class RangeSelect { } document.getSelection()?.removeAllRanges(); this.isMouseDown = false; + this.isHover = false; } // @ts-ignore mouseMove(rows: Array>, ev: MouseEvent): void { @@ -282,6 +288,7 @@ export class RangeSelect { return; } if (!this.isMouseDown) { + this.isHover = false; this.handleDrawForNotMouseDown(); return; } @@ -388,7 +395,6 @@ export class RangeSelect { TraceRow.rangeSelectObject = rangeSelect; return true; } - return false; }); this.timerShaftEL!.sportRuler!.isRangeSelect = (this.rangeTraceRow?.length || 0) > 0; this.timerShaftEL!.sportRuler!.draw(); diff --git a/ide/src/trace/component/trace/base/TraceRow.html.ts b/ide/src/trace/component/trace/base/TraceRow.html.ts index 4abec2c0053c8843dc876a5723199182c442f4db..5cba6b7315847ce14972786518616b113a268ab4 100644 --- a/ide/src/trace/component/trace/base/TraceRow.html.ts +++ b/ide/src/trace/component/trace/base/TraceRow.html.ts @@ -122,6 +122,7 @@ export const TraceRowHtml = ` } :host([expansion]) { background-color: var(--bark-expansion,#0C65D1); + opacity:0.8; } :host([expansion]) .name,:host([expansion]) .icon{ color: #fff; diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 43655a21b8dfd38c36bdce1092e4e245ffae4fc3..fc4f9a1cc53764cd7ca98c3321beed005308575d 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -32,6 +32,7 @@ import { TraceRowConfig } from './TraceRowConfig'; import { type TreeItemData, LitTree } from '../../../../base-ui/tree/LitTree'; import { SpSystemTrace } from '../../SpSystemTrace'; import { TraceRowHtml } from './TraceRow.html'; +import { Utils } from './Utils'; export class RangeSelectStruct { startX: number | undefined; @@ -63,7 +64,9 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_FPS = 'fps'; static ROW_TYPE_NATIVE_MEMORY = 'native-memory'; static ROW_TYPE_HIPERF = 'hiperf'; + static ROW_TYPE_HIPERF_THREADTYPE: Array = [-2]; static ROW_TYPE_DELIVER_INPUT_EVENT = 'DeliverInputEvent'; + static ROW_TYPE_TOUCH_EVENT_DISPATCH = 'TouchEventDispatch'; static ROW_TYPE_HIPERF_CPU = 'hiperf-cpu'; static ROW_TYPE_PERF_CALLCHART = 'hiperf-callchart'; static ROW_TYPE_HIPERF_PROCESS = 'hiperf-process'; @@ -90,6 +93,7 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_DISK_ABILITY = 'disk-ability'; static ROW_TYPE_NETWORK_ABILITY = 'network-ability'; static ROW_TYPE_DMA_ABILITY = 'dma-ability'; + static ROW_TYPE_DMA_FENCE = 'dma-fence'; static ROW_TYPE_GPU_MEMORY_ABILITY = 'gpu-memory-ability'; static ROW_TYPE_SDK = 'sdk'; static ROW_TYPE_SDK_COUNTER = 'sdk-counter'; @@ -130,6 +134,8 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_ALL_APPSTARTUPS = 'all-appstartups'; static ROW_TYPE_PERF_TOOL_GROUP = 'perf-tool-group'; static ROW_TYPE_PERF_TOOL = 'perf-tool'; + static ROW_TYPE_GPU_COUNTER_GROUP = 'gpu-counter-group'; + static ROW_TYPE_GPU_COUNTER = 'gpu-counter'; static FRAME_WIDTH: number = 0; static range: TimeRange | undefined | null; static rangeSelectObject: RangeSelectStruct | undefined; @@ -182,9 +188,9 @@ export class TraceRow extends HTMLElement { private _enableCollapseChart: boolean = false; online: boolean = false; static isUserInteraction: boolean; - asyncFuncName: string | undefined | null; + asyncFuncName: string | Array | undefined | null; asyncFuncNamePID: number | undefined | null; - asyncFuncThreadName: Array | string | undefined | null; + asyncFuncThreadName: Array| string | undefined | null; translateY: number = 0; //single canvas offsetY; // @ts-ignore childrenList: Array> = []; // @ts-ignore @@ -220,22 +226,29 @@ export class TraceRow extends HTMLElement { contextId: '2d', isOffScreen: true, skeleton: false, - } + }, + traceId?: string ) { super(); this.args = args; this.attachShadow({ mode: 'open' }).innerHTML = this.initHtml(); + if (traceId) { + this.traceId = traceId; + } this.initElements(); } - static skeleton(): TraceRow { - let tr = new TraceRow({ - alpha: false, - canvasNumber: 0, - contextId: '', - isOffScreen: false, - skeleton: true, - }); + static skeleton(traceId?: string): TraceRow { + let tr = new TraceRow( + { + alpha: false, + canvasNumber: 0, + contextId: '', + isOffScreen: false, + skeleton: true, + }, + traceId + ); tr.isTransferCanvas = true; return tr; } @@ -389,7 +402,7 @@ export class TraceRow extends HTMLElement { } set rangeSelect(value: boolean) { - this._rangeSelect = value; + this._rangeSelect = value && this.traceId === Utils.currentSelectTrace; } sleeping: boolean = false; @@ -402,12 +415,21 @@ export class TraceRow extends HTMLElement { this.setAttribute('row-type', val || ''); } + get traceId(): string | undefined | null { + return this.getAttribute('trace-id'); + } + + set traceId(val) { + this.setAttribute('trace-id', val || ''); + } + get rowId(): string | undefined | null { return this.getAttribute('row-id'); } set rowId(val) { - this.setAttribute('row-id', val || ''); + let id = this.traceId ? `${val || ''}-${this.traceId}` : `${val || ''}`; + this.setAttribute('row-id', id); } get rowParentId(): string | undefined | null { @@ -482,6 +504,7 @@ export class TraceRow extends HTMLElement { if (value) { this.updateChildRowStatus(); } else { + this.sticky = false; this.childRowToFragment(false); } if (value) { @@ -559,8 +582,11 @@ export class TraceRow extends HTMLElement { } }; - //@ts-ignore - getHoverStruct(strict: boolean = true, offset: boolean = false, maxKey?: string): T | undefined { + getHoverStruct( + strict: boolean = true, + offset: boolean = false, + maxKey: string | undefined = undefined + ): T | undefined { if (this.isHover) { if (maxKey) { let arr = this.dataListCache @@ -574,6 +600,7 @@ export class TraceRow extends HTMLElement { } } } + // @ts-ignore addChildTraceRow(child: TraceRow): void { // @ts-ignore @@ -585,6 +612,7 @@ export class TraceRow extends HTMLElement { child.rowHidden = false; this.fragment.appendChild(child); } + // @ts-ignore addChildTraceRowAfter(child: TraceRow, targetRow: TraceRow): void { // @ts-ignore @@ -620,15 +648,14 @@ export class TraceRow extends HTMLElement { } } - addRowSampleUpload(): void { + addRowSampleUpload(type: string = 'application/json'): void { this.sampleUploadEl = document.createElement('div'); this.sampleUploadEl!.className = 'upload'; this.sampleUploadEl!.innerHTML = ` - - - `; + + `; this.jsonFileEl = this.sampleUploadEl!.querySelector('.file') as HTMLInputElement; this.sampleUploadEl!.addEventListener('change', () => { let files = this.jsonFileEl!.files; @@ -693,6 +720,7 @@ export class TraceRow extends HTMLElement { 'VSync-app', 'render_service', 'RSUniRenderThre', + 'Release Fence', 'Acquire Fence', 'RSHardwareThrea', 'Present Fence', @@ -761,6 +789,9 @@ export class TraceRow extends HTMLElement { if (this.folder) { this.childrenList.forEach((it) => (it.checkType = value)); } + if (this.refreshCheckType()) { + return; + } this.setAttribute('check-type', value); if (this.hasAttribute('disabled-check')) { this.checkBoxEL!.style.display = 'none'; @@ -913,10 +944,11 @@ export class TraceRow extends HTMLElement { event.stopPropagation(); }); - window.addEventListener('storage', (e): void => { + let that = this; + window.addEventListener('storage', function (e): void { if (e.storageArea === sessionStorage) { if (e.key === 'freqInfoData') { - this.onRowCheckFileChangeHandler?.(); + that.onRowCheckFileChangeHandler?.(); } } }); // @ts-ignore @@ -945,8 +977,13 @@ export class TraceRow extends HTMLElement { } addRowSettingPop(): void { + let nameEl = this.shadowRoot?.querySelector('.name') as HTMLLabelElement; + nameEl.style.maxWidth = '160px'; + let collectEl = this.shadowRoot?.querySelector('.collect') as LitIcon; + collectEl.style.marginRight = '20px'; this.rowSettingPop = document.createElement('lit-popover') as LitPopover; - this.rowSettingPop.innerHTML = `
+ this.rowSettingPop.innerHTML = `
`; @@ -957,6 +994,7 @@ export class TraceRow extends HTMLElement { this.rowSettingPop.setAttribute('haveRadio', 'true'); this.rowSettingTree = this.rowSettingPop.querySelector('#rowSettingTree') as LitTree; this.rowSettingTree.onChange = (): void => { + TraceRow.ROW_TYPE_HIPERF_THREADTYPE = []; let isVisible = false; // @ts-ignore this.rowSettingPop!.visible = isVisible; @@ -964,7 +1002,8 @@ export class TraceRow extends HTMLElement { isVisible = true; } // @ts-ignore - this.rowSettingPop!.visible = isVisible; //@ts-ignore + this.rowSettingPop!.visible = isVisible; + TraceRow.ROW_TYPE_HIPERF_THREADTYPE.push(Number(this.rowSettingTree!.getCheckdKeys())) //@ts-ignore this.onRowSettingChangeHandler?.(this.rowSettingTree!.getCheckdKeys(), this.rowSettingTree!.getCheckdNodes()); }; this.rowSettingPop?.addEventListener('mouseenter', (): void => { @@ -981,26 +1020,30 @@ export class TraceRow extends HTMLElement { return []; } - expandFunc(): void { + //@ts-ignore + expandFunc(rootRow: TraceRow, sp: SpSystemTrace): void { if (this._enableCollapseChart && !this.funcExpand) { + let foldHeight = Number(this.style.height.substring(0, this.style.height.length - 2)); this.style.height = `${this.funcMaxHeight}px`; this.funcExpand = true; + rootRow.needRefresh = true; + sp.refreshCanvas(true); if (this.collect) { window.publish(window.SmartEvent.UI.RowHeightChange, { expand: this.funcExpand, - value: this.funcMaxHeight - 20, + value: this.funcMaxHeight - foldHeight, }); } } } - enableCollapseChart(): void { + enableCollapseChart(H: number, trace: unknown): void { this._enableCollapseChart = true; this.nameEL!.onclick = (): void => { - if (this.funcMaxHeight > 20 || this.clientHeight > 20) { + if (this.funcMaxHeight > H || this.clientHeight > H) { if (this.funcExpand) { this.funcMaxHeight = this.clientHeight; - this.style.height = '20px'; + this.style.height = H + 'px'; this.funcExpand = false; } else { this.style.height = `${this.funcMaxHeight}px`; @@ -1008,11 +1051,12 @@ export class TraceRow extends HTMLElement { } TraceRow.range!.refresh = true; this.needRefresh = true; - this.draw(false); + //@ts-ignore + trace.refreshCanvas(true); if (this.collect) { window.publish(window.SmartEvent.UI.RowHeightChange, { expand: this.funcExpand, - value: this.funcMaxHeight - 20, + value: this.funcMaxHeight - H, }); } } @@ -1276,11 +1320,22 @@ export class TraceRow extends HTMLElement { } } + refreshCheckType(): boolean { + if (!this.rangeSelect && this.traceId !== Utils.currentSelectTrace) { + this.checkBoxEL!.style.display = 'none'; + this.rangeSelect = false; + this.removeAttribute('check-type'); + return true; + } + return false; + } + draw(useCache: boolean = false): void { this.dpr = window.devicePixelRatio || 1; if (this.sleeping) { return; } + this.refreshCheckType(); if (this.supplierFrame) { //如果设置了实时渲染,则调用drawFrame this.drawFrame(); @@ -1472,14 +1527,22 @@ export class TraceRow extends HTMLElement { } } - focusContain(e: MouseEvent, inFavoriteArea: boolean): boolean { + focusContain(e: MouseEvent, inFavoriteArea: boolean, prevScrollY: number = 0,favoriteHeight: number): boolean { let _y = (e.currentTarget as HTMLElement).getBoundingClientRect().y; let myRect = this.getBoundingClientRect(); let x = e.offsetX; let y = e.offsetY + _y; - if (x >= myRect.x && x <= myRect.x + myRect.width && y >= myRect.y && y <= myRect.y + myRect.height) { + let rectY = myRect.y; + let rectHeight = myRect.height; + if (!inFavoriteArea && favoriteHeight !== undefined) { + y = e.offsetY + prevScrollY - 90 - favoriteHeight!; + rectY = this.offsetTop; + rectHeight = this.clientHeight; + } + if (x >= myRect.x && x <= myRect.x + myRect.width && y >= rectY && + y <= rectY + rectHeight) { this.hoverX = x - this.describeEl!.clientWidth; - this.hoverY = y - myRect.y; + this.hoverY = y - rectY; this.isHover = this.collect === inFavoriteArea; return true; } else { diff --git a/ide/src/trace/component/trace/base/TraceRowConfig.ts b/ide/src/trace/component/trace/base/TraceRowConfig.ts index 5cbc1dd4246409c2bd75f08e26dbf385dbc1cc07..5951ed1dc5147e456503860d5c5f3557ac5f96df 100644 --- a/ide/src/trace/component/trace/base/TraceRowConfig.ts +++ b/ide/src/trace/component/trace/base/TraceRowConfig.ts @@ -83,7 +83,7 @@ export class TraceRowConfig extends BaseElement { TraceRowConfig.allTraceRowList.push(...this.traceRowList!); this.refreshAllConfig(true, true); // 鼠标移入该页面,隐藏泳道图tip - this.onmouseenter = (): void => { + this.onmouseenter = () => { this.spSystemTrace!.tipEL!.style.display = 'none'; this.spSystemTrace!.hoverStructNull(); this.spSystemTrace!.refreshCanvas(true); @@ -176,6 +176,8 @@ export class TraceRowConfig extends BaseElement { this.spSystemTrace?.removeLinkLinesByBusinessType('janks'); } else if (type === 'Task Pool') { this.spSystemTrace?.removeLinkLinesByBusinessType('task'); + } else if (type === 'func') { + this.spSystemTrace?.removeLinkLinesByBusinessType('distributed'); } } @@ -211,7 +213,7 @@ export class TraceRowConfig extends BaseElement { chartRow.rowHidden = false; chartRow.setAttribute('scene', ''); } else { - row.expansion = true; + row.expansion = false; chartRow.removeAttribute('scene'); chartRow.rowHidden = true; } @@ -567,8 +569,7 @@ export class TraceRowConfig extends BaseElement { for (let subIndex = 0; subIndex < subsystemsData.length; subIndex++) { let currentSystemData = subsystemsData[subIndex]; if ( - !('subsystem' in currentSystemData) || - currentSystemData.subsystem === '' || + !currentSystemData.subsystem || currentSystemData.subsystem === '' || subsystemList.indexOf(currentSystemData.subsystem) > -1 || Array.isArray(currentSystemData.subsystem) ) { @@ -592,7 +593,7 @@ export class TraceRowConfig extends BaseElement { } for (let compIndex = 0; compIndex < currentCompDates.length; compIndex++) { let currentCompDate = currentCompDates[compIndex]; - if (!('component' in currentCompDate) || currentCompDate.component === '' || !('charts' in currentCompDate)) { + if ( !currentCompDate.component || currentCompDate.component === '' || !currentCompDate.charts) { continue; } id = this.setSubsystemComp(currentCompDate, id, subsystemStruct); @@ -633,8 +634,8 @@ export class TraceRowConfig extends BaseElement { for (let chartIndex = 0; chartIndex < currentChartDates.length; chartIndex++) { let currentChartDate = currentChartDates[chartIndex]; if ( - (!('chartName' in currentChartDate) && !('chartId' in currentChartDate)) || - Object.keys(currentChartDate).includes('chartName') + (!currentChartDate.chartName && !currentChartDate.chartId) || + Array.isArray(currentChartDate.chartName) ) { continue; } @@ -674,7 +675,7 @@ export class TraceRowConfig extends BaseElement { currentChartId: string, scene: Array, findChartNames: Array - ): void { + ) { if (this.traceRowList) { for (let index = 0; index < this.traceRowList.length; index++) { let item = this.traceRowList[index]; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index 27459b0424f3574fb0864b3b87dece70116fd527..11fa0102de7489449502204ec0be0bc0e07bf442 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -32,6 +32,7 @@ import { type FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem'; import { CpuStateStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuState'; import { type ClockStruct } from '../../../database/ui-worker/ProcedureWorkerClock'; +import { type DmaFenceStruct } from '../../../database/ui-worker/ProcedureWorkerDmaFence'; import { type IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq'; import { type JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank'; import { type HeapStruct } from '../../../database/ui-worker/ProcedureWorkerHeap'; @@ -83,12 +84,14 @@ import '../../../../base-ui/popover/LitPopoverV'; import { LitPopover } from '../../../../base-ui/popover/LitPopoverV'; import { LitTree, TreeItemData } from '../../../../base-ui/tree/LitTree'; import { SampleStruct } from '../../../database/ui-worker/ProcedureWorkerBpftrace'; -import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction'; import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin'; +import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction'; import { TabPaneFreqStatesDataCut } from '../sheet/states/TabPaneFreqStatesDataCut'; import { TabPaneDataCut } from '../sheet/TabPaneDataCut'; import { SpSystemTrace } from '../../SpSystemTrace'; import { PerfToolStruct } from '../../../database/ui-worker/ProcedureWorkerPerfTool'; +import { GpuCounterStruct } from '../../../database/ui-worker/ProcedureWorkerGpuCounter'; +import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter'; @element('trace-sheet') export class TraceSheet extends BaseElement { @@ -209,7 +212,7 @@ export class TraceSheet extends BaseElement { }); this.getComponentByID('box-io-tier-statistics-analysis')?.addEventListener('row-click', (evt: MouseEvent) => { // @ts-ignore - if (evt.detail.button === 2) { + if (evt.detail.button === 2 && evt.detail.tableName) { let pane = this.getPaneByID('box-io-calltree'); this.litTabs!.activeByKey(pane.key); } @@ -218,7 +221,7 @@ export class TraceSheet extends BaseElement { 'row-click', (evt: MouseEvent) => { // @ts-ignore - if (evt.detail.button === 2) { + if (evt.detail.button === 2 && evt.detail.tableName) { let pane = this.getPaneByID('box-vm-calltree'); this.litTabs!.activeByKey(pane.key); } @@ -228,7 +231,7 @@ export class TraceSheet extends BaseElement { 'row-click', (evt: MouseEvent) => { // @ts-ignore - if (evt.detail.button === 2) { + if (evt.detail.button === 2 && evt.detail.tableName) { let pane = this.getPaneByID('box-file-system-calltree'); this.litTabs!.activeByKey(pane.key); } @@ -250,7 +253,7 @@ export class TraceSheet extends BaseElement { private perfAnalysisListener(evt: MouseEvent): void { // @ts-ignore - if (evt.detail.button === 2) { + if (evt.detail.button === 2 && evt.detail.pid) { let pane = this.getPaneByID('box-perf-profile'); this.litTabs!.activeByKey(pane.key); } @@ -258,7 +261,7 @@ export class TraceSheet extends BaseElement { private nativeAnalysisListener(e: MouseEvent): void { //@ts-ignore - if (e.detail.button === 2) { + if (e.detail.button === 2 && e.detail.tableName) { let pane = this.getPaneByID('box-native-calltree'); pane.hidden = false; this.litTabs!.activeByKey(pane.key); @@ -622,6 +625,7 @@ export class TraceSheet extends BaseElement { data: ThreadStruct, scrollCallback: ((e: ThreadStruct) => void) | undefined, scrollWakeUp: (d: unknown) => void | undefined, + scrollPrio: (d: any) => void | undefined, callback?: (data: Array, str: string) => void ): Promise => this.displayTab('current-selection').setThreadData( @@ -629,12 +633,15 @@ export class TraceSheet extends BaseElement { // @ts-ignore scrollCallback, scrollWakeUp, + scrollPrio, callback ); displayMemData = (data: ProcessMemStruct): void => this.displayTab('current-selection').setMemData(data); displayClockData = (data: ClockStruct): Promise => this.displayTab('current-selection').setClockData(data); + displayDmaFenceData = (data: DmaFenceStruct, rowData: any): void =>//展示tab页内容 + this.displayTab('current-selection').setDmaFenceData(data, rowData); displayPerfToolsData = (data: PerfToolStruct): void => this.displayTab('current-selection').setPerfToolsData(data); displayIrqData = (data: IrqStruct): void => @@ -651,8 +658,8 @@ export class TraceSheet extends BaseElement { val.nativeMemoryStatistic.push(rowType); val.nativeMemoryCurrentIPid = ipid; val.nativeMemory = []; - val.leftNs = data.startTime!; - val.rightNs = data.dur === 0 ? data.startTime! : data.startTime! + data.dur! - 1; + val.leftNs = data.startTime! + data.dur!; + val.rightNs = data.startTime! + data.dur! + 1; this.selection = val; this.displayTab('box-native-statistic-analysis', 'box-native-calltree').data = val; this.showUploadSoBt(val); @@ -669,8 +676,15 @@ export class TraceSheet extends BaseElement { this.displayTab('gpu-click-select', 'gpu-click-select-comparison').gpuClickData(dataObject); }; - displayFuncData = (names: string[], data: FuncStruct, scrollCallback: Function): Promise => - this.displayTab(...names).setFunctionData(data, scrollCallback); + displayFuncData = ( + names: string[], + threadName: string, + data: FuncStruct, + scrollCallback: Function, + callback?: (data: Array, str: string, binderTid: number) => void, + distributedCallback?: (dataList: FuncStruct[]) => void, + ): Promise => + this.displayTab(...names).setFunctionData(data, threadName, scrollCallback, callback, distributedCallback); displayCpuData = ( data: CpuStruct, callback: ((data: WakeupBean | null) => void) | undefined = undefined, @@ -860,12 +874,15 @@ export class TraceSheet extends BaseElement { { key: '1', title: 'cycles', checked: select[0] === '1' }, ]; }; - - displayUserPlugin = (selectData: any): void => { this.displayTab("tab-pane-userplugin").data = selectData; }; + + displayGpuCounterData = (data: GpuCounterStruct): void => { + this.displayTab('box-gpu-counter').data = data; + }; + displaySystemStatesData = (): void => { let dataCutPane = this.shadowRoot?.querySelector('tabpane-datacut'); if (dataCutPane) { @@ -969,7 +986,8 @@ export class TraceSheet extends BaseElement { selection.fileSysVirtualMemory || selection.vmCount > 0 || selection.diskIOLatency || - selection.diskIOipids.length > 0) + selection.diskIOipids.length > 0 || + selection.threadIds.length > 0) ) { this.importDiv!.style.display = 'flex'; } else { @@ -1063,6 +1081,7 @@ export class TraceSheet extends BaseElement { this.litTabs!.activeByKey(pane.key); // @ts-ignore pane.tab = Utils.transferPTSTitle(e.detail.title); let param = new BoxJumpParam(); + param.traceId = this.selection!.traceId; param.leftNs = this.selection!.leftNs; param.rightNs = this.selection!.rightNs; param.cpus = this.selection!.cpus; // @ts-ignore diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index 4e14c5eb4203355a0e131eda22a0e98a0966bf24..16bbc9f245818e75cb6ab6a68ab8abaeaf49a49e 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -128,7 +128,13 @@ import { TabPaneSampleInstructionDistributions } from '../sheet/bpftrace/TabPane import { TabPaneSampleInstructionTotalTime } from '../sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime'; import { TabPaneSampleInstructionSelection } from '../sheet/bpftrace/TabPaneSampleInstructionSelection'; import { TabPaneDataCut } from '../sheet/TabPaneDataCut'; +import { TabPaneGpuCounterSelection } from '../sheet/gpu-counter/TabPaneGpuCounterSelection'; +import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter'; +import { TabPaneTimeParallel } from '../sheet/parallel/TabPaneTimeParallel'; +import { TabPaneMtParallel } from '../sheet/parallel/TabPaneMtParallel'; +import { TabPanePerfAsync } from '../sheet/hiperf/TabPerfAsyncList'; import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin'; +import { TabPaneDmaFence } from '../sheet/dma-fence/TabPaneDmaFenceSelect'; export let tabConfig: unknown = { 'current-selection': { @@ -200,7 +206,7 @@ export let tabConfig: unknown = { 'box-slices': { title: 'Slices', type: TabPaneSlices, - require: (param: SelectionParam) => param.funTids.length > 0 || param.funAsync.length || param.funCatAsync.length > 0, + require: (param: SelectionParam) => param.funTids.length > 0 || param.funAsync.length > 0 || param.funCatAsync.length > 0, }, 'box-counters': { title: 'Counters', @@ -251,26 +257,6 @@ export let tabConfig: unknown = { type: TabPaneNMSampleList, require: (param: SelectionParam) => param.nativeMemory.length > 0, }, - 'box-perf-analysis': { - title: 'Analysis', - type: TabPanePerfAnalysis, - require: (param: SelectionParam) => param.perfSampleIds.length > 0, - }, - 'box-perf-bottom-up': { - title: 'Bottom Up', - type: TabpanePerfBottomUp, - require: (param: SelectionParam) => param.perfSampleIds.length > 0, - }, - 'box-perf-profile': { - title: 'Perf Profile', - type: TabpanePerfProfile, - require: (param: SelectionParam) => param.perfSampleIds.length > 0, - }, - 'box-perf-sample': { - title: 'Sample List', - type: TabPanePerfSample, - require: (param: SelectionParam) => param.perfSampleIds.length > 0, - }, 'box-live-processes-child': { title: 'Live Processes', @@ -660,15 +646,13 @@ export let tabConfig: unknown = { 'tabpane-gpufreq': { title: 'Gpufreq Usage', type: TabPaneGpufreq, - require: (param: SelectionParam) => - param.clockMapData.size === 1 && param.clockMapData.has('gpufreq Frequency') === true, + require: (param: SelectionParam) => param.clockMapData.size === 1 && param.clockMapData.has('gpufreq Frequency') === true, }, 'tabpane-datacut': { title: 'Data Cut', type: TabPaneDataCut, - require: (param: SelectionParam) => - param.threadIds.length > 0 || - (param.clockMapData.size === 1 && param.clockMapData.has('gpufreq Frequency') === true), + require: (param: SelectionParam) => param.threadIds.length > 0 || + (param.clockMapData.size > 0 && param.clockMapData.has('gpufreq Frequency') === true), }, 'box-sample-instruction-selection': { title: 'Data Selection', @@ -689,8 +673,57 @@ export let tabConfig: unknown = { title: 'Data Flow', type: TabPaneSampleInstruction, }, + 'box-gpu-counter-selection': { + title: 'Gpu Counter', + type: TabPaneGpuCounterSelection, + require: (param: SelectionParam) => param.gpuCounter.length > 0, + }, + 'box-gpu-counter': { + title: 'Gpu Counter', + type: TabPaneGpuCounter, + }, + 'tabpane-time-parallel': { + title: 'Time Parallel', + type: TabPaneTimeParallel, + require: (param: SelectionParam) => param.threadIds.length > 0, + }, + 'tabpane-mt-parallel': { + title: 'MT Parallel', + type: TabPaneMtParallel, + require: (param: SelectionParam) => param.threadIds.length > 0, + }, + 'box-perf-analysis': { + title: 'Analysis', + type: TabPanePerfAnalysis, + require: (param: SelectionParam) => param.perfSampleIds.length > 0, + }, + 'box-perf-bottom-up': { + title: 'Bottom Up', + type: TabpanePerfBottomUp, + require: (param: SelectionParam) => param.perfSampleIds.length > 0, + }, + 'box-perf-profile': { + title: 'Perf Profile', + type: TabpanePerfProfile, + require: (param: SelectionParam) => param.perfSampleIds.length > 0 || param.threadIds.length > 0, + }, + 'box-perf-sample': { + title: 'Sample List', + type: TabPanePerfSample, + require: (param: SelectionParam) => param.perfSampleIds.length > 0, + }, + 'box-perf-async': { + title: 'Async Call Profile', + type: TabPanePerfAsync, + require: (param: SelectionParam) => param.perfSampleIds.length > 0, + }, 'tab-pane-userplugin': { title: 'User Plugin', type: TabPaneUserPlugin, }, + 'tabpane-dmafrence': { + title: 'Dma Frence', + type: TabPaneDmaFence, + require: (param: SelectionParam) => param.dmaFenceNameData.length > 0, + }, }; diff --git a/ide/src/trace/component/trace/base/Utils.ts b/ide/src/trace/component/trace/base/Utils.ts index ac8e50d6a8bddebcce51b28ee4872520550d2986..a3ba25b8e5c60f870a7d69e186db627cf14bb084 100644 --- a/ide/src/trace/component/trace/base/Utils.ts +++ b/ide/src/trace/component/trace/base/Utils.ts @@ -16,14 +16,60 @@ import { SelectionParam } from '../../../bean/BoxSelection'; import { procedurePool } from '../../../database/Procedure'; import { queryNativeHookResponseTypes } from '../../../database/sql/NativeHook.sql'; +import { TraceMode } from '../../../SpApplicationPublicFunc'; export class Utils { static isTransformed: boolean = false; + static currentSelectTrace: string | null | undefined; + static currentTraceMode: TraceMode = TraceMode.NORMAL; + static distributedTrace: string[] = []; + static DMAFENCECAT_MAP: Map< + number, + { + id: number; + cat: string; + seqno: number; + driver: string; + context: string + }> = new Map< + number, + { + id: number; + cat: string; + seqno: number; + driver: string; + context: string + } + >(); private static statusMap: Map = new Map(); private static instance: Utils | null = null; - static THREAD_MAP: Map = new Map(); - static PROCESS_MAP: Map = new Map(); - static SCHED_SLICE_MAP: Map< + private trace1CpuCount: number = 1; + private trace1WinCpuCount: number = 1; + private trace2CpuCount: number = 1; + private trace2WinCpuCount: number = 1; + trace1RecordStartNS: number = 1; + trace2RecordStartNS: number = 1; + trace1RecordEndNS: number = 1; + trace2RecordEndNS: number = 1; + totalNS: number = 1; + private trace1ThreadMap: Map = new Map(); + private trace1ProcessMap: Map = new Map(); + private trace1SchedSliceMap: Map< + string, + { + endState: string; + priority: number; + } + > = new Map< + string, + { + endState: string; + priority: number; + } + >(); + private trace2ThreadMap: Map = new Map(); + private trace2ProcessMap: Map = new Map(); + private trace2SchedSliceMap: Map< string, { endState: string; @@ -36,6 +82,7 @@ export class Utils { priority: number; } >(); + private callStackMap: Map = new Map(); constructor() { Utils.statusMap.set('D', 'Uninterruptible Sleep'); @@ -58,6 +105,109 @@ export class Utils { Utils.statusMap.set('N', 'No Load'); } + public getProcessMap(traceId?: string | null): Map { + if (traceId) { + return (traceId === '2' ? this.trace2ProcessMap : this.trace1ProcessMap); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2ProcessMap : this.trace1ProcessMap); + } + } + + public getThreadMap(traceId?: string | null): Map { + if (traceId) { + return (traceId === '2' ? this.trace2ThreadMap : this.trace1ThreadMap); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2ThreadMap : this.trace1ThreadMap); + } + } + + public getCallStatckMap(): Map { + return this.callStackMap; + } + + public getSchedSliceMap(traceId?: string | null): Map { + if (traceId) { + return (traceId === '2' ? this.trace2SchedSliceMap : this.trace1SchedSliceMap); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2SchedSliceMap : this.trace1SchedSliceMap); + } + } + + public getCpuCount(traceId?: string | null): number { + if (traceId) { + return (traceId === '2' ? this.trace2CpuCount : this.trace1CpuCount); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2CpuCount : this.trace1CpuCount); + } + } + + public setCpuCount(count: number, traceId?: string | null): void { + if (traceId) { + if (traceId === '2') { + this.trace2CpuCount = count; + } else { + this.trace1CpuCount = count; + } + } else { + if (Utils.currentSelectTrace === '2') { + this.trace2CpuCount = count; + } else { + this.trace1CpuCount = count; + } + } + } + + public getWinCpuCount(traceId?: string | null): number { + if (traceId) { + return (traceId === '2' ? this.trace2WinCpuCount : this.trace1WinCpuCount); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2WinCpuCount : this.trace1WinCpuCount); + } + } + + public setWinCpuCount(count: number, traceId?: string | null): void { + if (traceId) { + if (traceId === '2') { + this.trace2WinCpuCount = count; + } else { + this.trace1WinCpuCount = count; + } + } else { + if (Utils.currentSelectTrace === '2') { + this.trace2WinCpuCount = count; + } else { + this.trace1WinCpuCount = count; + } + } + } + + public getRecordStartNS(traceId?: string | null): number { + if (traceId) { + return (traceId === '2' ? this.trace2RecordStartNS : this.trace1RecordStartNS); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2RecordStartNS : this.trace1RecordStartNS); + } + } + + public getRecordEndNS(traceId?: string | null): number { + if (traceId) { + return (traceId === '2' ? this.trace2RecordEndNS : this.trace1RecordEndNS); + } else { + return (Utils.currentSelectTrace === '2' ? this.trace2RecordEndNS : this.trace1RecordEndNS); + } + } + + public getTotalNS(traceId?: string | null): number { + return this.totalNS; + } + + public static isDistributedMode(): boolean { + return Utils.currentTraceMode === TraceMode.DISTRIBUTED; + } + public static getInstance(): Utils { if (Utils.instance === null) { Utils.instance = new Utils(); @@ -65,10 +215,27 @@ export class Utils { return Utils.instance; } + public clearCache(): void { + this.trace1ProcessMap.clear(); + this.trace2ProcessMap.clear(); + this.trace1ThreadMap.clear(); + this.trace2ThreadMap.clear(); + this.trace1SchedSliceMap.clear(); + this.trace2SchedSliceMap.clear(); + Utils.distributedTrace = []; + } + public static clearData(): void { - Utils.THREAD_MAP.clear(); - Utils.PROCESS_MAP.clear(); - Utils.SCHED_SLICE_MAP.clear(); + Utils.getInstance().clearCache(); + Utils.DMAFENCECAT_MAP.clear(); + } + + public static getDistributedRowId(id: unknown): string { + let rowId = id; + if (rowId === null || rowId === undefined) { + rowId = ''; + } + return this.currentSelectTrace ? `${rowId}-${this.currentSelectTrace}` : `${rowId}`; } public static getEndState(state: string): string { @@ -100,30 +267,30 @@ export class Utils { return Utils.getEndState(ptsValue.replace('S-', '')); // @ts-ignore } else if (ptsValue.startsWith('P-')) { // @ts-ignore - let pid = ptsValue.replace('P-', ''); // @ts-ignore - let process = Utils.PROCESS_MAP.get(parseInt(pid)) || 'Process'; + let pid = ptsValue.replace('P-', ''); + let process = Utils.getInstance().getProcessMap(Utils.currentSelectTrace).get(parseInt(pid)) || 'Process'; return `${process} [${pid}]`; // @ts-ignore } else if (ptsValue.startsWith('T-')) { // @ts-ignore let tid = ptsValue.replace('T-', ''); - let thread = Utils.THREAD_MAP.get(parseInt(tid)) || 'Thread'; + let thread = Utils.getInstance().getThreadMap(Utils.currentSelectTrace).get(parseInt(tid)) || 'Thread'; return `${thread} [${tid}]`; } else { return ''; } } - public static transferBinderTitle(value: unknown): string { + public static transferBinderTitle(value: unknown, traceId?: string | null): string { // @ts-ignore if (value.startsWith('P-')) { // @ts-ignore let pid = value.replace('P-', ''); - let process = Utils.PROCESS_MAP.get(parseInt(pid)) || 'Process'; + let process = Utils.getInstance().getProcessMap(traceId).get(parseInt(pid)) || 'Process'; return `${process} [${pid}]`; // @ts-ignore } else if (value.startsWith('T-')) { // @ts-ignore let tid = value.replace('T-', ''); - let thread = Utils.THREAD_MAP.get(parseInt(tid)) || 'Thread'; + let thread = Utils.getInstance().getThreadMap(traceId).get(parseInt(tid)) || 'Thread'; return `${thread} [${tid}]`; } else { return ''; @@ -470,6 +637,29 @@ export class Utils { }, []); } + // 线程排序去重 + public static sortThreadRow(array1: unknown[], array2: unknown[], flag: string): unknown { + let total = new Array(); + let arr2Map = new Map(); + // 将array2转为map + for (let i = 0; i < array2.length; i++) { + // @ts-ignore + arr2Map.set(flag === 'thread' ? `${array2[i].pid}-${array2[i].tid}` : `${array2[i].pid}`, array2[i]) + } + for (let i = 0; i < array1.length; i++) { + // @ts-ignore + total.push(arr2Map.get(`${array1[i][0]}`)) + // @ts-ignore + arr2Map.delete(`${array1[i][0]}`) + }; + // 将map中剩余的循环加在total后 + // @ts-ignore + arr2Map.forEach((v) => { + total.push(v) + }) + return total + } + static getFrequencyWithUnit = ( maxFreq: number ): { @@ -485,10 +675,11 @@ export class Utils { if (maxFreq > 0) { let log10: number = Math.ceil(Math.log10(maxFreq)); let pow10: number = Math.pow(10, log10); - let afterCeil: number = Math.ceil(maxFreq / (pow10 / 4)) * (pow10 / 4); - maxFreqObj.maxFreq = afterCeil; + let afterCeil: number = Math.ceil(maxFreq / (pow10 / 4)) * 1000; + let afterDivision:number = (afterCeil * ((pow10 / 4) * 1000)) / 1000000; + maxFreqObj.maxFreq = afterDivision; let unitIndex: number = Math.floor(log10 / 3); - sb = `${afterCeil / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}`; + sb = `${afterDivision / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}`; } maxFreqObj.maxFreqName = sb.toString(); return maxFreqObj; @@ -525,11 +716,50 @@ export class Utils { } } queryNativeHookResponseTypes(val.leftNs, val.rightNs, types, isStatistic).then((res): void => { - procedurePool.submitWithName('logic0', 'native-memory-init-responseType', res, undefined, (): void => {}); + procedurePool.submitWithName('logic0', 'native-memory-init-responseType', res, undefined, (): void => { }); }); } setCurrentSelectIPid(ipid: number): void { - procedurePool.submitWithName('logic0', 'native-memory-set-current_ipid', ipid, undefined, (): void => {}); + procedurePool.submitWithName('logic0', 'native-memory-set-current_ipid', ipid, undefined, (): void => { }); + } + + public static convertJSON(arr: ArrayBuffer | Array): any { + if (arr instanceof ArrayBuffer) { + let dec = new TextDecoder(); + let str = dec.decode(arr); + let jsonArray: Array = []; + str = str.substring(str.indexOf('\n') + 1); + if (!str) { + } else { + let parse; + let tansStr: string; + try { + tansStr = str.replace(/[\t\r\n]/g, ''); + parse = JSON.parse(tansStr); + } catch { + try { + tansStr = tansStr!.replace(/[^\x20-\x7E]/g, '?'); //匹配乱码字 符,将其转换为? + parse = JSON.parse(tansStr); + } catch { + tansStr = tansStr!.replace(/\\/g, '\\\\'); + parse = JSON.parse(tansStr); + } + } + let columns = parse.columns; + let values = parse.values; + for (let i = 0; i < values.length; i++) { + let obj: unknown = {}; + for (let j = 0; j < columns.length; j++) { + //@ts-ignore + obj[columns[j]] = values[i][j]; + } + jsonArray.push(obj); + } + } + return jsonArray; + } else { + return arr; + } } } diff --git a/ide/src/trace/component/trace/search/Search.html.ts b/ide/src/trace/component/trace/search/Search.html.ts index 33705e584afc07e8beb9267dc5323ad70e5db7f2..8e97e86a39c17950c5c191554c6791a72ada883a 100644 --- a/ide/src/trace/component/trace/search/Search.html.ts +++ b/ide/src/trace/component/trace/search/Search.html.ts @@ -69,6 +69,12 @@ export const SearchHtml = ` :host(:not([show-search-info])) .search-info{ display: none; } + :host(:not([distributed])) #trace_select{ + display: none; + } + :host([distributed]) #trace_select{ + display: block; + } .search-info span{ color:#ABABAB; } @@ -129,13 +135,22 @@ export const SearchHtml = ` padding-right: 20px; padding-left: 45px; } + #trace_selector{ + position: unset; + width: 100px; + margin-left: -10px; + border:none; + } input[name="retarge_index"]{ width:100px!important; } `, + },{ + name: 'Process', + value: (this.transferString(processName ?? '') || 'NULL') + ' [' + data.pid + '] ', + },{ + name: 'Thread', + value: (this.transferString(threadName ?? '') || 'NULL') + ' [' + data.tid + '] ', }); } else { - list.unshift({ name: 'Name', value: name }); + list.unshift({ + name: 'Name', + value: name + },{ + name: 'Process', + value: (this.transferString(processName ?? '') || 'NULL') + ' [' + data.pid + '] ', + },{ + name: 'Thread', + value: (this.transferString(threadName ?? '') || 'NULL') + ' [' + data.tid + '] ', + }); } - this.addTabPanelContent(list, data); + this.addTabPanelContent(list, data, information); this.currentSelectionTbl!.dataSource = list; let funcClick = this.currentSelectionTbl?.shadowRoot?.querySelector('#function-jump'); funcClick?.addEventListener('click', () => { scrollCallback(asyncBinderStract); + let timeLineNode = new ThreadTreeNode( + asyncBinderStract.tid, + asyncBinderStract.pid, + asyncBinderStract.startTs, + asyncBinderStract.depth + ); + jankJumperList.push(timeLineNode); + if (callback) { + let linkTo = 'binder-to'; + callback(jankJumperList, linkTo, binderTid); + linkTo = ''; + } }); + }); } - private addTabPanelContent(contentList: unknown[], data: FuncStruct): void { + private addTabPanelContent(contentList: any[], data: FuncStruct, information: string): void { contentList.push({ name: 'StartTime(Relative)', value: getTimeString(data.startTs || 0), }); contentList.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startTs || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + (window as any).recordStartNS) / 1000000000 + 's', }); contentList.push({ name: 'Duration', @@ -499,6 +706,7 @@ export class TabPaneCurrentSelection extends BaseElement { if (data.argsetid && data.argsetid > -1) { contentList.push({ name: 'arg_set_id', value: data.argsetid }); } + contentList.push({ name: 'information', value: information }); } private tabCurrentSelectionInit(leftTitleStr: string): void { @@ -524,7 +732,9 @@ export class TabPaneCurrentSelection extends BaseElement { } async setClockData(data: ClockStruct): Promise { - await this.setRealTime(); + if(SpApplication.traceType.indexOf('SQLite') === -1) { + await this.setRealTime(); + } this.setTableHeight('auto'); //时钟信息 this.tabCurrentSelectionInit('Counter Details'); @@ -540,32 +750,63 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); this.currentSelectionTbl!.dataSource = list; - // @ts-ignore - let startTimeAbsolute = (data.startNS || 0) + (window as unknown).recordStartNS; + let startTimeAbsolute = (data.startNS || 0) + Utils.getInstance().getRecordStartNS(); this.addClickToTransfBtn(startTimeAbsolute, CLOCK_TRANSF_BTN_ID, CLOCK_STARTTIME_ABSALUTED_ID); } + setDmaFenceData(data: DmaFenceStruct, rowData: any[]): void { + this.setTableHeight('auto'); + this.tabCurrentSelectionInit('Slice Details'); + let list: any[] = []; + list.push({ + name: 'Title', + value: data.sliceName, + }); + list.push({ + name: 'StartTime(Relative)', + value: getTimeString(data.startTime || 0), + }); + list.push({ + name: 'StartTime(Absolute)', + value: ((data.startTime || 0) + (window as any).recordStartNS) / 1000000000 + 's', + }); + if (data.dur !== 0) { + list.push({ + name: 'Wall Duration', + value: getTimeString(data.dur || 0) + }); + } + list.push({ + name: 'driver', + value: data.driver, + }); + list.push({ + name: 'context', + value: data.context, + }); + this.currentSelectionTbl!.dataSource = list; + } + setPerfToolsData(data: PerfToolStruct): void { this.setTableHeight('auto'); //Perf Tools info this.tabCurrentSelectionInit('Slice Details'); - let list: unknown[] = []; + let list: any[] = []; list.push({ name: 'Name', value: data.name, }); list.push({ name: 'StartTime(Relative)', - value: getTimeString(data.startNS || 0), + value: getTimeString(data.startTs || 0), }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startNS || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + (window as any).recordStartNS) / 1000000000 + 's', }); list.push({ name: 'Value', - value: Number(data.count), + value: data.count, }); list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); this.currentSelectionTbl!.dataSource = list; @@ -586,8 +827,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startTime || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTime || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'Value', value: data.value }); list.push({ name: 'Delta', value: data.delta }); @@ -613,8 +853,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startNS || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startNS || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'Name', value: data.name }); list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); @@ -632,10 +871,13 @@ export class TabPaneCurrentSelection extends BaseElement { data: ThreadStruct, scrollCallback: ((d: unknown) => void) | undefined, scrollWakeUp: (d: unknown) => void | undefined, + scrollPrio: (d: any) => void | undefined, callback?: (data: Array, str: string) => void ): Promise { //线程信息 - await this.setRealTime(); + if(SpApplication.traceType.indexOf('SQLite') === -1) { + await this.setRealTime(); + } this.setTableHeight('550px'); this.initCanvas(); let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector('#leftTitle'); @@ -649,7 +891,7 @@ export class TabPaneCurrentSelection extends BaseElement { let cpu = new CpuStruct(); cpu.id = data.id; cpu.startTime = data.startTime; - this.queryThreadDetails(data, list, jankJumperList, callback, scrollWakeUp, scrollCallback); + this.queryThreadDetails(data, list, jankJumperList, callback, scrollWakeUp, scrollPrio, scrollCallback); } private sortByNearData(nearData: unknown[], data: ThreadStruct, list: unknown[]): unknown[] { @@ -671,7 +913,7 @@ export class TabPaneCurrentSelection extends BaseElement {
${ // @ts-ignore Utils.getEndState(near.state) - }
+ }
`, }); @@ -683,7 +925,7 @@ export class TabPaneCurrentSelection extends BaseElement {
${ // @ts-ignore Utils.getEndState(near.state) - }
+ } `, }); @@ -724,6 +966,7 @@ export class TabPaneCurrentSelection extends BaseElement { jankJumperList: ThreadTreeNode[], callback: ((data: Array, str: string) => void) | undefined, scrollWakeUp: (d: unknown) => void | undefined, + scrollPrio: (d: any) => void | undefined, scrollCallback: ((d: unknown) => void) | undefined ): void { Promise.all([ @@ -732,8 +975,8 @@ export class TabPaneCurrentSelection extends BaseElement { this.queryThreadStateDArgs(data.argSetID), queryThreadNearData(data.id!, data.startTime!), ]).then((result) => { - let fromBean = result[0] as WakeupBean; - let wakeUps = result[1] as WakeupBean[]; + let fromBean = result[0]; + let wakeUps = result[1]; let args = result[2]; let [preData, nextData] = this.sortByNearData(result[3], data, list); this.setWakeupData(fromBean, wakeUps, list); @@ -743,8 +986,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); } this.currentSelectionTbl!.dataSource = list; - // @ts-ignore - let startTimeAbsolute = (data.startTime || 0) + (window as unknown).recordStartNS; + let startTimeAbsolute = (data.startTime || 0) + Utils.getInstance().getRecordStartNS(); this.addClickToTransfBtn(startTimeAbsolute, THREAD_TRANSF_BTN_ID, THREAD_STARTTIME_ABSALUTED_ID); let timeLineNode = new ThreadTreeNode(data.tid!, data.pid!, data.startTime!); jankJumperList.push(timeLineNode); @@ -752,7 +994,7 @@ export class TabPaneCurrentSelection extends BaseElement { callback(jankJumperList, this.wakeUp); this.wakeUp = ''; } - this.stateClickHandler(preData, nextData, data, scrollWakeUp, scrollCallback); + this.stateClickHandler(preData, nextData, data, scrollWakeUp, scrollCallback, scrollPrio); this.wakeupClickHandler(wakeUps, fromBean, scrollWakeUp); }); } @@ -805,7 +1047,8 @@ export class TabPaneCurrentSelection extends BaseElement { nextData: unknown, data: ThreadStruct, scrollWakeUp: (d: unknown) => void | undefined, - scrollCallback: ((d: unknown) => void) | undefined + scrollCallback: ((d: unknown) => void) | undefined, + scrollPrio: (d: any) => void | undefined ): void { this.currentSelectionTbl?.shadowRoot?.querySelector('#next-state-click')?.addEventListener('click', () => { if (nextData && scrollWakeUp !== undefined) { @@ -859,9 +1102,26 @@ export class TabPaneCurrentSelection extends BaseElement { scrollCallback(data); } }); + this.currentSelectionTbl?.shadowRoot?.querySelector('#prio-click')?.addEventListener('click', (ev) => { + if (scrollPrio) { + sqlPrioCount(data).then((res: any) => { + scrollPrio(res); + }); + } + }); } private async prepareThreadInfo(list: unknown[], data: ThreadStruct): Promise { + let processName = Utils.getInstance().getProcessMap().get(data.pid!); + let threadName = Utils.getInstance().getThreadMap().get(data.tid!); + list.push({ + name: 'Process', + value: (this.transferString(processName ?? '') || 'NULL') + ' [' + data.pid + '] ', + }); + list.push({ + name: 'Thread', + value: (this.transferString(threadName ?? '') || 'NULL') + ' [' + data.tid + '] ', + }); list.push({ name: 'StartTime(Relative)', value: getTimeString(data.startTime || 0), @@ -917,23 +1177,16 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'Freq [KHz,μs]', value: str.substring(0, str.length - 1) }); } - let slice = Utils.SCHED_SLICE_MAP.get(`${data.id}-${data.startTime}`); + let slice = Utils.getInstance().getSchedSliceMap().get(`${data.id}-${data.startTime}`); if (slice) { - list.push({ name: 'Prio', value: `${slice.priority}` }); - } - let processName = Utils.PROCESS_MAP.get(data.pid!); - if ( - processName === null || - processName === undefined || - processName === '' || - processName.toLowerCase() === 'null' - ) { - processName = Utils.THREAD_MAP.get(data.tid!) || 'null'; + list.push({ + name: 'Prio', + value: `
+
${slice.priority}
+ +
`, + }); } - list.push({ - name: 'Process', - value: this.transferString(processName ?? '') + ' [' + data.pid + '] ', - }); } setJankData( @@ -946,7 +1199,7 @@ export class TabPaneCurrentSelection extends BaseElement { this.tabCurrentSelectionInit('Slice Details'); let list: unknown[] = []; this.setJankCommonMessage(list, data); - if (data.type === '0') { + if (`${data.type}` === '0') { this.handleTypeJank(data, list, scrollCallback, callback); } else { this.currentSelectionTbl!.dataSource = list; @@ -961,7 +1214,7 @@ export class TabPaneCurrentSelection extends BaseElement { ): void { this.setJankType(data, list); let jankJumperList: Array = []; - if (data.frame_type === 'render_service') { + if (data.frameType === 'render_service') { queryGpuDur(data.id!).then((it) => { if (it.length > 0) { //@ts-ignore @@ -969,9 +1222,9 @@ export class TabPaneCurrentSelection extends BaseElement { } }); this.handleRenderServiceJank(data, list, jankJumperList, scrollCallback, callback); - } else if (data.frame_type === 'app') { + } else if (data.frameType === 'app') { this.handleAppJank(list, data, jankJumperList, scrollCallback, callback); - } else if (data.frame_type === 'frameTime') { + } else if (data.frameType === 'frameTime') { this.handleFrameTimeJank(data, list, jankJumperList, scrollCallback, callback); } } @@ -1019,8 +1272,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.rs_ts || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.rs_ts || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'end time', @@ -1061,8 +1313,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.ts || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.ts || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'end time', @@ -1210,8 +1461,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startTs || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'EndTime(Relative)', @@ -1219,8 +1469,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'EndTime(Abslute)', - // @ts-ignore - value: ((data.startTs || 0) + (data.dur || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + (data.dur || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'Dur', @@ -1245,8 +1494,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startTs || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); if (data.dur && data.dur > 0) { list.push({ @@ -1258,8 +1506,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'EndTime(Absolute)', - // @ts-ignore - value: ((data.startTs || 0) + (data.dur || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + (data.dur || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); } else { list.push({ @@ -1285,8 +1532,8 @@ export class TabPaneCurrentSelection extends BaseElement { index === 0 ? 'NULL' : `${AppStartupStruct.getStartupName(sortedArray[index - 1].startName)} ${getTimeString( - sortedArray[index - 1].startTs + sortedArray[index - 1].dur - )}`, + sortedArray[index - 1].startTs + sortedArray[index - 1].dur + )}`, }); list.push({ name: 'EndSlice', @@ -1294,8 +1541,8 @@ export class TabPaneCurrentSelection extends BaseElement { index === sortedArray.length - 1 ? 'NULL' : `${AppStartupStruct.getStartupName(sortedArray[index + 1].startName)} ${getTimeString( - sortedArray[index + 1].startTs - )}`, + sortedArray[index + 1].startTs + )}`, }); } }); @@ -1322,8 +1569,7 @@ export class TabPaneCurrentSelection extends BaseElement { let startIcon = this.currentSelectionTbl?.shadowRoot?.querySelector('#start-jump'); let endIcon = this.currentSelectionTbl?.shadowRoot?.querySelector('#end-jump'); let scrollClick = (type: number): void => { - // @ts-ignore - let recordNs: number = (window as unknown).recordStartNS; + let recordNs: number = Utils.getInstance().getRecordStartNS(); let useEnd = type === 1 && data.startName! < 6; queryThreadByItid( useEnd ? data.endItid! : data.itid!, @@ -1374,8 +1620,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.startTs || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.startTs || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); this.currentSelectionTbl!.dataSource = list; @@ -1401,8 +1646,7 @@ export class TabPaneCurrentSelection extends BaseElement { let startIcon = this.currentSelectionTbl?.shadowRoot?.querySelector('#start-jump'); if (startIcon) { startIcon.addEventListener('click', () => { - // @ts-ignore - let recordNs: number = (window as unknown).recordStartNS; + let recordNs: number = Utils.getInstance().getRecordStartNS(); queryThreadByItid(data.itid!, recordNs + data.startTs!).then((result) => { if (result.length > 0) { //@ts-ignore @@ -1438,8 +1682,7 @@ export class TabPaneCurrentSelection extends BaseElement { list.push({ name: 'Start time(Relative)', value: `${Utils.getTimeString(dataTs)}` }); list.push({ name: 'Start time(Absolute)', - // @ts-ignore - value: ((dataTs || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((dataTs || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'End time(Relative)', @@ -1447,8 +1690,7 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'End time(Absolute)', - // @ts-ignore - value: (dataTs + (data.dur || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: (dataTs + (data.dur || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'Duration', value: `${Utils.getTimeString(data.dur || 0)}` }); if (data.status === 'Completion delay') { @@ -1479,8 +1721,7 @@ export class TabPaneCurrentSelection extends BaseElement { private fpsClickEvent(data: FrameAnimationStruct, scrollCallback: Function): void { let queryJoinName = `${data.frameInfo?.split(':')[1]}: ${data.name?.split(':')![1]}`; - // @ts-ignore - let recordNs: number = (window as unknown).recordStartNS; + let recordNs: number = Utils.getInstance().getRecordStartNS(); this.currentSelectionTbl?.shadowRoot?.querySelector('#fps-jump')?.addEventListener('click', () => { queryFpsSourceList(data.inputTime, data.endTime, queryJoinName).then((result) => { if (result.length > 0) { @@ -1512,11 +1753,11 @@ export class TabPaneCurrentSelection extends BaseElement { private setJankType(data: JankStruct, list: unknown[]): void { if (data.jank_tag === 1) { - if (data.frame_type === 'render_service') { + if (data.frameType === 'render_service') { list.push({ name: 'Jank Type', value: 'RenderService Deadline Missed' }); - } else if (data.frame_type === 'app') { + } else if (data.frameType === 'app') { list.push({ name: 'Jank Type', value: 'APP Deadline Missed' }); - } else if (data.frame_type === 'frameTime') { + } else if (data.frameType === 'frameTime') { list.push({ name: 'Jank Type', value: 'Deadline Missed' }); } } else if (data.jank_tag === 3) { @@ -1531,11 +1772,10 @@ export class TabPaneCurrentSelection extends BaseElement { list.push({ name: 'StartTime(Relative)', value: getTimeString(data.ts || 0) }); list.push({ name: 'StartTime(Absolute)', - // @ts-ignore - value: ((data.ts || 0) + (window as unknown).recordStartNS) / 1000000000 + 's', + value: ((data.ts || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', }); list.push({ name: 'Duration', value: data.dur ? getTimeString(data.dur) : ' ' }); - if (data.frame_type !== 'frameTime') { + if (data.frameType !== 'frameTime') { list.push({ name: 'Process', value: data.cmdline + ' ' + data.pid }); } } @@ -1588,14 +1828,14 @@ export class TabPaneCurrentSelection extends BaseElement { let wakeup = await queryRunnableTimeByRunning(data.tid!, data.startTime); if (wakeup && wakeup[0]) { let wakeupTs = wakeup[0].ts as number; - let recordStartTs = window.recordStartNS; + let recordStartTs = Utils.getInstance().getRecordStartNS(); let wf = await queryThreadWakeUpFrom(data.id, wakeupTs); if (wf && wf[0]) { wb = wf[0]; if (wb !== null) { wb.wakeupTime = wakeupTs - recordStartTs; - wb.process = Utils.PROCESS_MAP.get(wb.pid!) || 'Process'; - wb.thread = Utils.THREAD_MAP.get(wb.tid!) || 'Thread'; + wb.process = Utils.getInstance().getProcessMap().get(wb.pid!) || 'Process'; + wb.thread = Utils.getInstance().getThreadMap().get(wb.tid!) || 'Thread'; wb.schedulingLatency = (data.startTime || 0) - (wb.wakeupTime || 0); wb.schedulingDesc = INPUT_WORD; } @@ -1613,15 +1853,14 @@ export class TabPaneCurrentSelection extends BaseElement { let wakeup = await queryRunnableTimeByRunning(data.tid!, data.ts!); if (wakeup && wakeup[0]) { let wakeupTs = wakeup[0].ts as number; - // @ts-ignore - let recordStartTs = (window as unknown).recordStartNS; + let recordStartTs = Utils.getInstance().getRecordStartNS(); let wf = await queryThreadWakeUpFrom(data.itid!, wakeupTs); if (wf && wf[0]) { wb = wf[0]; if (wb !== null) { wb.wakeupTime = wakeupTs - recordStartTs; - wb.process = Utils.PROCESS_MAP.get(wb.pid!) || 'Process'; - wb.thread = Utils.THREAD_MAP.get(wb.tid!) || 'Thread'; + wb.process = Utils.getInstance().getProcessMap().get(wb.pid!) || 'Process'; + wb.thread = Utils.getInstance().getThreadMap().get(wb.tid!) || 'Thread'; wb.schedulingLatency = (data.ts || 0) - (wb.wakeupTime || 0); wb.schedulingDesc = INPUT_WORD; } @@ -1633,13 +1872,10 @@ export class TabPaneCurrentSelection extends BaseElement { /** * 查询出 线程唤醒了哪些线程信息 */ - async queryThreadWakeUpFromData(itid: number, startTime: number, dur: number): Promise { - // @ts-ignore - let wakeUps = await queryThreadWakeUpFrom(itid, startTime + (window as unknown).recordStartNS); + async queryThreadWakeUpFromData(itid: number, startTime: number, dur: number): Promise { + let wakeUps = await queryThreadWakeUpFrom(itid, startTime + Utils.getInstance().getRecordStartNS()); if (wakeUps !== undefined && wakeUps.length > 0) { return wakeUps[0]; - } else { - return; } } @@ -1757,7 +1993,7 @@ export class TabPaneCurrentSelection extends BaseElement { this.currentSelectionTbl = this.shadowRoot?.querySelector('#selectionTbl'); this.wakeupListTbl = this.shadowRoot?.querySelector('#wakeupListTbl'); this.scrollView = this.shadowRoot?.querySelector('#scroll_view'); - this.currentSelectionTbl?.addEventListener('column-click', (ev: unknown): void => {}); //@ts-ignore + this.currentSelectionTbl?.addEventListener('column-click', (ev: any): void => { }); //@ts-ignore window.subscribe(window.SmartEvent.UI.WakeupList, (data: Array) => this.showWakeupListTableData(data)); } @@ -1859,10 +2095,18 @@ export class ThreadTreeNode { tid: number = 0; pid: number = -1; startTime: number = 1; + depth: number = 0; - constructor(tid: number, pid: number, startTime: number) { + constructor(tid: number, pid: number, startTime: number, depth: number = 0) { this.tid = tid; this.pid = pid; this.startTime = startTime; + this.depth = depth; } } + +class FunDetail { + slice: string = ''; + CN: string = ''; + EN: string = ''; +} diff --git a/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts b/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts index 798b777cc8c97c17ba2d35c04fe78280f082229b..f8d3d3c65dabcbbc65a3829bc3b7c22d02662a6f 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts @@ -109,7 +109,7 @@ export class TabPaneDataCut extends BaseElement { ); } if ( - this.currentSelection!.clockMapData.size === 1 && + this.currentSelection!.clockMapData.size > 0 && this.currentSelection!.clockMapData.has('gpufreq Frequency') === true ) { options.push({ diff --git a/ide/src/trace/component/trace/sheet/TabPaneFilter.html.ts b/ide/src/trace/component/trace/sheet/TabPaneFilter.html.ts index e623bed0374debb0f6f001e3278429f32a39a24c..5613b4216f238d1367b9d8e371ca665641b0cde2 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneFilter.html.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneFilter.html.ts @@ -147,6 +147,14 @@ margin-left: 15px; :host(:not([options])) #check-popover{ display: none; } + +:host(:not([cpu_config])) #data-core-popover{ + display: none; +} + +:host(:not([group_config])) #group-mining-popover{ + display: none; +} #icon[name="statistics"]{ margin-left: 12px; } @@ -174,6 +182,61 @@ margin-left: 15px; border-radius: 16px; padding: 2px 18px; } +#tb_core_setting, #tb_cpu, #tb_add_group{ + height: 135px; + width: 250px; + background: var(--dark-background4,#F2F2F2); + overflow-y: auto ; + border-radius: 5px; + border: solid 1px var(--dark-border1,#e0e0e0); +} +#tb_core_setting { + display: grid; + grid-template-columns: auto auto auto auto; +} + +.button{ + opacity: 0.9; + font-size: 13px; + color: #0A59F7; + text-align: center; + line-height: 16px; + background: var(--dark-background3,#F4F3F4); + border: 1px solid var(--dark-background8,#F4F3F4); + border-radius: 16px; + padding: 2px 18px; +} + +.core_line{ + position: fixed; + bottom: 0; + height: 35px; + line-height: 35px; + position: sticky; + top: 0; + background: var(--dark-background4,#F2F2F2); + z-index: 1; + width: 100%; + font-Weight:bold; + font-style:12px; + text-align:center; +} +.tb_setting_content { + display: flex; + justify-content: space-between; +} +#move { + display: flex; + flex-direction: column; + width: 50px; + justify-content: space-evenly; + height: 135px; +} +.check-content{ + display: flex; + align-content: center; + justify-content: center; +} #call-tree-popover[visible="true"] #call-tree{ color: #0A59F7; @@ -187,6 +250,12 @@ margin-left: 15px; #data-mining-popover[visible="true"] #data-mining{ color: #0A59F7; } +#data-core-popover[visible="true"] #core-mining{ + color: #0A59F7; +} +#group-mining-popover[visible="true"] #group-mining{ + color: #0A59F7; +} .mining-checked[highlight]{ color: #FFFFFF; @@ -318,11 +387,41 @@ margin-left: 15px; Library Filter + +
+
+
+
Reset
+
Confirm
+
+
+ CPU Setting +
+ +
+
+
+
+
>
+
<
+
+
+
Group
+
+
+
+
+
Reset
+
Confirm
+
+
+ Group Setting +
Statistics by Thread
-`; +` export const TabPaneFilterHtml = (input: string): string => { return replacePlaceholders(html, input); -}; +} diff --git a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts index 50496fdefb1288d1dfb1569f3864495659b976bd..c6af17d3656efa33dd451863f7acb399726acb5f 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts @@ -23,6 +23,7 @@ import { LitCheckBox } from '../../../../base-ui/checkbox/LitCheckBox'; import { LitSelect } from '../../../../base-ui/select/LitSelect'; import { queryTransferList } from '../../../database/sql/Perf.sql'; import { TabPaneFilterHtml } from './TabPaneFilter.html'; +import { SpSystemTrace } from '../../SpSystemTrace'; export interface FilterData { inputValue: string; @@ -40,6 +41,13 @@ export interface MiningData { remove?: Array | null | undefined; } +export class CpuStatus { + cpu: number = 0; + small: boolean = false; + medium: boolean = false; + large: boolean = false; +} + @element('tab-pane-filter') export class TabPaneFilter extends BaseElement { private filterInputEL: HTMLInputElement | null | undefined; @@ -141,6 +149,11 @@ export class TabPaneFilter extends BaseElement { this.initializeLibrary(); this.initBaseElListener(); this.queryElListener(); + this.filterInputEL?.addEventListener('keydown', (ev) => { + if (ev.key === 'Enter') { + ev.stopPropagation(); + } + }); } private queryElListener(): void { @@ -468,6 +481,124 @@ export class TabPaneFilter extends BaseElement { } } + //添加cpu列表 + setCoreConfigList(count: number, small: Array, mid: Array, large: Array) { + let divEl = this.shadowRoot!.querySelector('#data-core-popover > div > #tb_core_setting'); + divEl!.innerHTML = ''; + this.createCoreHeaderDiv(divEl); + for (let i = 0; i < count; i++) { + let obj = { + cpu: i, + // @ts-ignore + small: small.includes(i), + // @ts-ignore + medium: mid.includes(i), + // @ts-ignore + large: large.includes(i), + }; + this.createCheckBoxLine(divEl, obj, small, mid, large); + } + } + + createCoreHeaderDiv(tab: any) { + let cpuIdLine = document.createElement('div'); + cpuIdLine.className = 'core_line'; + cpuIdLine.style.fontWeight = 'bold'; + cpuIdLine.style.fontSize = '12px'; + cpuIdLine.textContent = 'Cpu'; + cpuIdLine.style.textAlign = 'center'; + let smallLine = document.createElement('div'); + smallLine.className = 'core_line'; + smallLine.style.fontWeight = 'bold'; + smallLine.textContent = 'S'; + smallLine.style.fontSize = '12px'; + smallLine.style.textAlign = 'center'; + let mediumLine = document.createElement('div'); + mediumLine.className = 'core_line'; + mediumLine.style.fontWeight = 'bold'; + mediumLine.textContent = 'M'; + mediumLine.style.fontSize = '12px'; + mediumLine.style.textAlign = 'center'; + let largeLine = document.createElement('div'); + largeLine.className = 'core_line'; + largeLine.style.fontWeight = 'bold'; + largeLine.textContent = 'L'; + largeLine.style.fontSize = '12px'; + largeLine.style.textAlign = 'center'; + tab?.append(...[cpuIdLine, smallLine, mediumLine, largeLine]); + } + + //添加对应的cpu checkbox,并添加对应的监听事件 + createCheckBoxLine( + divEl: any, + cpuStatus: CpuStatus, + small: Array, + mid: Array, + large: Array + ): void { + let div = document.createElement('div'); + div.textContent = cpuStatus.cpu + ''; + div.style.textAlign = 'center'; + div.style.fontWeight = 'normal'; + let smallCheckBox: LitCheckBox = new LitCheckBox(); + smallCheckBox.checked = cpuStatus.small; + smallCheckBox.setAttribute('not-close', ''); + smallCheckBox.style.textAlign = 'center'; + smallCheckBox.style.marginLeft = 'auto'; + smallCheckBox.style.marginRight = 'auto'; + let midCheckBox: LitCheckBox = new LitCheckBox(); + midCheckBox.checked = cpuStatus.medium; + midCheckBox.setAttribute('not-close', ''); + midCheckBox.style.textAlign = 'center'; + midCheckBox.style.marginLeft = 'auto'; + midCheckBox.style.marginRight = 'auto'; + let largeCheckBox: LitCheckBox = new LitCheckBox(); + largeCheckBox.checked = cpuStatus.large; + largeCheckBox.setAttribute('not-close', ''); + largeCheckBox.style.marginLeft = 'auto'; + largeCheckBox.style.marginRight = 'auto'; + smallCheckBox.addEventListener('change', (e: any) => { + midCheckBox.checked = false; + largeCheckBox.checked = false; + cpuStatus.small = e.detail.checked; + this.canUpdateCheckList(e.detail.checked, small, cpuStatus.cpu); + mid = mid.filter((it) => it !== cpuStatus.cpu); + large = large.filter((it) => it !== cpuStatus.cpu); + }); + midCheckBox.addEventListener('change', (e: any) => { + largeCheckBox.checked = false; + smallCheckBox.checked = false; + cpuStatus.medium = e.detail.checked; + this.canUpdateCheckList(e.detail.checked, mid, cpuStatus.cpu); + large = large.filter((it) => it !== cpuStatus.cpu); + small = small.filter((it) => it !== cpuStatus.cpu); + }); + largeCheckBox.addEventListener('change', (e: any) => { + midCheckBox.checked = false; + smallCheckBox.checked = false; + cpuStatus.large = e.detail.checked; + this.canUpdateCheckList(e.detail.checked, large, cpuStatus.cpu); + mid = mid.filter((it) => it !== cpuStatus.cpu); + small = small.filter((it) => it !== cpuStatus.cpu); + }); + divEl!.append(...[div, smallCheckBox, midCheckBox, largeCheckBox]); + } + + //判断checkList数组是否需要push数据或删除数据 + canUpdateCheckList(check: boolean, coreArr: Array, cpu: number): void { + if (check) { + const isFalse = coreArr.includes(cpu); + if (!isFalse) { + coreArr.push(cpu); + } + } else { + const index = coreArr.indexOf(cpu); + if (index !== -1) { + coreArr.splice(index, 1); + } + } + } + private treeCheckClickSwitch(idx: number, check: boolean, row: NodeListOf): void { let checkList = []; for (let index = 0; index < 6; index++) { @@ -575,6 +706,7 @@ export class TabPaneFilter extends BaseElement { this.value = this.value.replace(/\D/g, ''); }; e.addEventListener('keyup', (event: unknown): void => { + SpSystemTrace.isKeyUp = true; // @ts-ignore event.stopPropagation(); // @ts-ignore diff --git a/ide/src/trace/component/trace/sheet/TabPaneMt.html.ts b/ide/src/trace/component/trace/sheet/TabPaneMt.html.ts new file mode 100644 index 0000000000000000000000000000000000000000..93bdba7ea7a3471b7238a31e0fe61834407ceaad --- /dev/null +++ b/ide/src/trace/component/trace/sheet/TabPaneMt.html.ts @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 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. + */ +export const MtSettingHtml = ` + + + + + + + + + + + + + + + + + + + + +`; \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/TabPaneTime.html.ts b/ide/src/trace/component/trace/sheet/TabPaneTime.html.ts new file mode 100644 index 0000000000000000000000000000000000000000..52930d242e7208859e30bae112a2c46e0f02d117 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/TabPaneTime.html.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 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. + */ +export const ClassifyCoreSettingHtml = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/ability/TabPanePurgPinComparisonAbility.ts b/ide/src/trace/component/trace/sheet/ability/TabPanePurgPinComparisonAbility.ts index b19c2fb9f09f7c620a0aea8701665c64b999d9e6..4f8d00e52da2e2d2903b5202f41d150df11946ea 100644 --- a/ide/src/trace/component/trace/sheet/ability/TabPanePurgPinComparisonAbility.ts +++ b/ide/src/trace/component/trace/sheet/ability/TabPanePurgPinComparisonAbility.ts @@ -56,6 +56,7 @@ export class TabPanePurgPinComparisonAbility extends BaseElement { } private initSelect(fileStartNs: number, purgePinComFileArr: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; let option = new LitSelectOption(); @@ -75,7 +76,7 @@ export class TabPanePurgPinComparisonAbility extends BaseElement { // @ts-ignore if (input.value === f.name) { // @ts-ignore - this.updateComparisonData(fileStartNs, f.startNs); + that.updateComparisonData(fileStartNs, f.startNs); } } // @ts-ignore e.stopPropagation(); diff --git a/ide/src/trace/component/trace/sheet/ability/TabPanePurgTotalComparisonAbility.ts b/ide/src/trace/component/trace/sheet/ability/TabPanePurgTotalComparisonAbility.ts index 8be409a973be3a40f9b3ded268f3e0dcf5fb5d10..5ebcae83d8df8aee97488ac3490a8295e3141e87 100644 --- a/ide/src/trace/component/trace/sheet/ability/TabPanePurgTotalComparisonAbility.ts +++ b/ide/src/trace/component/trace/sheet/ability/TabPanePurgTotalComparisonAbility.ts @@ -56,6 +56,7 @@ export class TabPanePurgTotalComparisonAbility extends BaseElement { } private initSelect(fileStartNs: number, purgeTotalComFileArr: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; let option = new LitSelectOption(); @@ -75,7 +76,7 @@ export class TabPanePurgTotalComparisonAbility extends BaseElement { // @ts-ignore if (input.value === f.name) { // @ts-ignore - this.updateComparisonData(fileStartNs, f.startNs); + that.updateComparisonData(fileStartNs, f.startNs); } } // @ts-ignore e.stopPropagation(); diff --git a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneComparison.ts b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneComparison.ts index 93348b04a45dedcba34bebd7dbe491064fabb5d3..2b01b44b1cc8ef37c91ec35d8418814d935b64d2 100644 --- a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneComparison.ts +++ b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneComparison.ts @@ -61,6 +61,7 @@ export class TabPaneComparison extends BaseElement { this.clear(); this.retainerTableEl!.snapshotDataSource = []; let fileArr: HeapSnapshotStruct[] = []; + let that = this; for (let file of dataListCache) { if (file.id !== data.id) { fileArr.push(file); @@ -71,7 +72,7 @@ export class TabPaneComparison extends BaseElement { this.initSelect(data.id, fileArr); this.baseFileId = data.id; this.targetFileId = fileArr[0].id; - this.updateComparisonData(data.id, fileArr[0].id); + that.updateComparisonData(data.id, fileArr[0].id); new ResizeObserver((): void => { this.comparisonTableEl!.style.height = '100%'; this.comparisonTableEl!.reMeauseHeight(); @@ -93,6 +94,7 @@ export class TabPaneComparison extends BaseElement { } initSelect(fileId: number, comFileArr: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; this.selectEl!.defaultValue = comFileArr[0].name || ''; @@ -111,7 +113,7 @@ export class TabPaneComparison extends BaseElement { this.retainerTableEl!.snapshotDataSource = []; for (let f of comFileArr) { if (input.value === f.name) { - this.updateComparisonData(fileId, f.id); + that.updateComparisonData(fileId, f.id); } } e.stopPropagation(); @@ -374,6 +376,7 @@ export class TabPaneComparison extends BaseElement { if (this.retainsData && this.retainsData.length > 0) { this.retainsDataInit(); let i = 0; + let that = this; if (this.retainsData[0].distance > 1) { this.retainsData[0].getChildren(); this.retainsData[0].expanded = false; @@ -393,7 +396,7 @@ export class TabPaneComparison extends BaseElement { } i++; // @ts-ignore - if (i < this.retainsData[0].distance - 1 && list[0].distance !== '-') { + if (i < that.retainsData[0].distance - 1 && list[0].distance !== '-') { list[0].getChildren(); list[0].expanded = false; if (structRow.hasNext) { @@ -404,7 +407,7 @@ export class TabPaneComparison extends BaseElement { } }); }; - getList(this.retainsData[0].children); + getList(that.retainsData[0].children); }; retainsTable(); this.retainerTableEl!.snapshotDataSource = this.retainsData; @@ -472,7 +475,8 @@ export class TabPaneComparison extends BaseElement { if (retainerNext.status) { retainerNext.getChildren(); let i = 0; - const retainsTable = (): void => { + let that = this; + let retainsTable = (): void => { const getList = (comList: Array): void => { comList.forEach((row): void => { let shallow = `${Math.round((row.shallowSize / this.fileSize) * 100)}%`; @@ -487,7 +491,7 @@ export class TabPaneComparison extends BaseElement { } i++; // @ts-ignore - if (i < this.retainsData[0].distance - 1 && comList[0].distance !== '-') { + if (i < that.retainsData[0].distance - 1 && comList[0].distance !== '-') { comList[0].getChildren(); comList[0].expanded = false; if (row.hasNext) { diff --git a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts index 60fe5d0d34cfc6754b56f705c1a9ad298adbbbbc..4e239182bf4a8a1faff01f8bb7ede441935366cf 100644 --- a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts +++ b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneJsCpu.ts @@ -207,16 +207,14 @@ export class TabPaneJsCpuCallTree extends BaseElement { } private sortTree(arr: Array): Array { - const defaultSort = ( - callTreeLeftData: JsCpuProfilerTabStruct, - callTreeRightData: JsCpuProfilerTabStruct - ): number => { - if (this.currentType === this.TYPE_TOP_DOWN) { + const that = this; + function defaultSort(callTreeLeftData: JsCpuProfilerTabStruct, callTreeRightData: JsCpuProfilerTabStruct): number { + if (that.currentType === that.TYPE_TOP_DOWN) { return callTreeRightData.totalTime - callTreeLeftData.totalTime; } else { return callTreeRightData.selfTime - callTreeLeftData.selfTime; } - }; + } const CallTreeSortArr = arr.sort((callTreeLeftData, callTreeRightData) => { if (this.sortKey === 'selfTimeStr' || this.sortKey === 'selfTimePercent') { if (this.sortType === 0) { @@ -251,6 +249,11 @@ export class TabPaneJsCpuCallTree extends BaseElement { return CallTreeSortArr; } + private clearTab(): void { + this.stackTable!.recycleDataSource = []; + this.callTreeTable!.recycleDataSource = []; + } + public initHtml(): string { return TabPaneJsCpuHtml; } diff --git a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneSummary.ts b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneSummary.ts index 539ac5d06b020a1fda3620054b29727a59faf4ad..c09252d5e30c267d09dfa4d069b5dcd4225d3365 100644 --- a/ide/src/trace/component/trace/sheet/ark-ts/TabPaneSummary.ts +++ b/ide/src/trace/component/trace/sheet/ark-ts/TabPaneSummary.ts @@ -324,34 +324,35 @@ export class TabPaneSummary extends BaseElement { clickToggleTable(): void { let lis = this.shadowRoot?.querySelectorAll('li'); + let that = this; lis!.forEach((li: HTMLElement, i: number) => { - lis![i].onclick = (): void => { + lis![i].onclick = function (): void { for (let i = 0; i < lis!.length; i++) { lis![i].className = ''; } switch (li.textContent) { case 'Retainers': - this.stackTable!.style.display = 'none'; - this.stackText!.style.display = 'none'; - this.tbs!.style.display = 'flex'; - this.tbs!.snapshotDataSource = this.retainsData; + that.stackTable!.style.display = 'none'; + that.stackText!.style.display = 'none'; + that.tbs!.style.display = 'flex'; + that.tbs!.snapshotDataSource = that.retainsData; break; case 'Allocation stack': - if (this.stackData.length > 0) { - this.stackText!.style.display = 'none'; - this.stackTable!.style.display = 'flex'; - this.stackTable!.recycleDataSource = this.stackData; + if (that.stackData.length > 0) { + that.stackText!.style.display = 'none'; + that.stackTable!.style.display = 'flex'; + that.stackTable!.recycleDataSource = that.stackData; } else { - this.stackText!.style.display = 'flex'; - if (this.retainsData === undefined || this.retainsData.length === 0) { - this.stackText!.textContent = ''; + that.stackText!.style.display = 'flex'; + if (that.retainsData === undefined || that.retainsData.length === 0) { + that.stackText!.textContent = ''; } else { - this.stackText!.textContent = + that.stackText!.textContent = 'Stack was not recorded for this object because it had been allocated before ' + 'this profile recording started.'; } } - this.tbs!.style.display = 'none'; + that.tbs!.style.display = 'none'; break; } // @ts-ignore @@ -602,7 +603,7 @@ export class TabPaneSummary extends BaseElement { } i++; //@ts-ignore - if (i < this.retainsData[0].distance - 1 && list[0].distance !== '-') { + if (i < that.retainsData[0].distance - 1 && list[0].distance !== '-') { list[0].getChildren(); list[0].expanded = false; if (summaryRow.hasNext) { @@ -613,7 +614,7 @@ export class TabPaneSummary extends BaseElement { } }); }; - getList(this.retainsData[0].children); + getList(that.retainsData[0].children); }; retainsTable(); this.tbs!.snapshotDataSource = this.retainsData; diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts index 37f08bd2c6aef766340be0f17cf251546e7b6dac..0bec3db96f5443848c9a16b43a982303ccfec6cc 100644 --- a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts @@ -55,8 +55,6 @@ export class TabPaneBinderDataCut extends BaseElement { private threadBinderMap: Map> = new Map(); private processIds: Array = []; private funcCycleArr: Array = []; - private currentCutThreadId: string | undefined; - private currentCutFuncName: string | undefined; set data(threadStatesParam: SelectionParam) { if (this.currentSelectionParam === threadStatesParam) { @@ -76,13 +74,11 @@ export class TabPaneBinderDataCut extends BaseElement { // @ts-ignore this.tHeadClick(this.threadBindersTbl!.recycleDataSource); this.parentElement!.style.overflow = 'hidden'; - this.currentCutThreadId = ''; - this.currentCutFuncName = ''; new ResizeObserver(() => { // @ts-ignore let lastHeight: number = this.threadBindersTbl.tableElement!.offsetHeight; this.cycleColumnDiv!.style.height = lastHeight + 'px'; - }).observe(this.parentElement!); + }).observe(this.threadBindersTbl!); } hideQueryArea(b: boolean): void { @@ -200,9 +196,9 @@ export class TabPaneBinderDataCut extends BaseElement { if (!this.threadBinderMap.has(b.pid + '_' + b.tid)) { this.threadArr.push({ title: - Utils.THREAD_MAP.get(b.tid) === null + Utils.getInstance().getThreadMap().get(b.tid) === null ? 'Thread' + ' ' + '[' + b.tid + ']' - : Utils.THREAD_MAP.get(b.tid) + ' ' + '[' + b.tid + ']', + : Utils.getInstance().getThreadMap().get(b.tid) + ' ' + '[' + b.tid + ']', totalCount: 0, tid: b.tid, pid: b.pid, @@ -242,7 +238,7 @@ export class TabPaneBinderDataCut extends BaseElement { cycleMap.set(tBinder[j].tid + '_' + cid, new Array()); } cycleArr = cycleMap.get(tBinder[j].tid + '_' + cid); - let thread: string = Utils.THREAD_MAP.get(tBinder[j].tid) || 'Thread'; + let thread: string = Utils.getInstance().getThreadMap().get(tBinder[j].tid) || 'Thread'; countBinder.title = 'cycle ' + (idx + 1) + '_' + thread; countBinder.tid = tBinder[j].tid; countBinder.pid = tBinder[j].pid; @@ -284,7 +280,7 @@ export class TabPaneBinderDataCut extends BaseElement { cycleMap.set(tBinder[j].tid + '_' + cid, new Array()); } cycleArr = cycleMap.get(tBinder[j].tid + '_' + cid); - let thread: string = Utils.THREAD_MAP.get(tBinder[j].tid) || 'Thread'; + let thread: string = Utils.getInstance().getThreadMap().get(tBinder[j].tid) || 'Thread'; countBinder.title = 'cycle ' + (i + 1) + '_' + thread; countBinder.tid = tBinder[j].tid; countBinder.pid = tBinder[j].pid; @@ -338,9 +334,9 @@ export class TabPaneBinderDataCut extends BaseElement { processArr.push({ pid: pid, title: - Utils.PROCESS_MAP.get(pid) === null + Utils.getInstance().getProcessMap().get(pid) === null ? 'Process' + ' ' + '[' + pid + ']' - : Utils.PROCESS_MAP.get(pid) + ' ' + '[' + pid + ']', + : Utils.getInstance().getProcessMap().get(pid) + ' ' + '[' + pid + ']', totalCount: 0, type: 'Process', children: [], @@ -728,7 +724,7 @@ export class TabPaneBinderDataCut extends BaseElement {
- + diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts index 454e9eec16ee38ded511058e6e6fed7c887d0043..9082cc4508af6528b4bb22700dff896830d4b93e 100644 --- a/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinders.ts @@ -26,7 +26,7 @@ import { SliceGroup } from '../../../../bean/StateProcessThread'; export class TabPaneBinders extends BaseElement { private threadBindersTbl: LitTable | null | undefined; private threadBindersTblSource: Array = []; - private currentSelectionParam: Selection | undefined; + private currentSelectionParam: SelectionParam | undefined; set data(threadStatesParam: SelectionParam | any) { if (this.currentSelectionParam === threadStatesParam) { @@ -140,7 +140,8 @@ export class TabPaneBinders extends BaseElement { initElements(): void { this.threadBindersTbl = this.shadowRoot?.querySelector('#tb-binder-count'); - this.threadBindersTbl!.itemTextHandleMap.set('title', Utils.transferBinderTitle); + this.threadBindersTbl!.itemTextHandleMap.set('title', (value) => + Utils.transferBinderTitle(value, this.currentSelectionParam?.traceId)); } connectedCallback(): void { diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstruction.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstruction.ts index 9ad56bdac5e7adf9b6b95f9a9c935eed5d6cc99b..23aed73c275a57893b266d74ac22730aec6d8fa5 100644 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstruction.ts +++ b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstruction.ts @@ -279,12 +279,10 @@ export class TabPaneSampleInstruction extends BaseElement { //计算当前节点下指令数之和 用于计算每个节点所占的宽度比 const total = isCycles ? instructionArray[key] - // @ts-ignore - .filter((i: unknown) => i.parentName === parentNode.name) + .filter((i: any) => i.parentName === parentNode.name) .reduce((pre: number, cur: SampleStruct) => pre + cur.cycles!, 0) : instructionArray[key] - // @ts-ignore - .filter((i: unknown) => i.parentName === parentNode.name) + .filter((i: any) => i.parentName === parentNode.name) .reduce((pre: number, cur: SampleStruct) => pre + cur.instructions!, 0); const curWidth = isCycles ? cur.cycles : cur.instructions; const width = Math.floor(parentNode.frame.width * (curWidth / total)); @@ -384,26 +382,18 @@ export class TabPaneSampleInstruction extends BaseElement { * @param relationData * @param clickData */ - setRelationDataProperty(relationData: Array, clickData: SampleStruct): void { - const propertyData = this.instructionData.find((subArr: unknown) => - // @ts-ignore + setRelationDataProperty(relationData: Array, clickData: SampleStruct): void { + const propertyData = this.instructionData.find((subArr: any) => subArr.some((obj: SampleStruct) => obj.begin === clickData.begin) ); //获取非unknown数据 - // @ts-ignore - const knownRelation = relationData.filter((relation) => relation.name.indexOf('unknown') < 0); - propertyData.forEach((property: unknown) => { - // @ts-ignore - const relation = knownRelation.find((relation) => relation.name === property.func_name); - // @ts-ignore + const knownRelation = relationData.filter((relation) => relation['name'].indexOf('unknown') < 0); + propertyData.forEach((property: any) => { + const relation = knownRelation.find((relation) => relation['name'] === property['func_name']); relation['instructions'] = Math.ceil(property['instructions']) || 1; - // @ts-ignore relation['hoverInstructions'] = Math.ceil(property['instructions']); - // @ts-ignore relation['cycles'] = Math.ceil(property['cycles']) || 1; - // @ts-ignore relation['hoverCycles'] = Math.ceil(property['cycles']); - // @ts-ignore this.maxDepth = Math.max(this.maxDepth, relation['depth']); }); //获取所有unknown数据 @@ -411,35 +401,24 @@ export class TabPaneSampleInstruction extends BaseElement { let cyclesSum = 0; let hoverInstructionsSum = 0; let hoverCyclesSum = 0; - // @ts-ignore - const unknownRelation = relationData.filter((relation) => relation.name.indexOf('unknown') > -1); + const unknownRelation = relationData.filter((relation) => relation['name'].indexOf('unknown') > -1); if (unknownRelation.length > 0) { unknownRelation.forEach((unknownItem) => { instructionSum = 0; cyclesSum = 0; hoverInstructionsSum = 0; hoverCyclesSum = 0; - // @ts-ignore const children = unknownItem['children']; for (const key in children) { - // @ts-ignore - const it = relationData.find((relation) => relation.name === key); - // @ts-ignore + const it = relationData.find((relation) => relation['name'] === key); instructionSum += it['instructions'] ?? 0; - // @ts-ignore cyclesSum += it['cycles'] ?? 0; - // @ts-ignore hoverInstructionsSum += it['hoverInstructions'] ?? 0; - // @ts-ignore hoverCyclesSum += it['hoverCycles'] ?? 0; } - // @ts-ignore unknownItem['instructions'] = instructionSum; - // @ts-ignore unknownItem['hoverInstructions'] = hoverInstructionsSum; - // @ts-ignore unknownItem['cycles'] = cyclesSum; - // @ts-ignore unknownItem['hoverCycles'] = hoverCyclesSum; }); } diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts index f9eef5e790efebb2080ad38b711be56be147986c..bb334e6cbedabf95e0d9336e009816d27e82b43c 100644 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts +++ b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts @@ -25,17 +25,17 @@ const barWidth = 2; // 柱子宽度 export class TabPaneSampleInstructionDistributions extends BaseElement { private instructionChartEle: HTMLCanvasElement | undefined | null; private ctx: CanvasRenderingContext2D | undefined | null; - private onReadableData: Array = []; + private onReadableData: Array = []; private hintContent = ''; //悬浮框内容 private floatHint!: HTMLDivElement | undefined | null; //悬浮框 private canvasScrollTop = 0; // tab页上下滚动位置 private isUpdateCanvas = false; - private cacheData: Array = []; + private cacheData: Array = []; private canvasX = -1; // 鼠标当前所在画布x坐标 private canvasY = -1; // 鼠标当前所在画布y坐标 private startX = 0; // 画布相对于整个界面的x坐标 private startY = 0; // 画布相对于整个界面的y坐标 - private hoverBar: unknown; + private hoverBar: any; private isChecked: boolean = false; private xCount = 0; //x轴刻度个数 private xMaxValue = 0; //x轴上数据最大值 @@ -105,8 +105,7 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { this.instructionChartEle!.onmouseleave = () => { this.hideTip(); }; - document.addEventListener('sample-popver-change', (e: unknown) => { - // @ts-ignore + document.addEventListener('sample-popver-change', (e: any) => { const select = Number(e.detail.select); this.isChecked = Boolean(select); this.calInstructionRangeCount(this.isChecked); @@ -136,10 +135,8 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { * @param canvasY * @returns */ - searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number): unknown { - // @ts-ignore + searchDataByCoord(nodes: any, canvasX: number, canvasY: number) { for (let i = 0; i < nodes.length; i++) { - // @ts-ignore const element = nodes[i]; if (this.isContains(element, canvasX, canvasY)) { return element; @@ -209,14 +206,8 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { } const detail = hoverNode!; this.hintContent = ` - ${ - // @ts-ignore - detail.instruct - }
- ${ - // @ts-ignore - parseFloat(detail.heightPer) - } + ${detail.instruct}
+ ${parseFloat(detail.heightPer)} `; } @@ -227,8 +218,7 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { * @param y * @returns */ - isContains(point: unknown, x: number, y: number): boolean { - // @ts-ignore + isContains(point: any, x: number, y: number): boolean { return x >= point.x && x <= point.x + 2 && point.y <= y && y <= point.y + point.height; } @@ -242,16 +232,12 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { const count = this.onReadableData.length; let instructions = {}; if (isCycles) { - // @ts-ignore - instructions = this.onReadableData.reduce((pre: unknown, current: unknown) => { - // @ts-ignore + instructions = this.onReadableData.reduce((pre: any, current: any) => { (pre[`${Math.ceil(current.cycles)}`] = pre[`${Math.ceil(current.cycles)}`] || []).push(current); return pre; }, {}); } else { - // @ts-ignore - instructions = this.onReadableData.reduce((pre: unknown, current: unknown) => { - // @ts-ignore + instructions = this.onReadableData.reduce((pre: any, current: any) => { (pre[`${Math.ceil(current.instructions)}`] = pre[`${Math.ceil(current.instructions)}`] || []).push(current); return pre; }, {}); @@ -264,8 +250,7 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { .map((i) => Number(i)) .reduce((pre, cur) => Math.max(pre, cur), 0) + 10; const yMaxValue = Object.values(instructions).reduce( - // @ts-ignore - (pre: number, cur: unknown) => Math.max(pre, Number((cur.length / count).toFixed(2))), + (pre: number, cur: any) => Math.max(pre, Number((cur.length / count).toFixed(2))), 0 ); this.yAvg = Number(((yMaxValue / 5) * 1.5).toFixed(2)) || yMaxValue; @@ -281,19 +266,16 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { * @param height * @param count */ - drawBar(instructionData: unknown, height: number, count: number): void { + drawBar(instructionData: any, height: number, count: number) { const yTotal = Number((this.yAvg * 5).toFixed(2)); const interval = Math.floor((height - paddingBottom) / 6); - // @ts-ignore for (const x in instructionData) { const xNum = Number(x); const xPosition = xStep + (xNum / (this.xCount * this.xAvg)) * (this.xCount * this.xSpacing) - barWidth / 2; - // @ts-ignore const yNum = Number((instructionData[x].length / count).toFixed(3)); const percent = Number((yNum / yTotal).toFixed(2)); const barHeight = (height - paddingBottom - interval) * percent; this.drawRect(xPosition, height - paddingBottom - barHeight, barWidth, barHeight); - // @ts-ignore const existX = this.cacheData.find((i) => i.instruct === x); if (!existX) { this.cacheData.push({ @@ -304,7 +286,6 @@ export class TabPaneSampleInstructionDistributions extends BaseElement { heightPer: parseFloat((yNum * 100).toFixed(2)), }); } else { - // @ts-ignore existX.x = xPosition; } } diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts index 46f3c26f582867887b70872cfd8f69232cda3790..1f17bd0f1088ba3ff096f3e598cd3762248cd94c 100644 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts +++ b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts @@ -28,8 +28,8 @@ export class TabPaneSampleInstructionSelection extends BaseElement { private instructionEle: HTMLCanvasElement | undefined | null; private ctx: CanvasRenderingContext2D | undefined | null; private textEle: HTMLSpanElement | undefined | null; - private instructionArray: Array = []; - private instructionData: Array = []; + private instructionArray: Array = []; + private instructionData: Array = []; private isUpdateCanvas = false; private canvasX = -1; // 鼠标当前所在画布x坐标 private canvasY = -1; // 鼠标当前所在画布y坐标 @@ -38,7 +38,7 @@ export class TabPaneSampleInstructionSelection extends BaseElement { private hintContent = ''; //悬浮框内容 private floatHint: HTMLDivElement | undefined | null; //悬浮框 private canvasScrollTop = 0; // tab页上下滚动位置 - private hoverSampleStruct: unknown | undefined; + private hoverSampleStruct: any | undefined; private isChecked: boolean = false; private maxDepth = 0; @@ -127,8 +127,7 @@ export class TabPaneSampleInstructionSelection extends BaseElement { this.instructionEle!.onmouseleave = () => { this.hideTip(); }; - document.addEventListener('sample-popver-change', (e: unknown) => { - // @ts-ignore + document.addEventListener('sample-popver-change', (e: any) => { const select = Number(e.detail.select); this.hoverSampleStruct = undefined; this.isChecked = Boolean(select); @@ -169,9 +168,7 @@ export class TabPaneSampleInstructionSelection extends BaseElement { this.ctx!.clearRect(0, 0, this.instructionEle!.width, this.instructionEle!.height); this.ctx!.beginPath(); for (const key in this.instructionArray) { - // @ts-ignore for (let i = 0; i < this.instructionArray[key].length; i++) { - // @ts-ignore const cur = this.instructionArray[key][i]; this.draw(this.ctx!, cur); } @@ -222,12 +219,8 @@ export class TabPaneSampleInstructionSelection extends BaseElement { if (!hoverNode) { return; } - // @ts-ignore this.hintContent = `${hoverNode.detail}(${hoverNode.name})
- ${ - // @ts-ignore - this.isChecked ? hoverNode.hoverCycles : hoverNode.hoverInstructions - } + ${this.isChecked ? hoverNode.hoverCycles : hoverNode.hoverInstructions} `; } @@ -255,8 +248,7 @@ export class TabPaneSampleInstructionSelection extends BaseElement { * @param y * @returns */ - isContains(frame: unknown, x: number, y: number): boolean { - // @ts-ignore + isContains(frame: any, x: number, y: number): boolean { return x >= frame.x && x <= frame.x + frame.width && frame.y <= y && y <= frame.y + frame.height; } @@ -269,46 +261,35 @@ export class TabPaneSampleInstructionSelection extends BaseElement { const clientWidth = this.instructionEle!.width; //将数据转换为层级结构 const instructionArray = this.instructionData - // @ts-ignore - .filter((item: unknown) => (isCycles ? item.cycles : item.instructions)) - .reduce((pre: unknown, cur: unknown) => { - // @ts-ignore + .filter((item: any) => (isCycles ? item.cycles : item.instructions)) + .reduce((pre: any, cur: any) => { (pre[`${cur.depth}`] = pre[`${cur.depth}`] || []).push(cur); return pre; }, {}); - // @ts-ignore for (const key in instructionArray) { - // @ts-ignore for (let i = 0; i < instructionArray[key].length; i++) { - // @ts-ignore const cur = instructionArray[key][i]; //第一级节点直接将宽度设置为容器宽度 if (key === '0') { this.setSampleFrame(cur, clientWidth, 0); } else { //获取上一层级节点数据 - // @ts-ignore const preList = instructionArray[Number(key) - 1]; //获取当前节点的父节点 const parentNode = preList.find((node: SampleStruct) => node.name === cur.parentName); //计算当前节点下指令数之和 用于计算每个节点所占的宽度比 const total = isCycles - ? // @ts-ignore - instructionArray[key] - // @ts-ignore - .filter((i: unknown) => i.parentName === parentNode.name) + ? instructionArray[key] + .filter((i: any) => i.parentName === parentNode.name) .reduce((pre: number, cur: SampleStruct) => pre + cur.cycles!, 0) - : // @ts-ignore - instructionArray[key] - // @ts-ignore - .filter((i: unknown) => i.parentName === parentNode.name) + : instructionArray[key] + .filter((i: any) => i.parentName === parentNode.name) .reduce((pre: number, cur: SampleStruct) => pre + cur.instructions!, 0); const curWidth = isCycles ? cur.cycles : cur.instructions; const width = Math.floor(parentNode.frame.width * (curWidth / total)); if (i === 0) { this.setSampleFrame(cur, width, parentNode.frame.x); } else { - // @ts-ignore const preNode = instructionArray[key][i - 1]; preNode.parentName === parentNode.name ? this.setSampleFrame(cur, width, preNode.frame.x + preNode.frame.width) @@ -317,16 +298,12 @@ export class TabPaneSampleInstructionSelection extends BaseElement { } } } - // @ts-ignore this.instructionArray = instructionArray; this.ctx!.clearRect(0, 0, this.instructionEle!.width, this.instructionEle!.height); this.ctx!.beginPath(); - // @ts-ignore for (const key in instructionArray) { - // @ts-ignore for (let i = 0; i < instructionArray[key].length; i++) { - // @ts-ignore const cur = instructionArray[key][i]; this.draw(this.ctx!, cur); } @@ -356,12 +333,9 @@ export class TabPaneSampleInstructionSelection extends BaseElement { * @param canvasY * @returns */ - searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number): unknown { - // @ts-ignore + searchDataByCoord(nodes: any, canvasX: number, canvasY: number) { for (const key in nodes) { - // @ts-ignore for (let i = 0; i < nodes[key].length; i++) { - // @ts-ignore const cur = nodes[key][i]; if (this.isContains(cur.frame, canvasX, canvasY)) { return cur; @@ -385,13 +359,12 @@ export class TabPaneSampleInstructionSelection extends BaseElement { const textColor = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', data.depth!, ColorUtils.FUNC_COLOR.length)]; ctx.lineWidth = 0.4; - // @ts-ignore if (this.hoverSampleStruct && data.name == this.hoverSampleStruct.name) { if (spApplication.dark) { ctx.strokeStyle = '#fff'; } else { ctx.strokeStyle = '#000'; - } + } } else { if (spApplication.dark) { ctx.strokeStyle = '#000'; @@ -411,38 +384,27 @@ export class TabPaneSampleInstructionSelection extends BaseElement { * @param instructionData * @returns */ - getAvgInstructionData(instructionData: Array): unknown[] { - // @ts-ignore + getAvgInstructionData(instructionData: Array) { const length = instructionData[0].property.length; - // @ts-ignore - const knowData = instructionData.filter((instruction) => instruction.name.indexOf('unknown') < 0); + const knowData = instructionData.filter((instruction) => instruction['name'].indexOf('unknown') < 0); knowData.forEach((instruction) => { - // @ts-ignore if (instruction.property.length > 0) { - // @ts-ignore - const totalInstruction = instruction.property.reduce( - (pre: number, cur: SampleStruct) => pre + Math.ceil(cur.instructions!), + const totalInstruction = instruction['property'].reduce( + (pre: number, cur: SampleStruct) => pre + Math.ceil(cur['instructions']!), 0 ); - // @ts-ignore - const totalCycles = instruction.property.reduce( - (pre: number, cur: SampleStruct) => pre + Math.ceil(cur.cycles!), + const totalCycles = instruction['property'].reduce( + (pre: number, cur: SampleStruct) => pre + Math.ceil(cur['cycles']!), 0 ); - // @ts-ignore - instruction.instructions = Math.ceil(totalInstruction / length) || 1; - // @ts-ignore - instruction.cycles = Math.ceil(totalCycles / length) || 1; - // @ts-ignore - instruction.hoverInstructions = Math.ceil(totalInstruction / length); - // @ts-ignore - instruction.hoverCycles = Math.ceil(totalCycles / length); - // @ts-ignore - this.maxDepth = Math.max(this.maxDepth, instruction.depth); + instruction['instructions'] = Math.ceil(totalInstruction / length) || 1; + instruction['cycles'] = Math.ceil(totalCycles / length) || 1; + instruction['hoverInstructions'] = Math.ceil(totalInstruction / length); + instruction['hoverCycles'] = Math.ceil(totalCycles / length); + this.maxDepth = Math.max(this.maxDepth, instruction['depth']); } }); - // @ts-ignore - const unknownData = instructionData.filter((instruction) => instruction.name.indexOf('unknown') > -1); + const unknownData = instructionData.filter((instruction) => instruction['name'].indexOf('unknown') > -1); let instructionSum = 0; let cyclesSum = 0; let hoverInstructionsSum = 0; @@ -452,27 +414,17 @@ export class TabPaneSampleInstructionSelection extends BaseElement { cyclesSum = 0; hoverInstructionsSum = 0; hoverCyclesSum = 0; - // @ts-ignore - for (const key in unknown.children) { - // @ts-ignore - const child = instructionData.find((instruction) => instruction.name === key); - // @ts-ignore - instructionSum += child.instructions ?? 0; - // @ts-ignore - cyclesSum += child.cycles ?? 0; - // @ts-ignore - hoverInstructionsSum += child.hoverInstructions ?? 0; - // @ts-ignore - hoverCyclesSum += child.hoverCycles ?? 0; + for (const key in unknown['children']) { + const child = instructionData.find((instruction) => instruction['name'] === key); + instructionSum += child['instructions'] ?? 0; + cyclesSum += child['cycles'] ?? 0; + hoverInstructionsSum += child['hoverInstructions'] ?? 0; + hoverCyclesSum += child['hoverCycles'] ?? 0; } - // @ts-ignore - unknown.instructions = instructionSum; - // @ts-ignore - unknown.cycles = cyclesSum; - // @ts-ignore - unknown.hoverInstructions = hoverInstructionsSum; - // @ts-ignore - unknown.hoverCycles = hoverCyclesSum; + unknown['instructions'] = instructionSum; + unknown['cycles'] = cyclesSum; + unknown['hoverInstructions'] = hoverInstructionsSum; + unknown['hoverCycles'] = hoverCyclesSum; }); return instructionData; } diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts index 55f13292d3e3b91bd14a7ba56b68bf850a3544ff..f2ff377e1c299fd2b39856445ffd0ba7a607c33c 100644 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts +++ b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts @@ -130,7 +130,7 @@ export class TabPaneSampleInstructionTotalTime extends BaseElement { * @param canvasY * @returns */ - searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number): unknown { + searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number) { // @ts-ignore for (let i = 0; i < nodes.length; i++) { // @ts-ignore @@ -261,7 +261,7 @@ export class TabPaneSampleInstructionTotalTime extends BaseElement { * @param height * @param count */ - drawBar(instructionData: unknown, height: number, count: number): void { + drawBar(instructionData: unknown, height: number, count: number) { const yTotal = Number((this.yAvg * 5).toFixed(2)); const interval = Math.floor((height - paddingBottom) / 6); // @ts-ignore for (const x in instructionData) { diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts index 006443bbbcc436177c8ebe671eff112ba5bcf923..33ccb43bbf46777e8e870b57309690de07c3682e 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneBoxChild.ts @@ -55,8 +55,8 @@ export class TabPaneBoxChild extends BaseElement { getDataByDB(val: BoxJumpParam): void { this.boxChildTbl!.loading = true; - getTabBoxChildData(val.leftNs, val.rightNs, val.cpus, val.state, val.processId, val.threadId).then( - (result): void => { + getTabBoxChildData(val.leftNs, val.rightNs, val.cpus, val.state, val.processId, + val.threadId, val.traceId).then((result): void => { this.boxChildTbl!.loading = false; if (result.length !== null && result.length > 0) { result.map((e) => { diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts index e21d0f458b3ec10fc9d84bb8f6693c66e0bc15ba..535db78cd0c8fffe80cc9e53cfe368fff3d820bb 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByProcess.ts @@ -46,7 +46,8 @@ export class TabPaneCpuByProcess extends BaseElement { this.cpuByProcessTbl!.recycleDataSource = []; this.cpuByProcessTbl!.loading = true; // @ts-ignore - getTabCpuByProcess(cpuByProcessValue.cpus, cpuByProcessValue.leftNs, cpuByProcessValue.rightNs).then((result) => { + getTabCpuByProcess(cpuByProcessValue.cpus, cpuByProcessValue.leftNs, // @ts-ignore + cpuByProcessValue.rightNs, cpuByProcessValue.traceId).then((result): void => { this.cpuByProcessTbl!.loading = false; if (result !== null && result.length > 0) { log(`getTabCpuByProcess size :${result.length}`); @@ -54,7 +55,7 @@ export class TabPaneCpuByProcess extends BaseElement { let sumOcc = 0; for (let e of result) { //@ts-ignore - let process = Utils.PROCESS_MAP.get(e.pid); //@ts-ignore + let process = Utils.getInstance().getProcessMap(cpuByProcessValue.traceId).get(e.pid); //@ts-ignore e.process = !process || process.length === 0 ? '[NULL]' : process; //@ts-ignore sumWall += e.wallDuration; //@ts-ignore sumOcc += e.occurrences; //@ts-ignore diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts index 69aa8ce5e10fe25f67d5299f23543098c33d100f..128bc443206e6c8ec3d5fa28f7df279a07365be1 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuByThread.ts @@ -436,9 +436,9 @@ export class TabPaneCpuByThread extends BaseElement { private createThread(e: unknown, cpuByThreadValue: unknown, map: Map): void { // @ts-ignore - let process = Utils.PROCESS_MAP.get(e.pid); + let process = Utils.getInstance().getProcessMap(cpuByThreadValue.traceId).get(e.pid); // @ts-ignore - let thread = Utils.THREAD_MAP.get(e.tid); + let thread = Utils.getInstance().getThreadMap(cpuByThreadValue.traceId).get(e.tid); let cpuByThreadObject: unknown = { // @ts-ignore tid: e.tid, diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts index fe6e6e6bac985412df3d953c8c1223b57420ee3c..8ee789e3509d2d05746858ae511162b085d4c181 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneCpuUsage.ts @@ -39,9 +39,9 @@ export class TabPaneCpuUsage extends BaseElement { this.cpuUsageTbl!.loading = true; Promise.all([ // @ts-ignore - getTabCpuUsage(cpuUsageValue.cpus, cpuUsageValue.leftNs, cpuUsageValue.rightNs), + getTabCpuUsage(cpuUsageValue.cpus, cpuUsageValue.leftNs, cpuUsageValue.rightNs, cpuUsageValue.traceId), // @ts-ignore - getTabCpuFreq(cpuUsageValue.cpus, cpuUsageValue.leftNs, cpuUsageValue.rightNs), + getTabCpuFreq(cpuUsageValue.cpus, cpuUsageValue.leftNs, cpuUsageValue.rightNs, cpuUsageValue.traceId), ]).then((result): void => { this.cpuUsageTbl!.loading = false; let usages = result[0]; diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts b/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts index 1a0055536af2d93181a38dd4290f59580e789f5e..59bb7ef9a8cebfded17c2c371c46e33d158301c3 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts @@ -35,7 +35,7 @@ export class TabPanePTS extends BaseElement { this.ptsRange!.textContent = // @ts-ignore `Selected range: ${parseFloat(((ptsValue.rightNs - ptsValue.leftNs) / 1000000.0).toFixed(5))} ms`; // @ts-ignore - this.getDataByPTS(ptsValue.leftNs, ptsValue.rightNs, ptsValue.cpus); + this.getDataByPTS(ptsValue.leftNs, ptsValue.rightNs, ptsValue.cpus, ptsValue.traceId); } initElements(): void { @@ -44,9 +44,9 @@ export class TabPanePTS extends BaseElement { this.ptsTbl!.itemTextHandleMap.set('title', Utils.transferPTSTitle); } - getDataByPTS(ptsLeftNs: number, ptsRightNs: number, cpus: Array): void { + getDataByPTS(ptsLeftNs: number, ptsRightNs: number, cpus: Array, traceId?: string): void { this.ptsTbl!.loading = true; - sliceSPTSender(ptsLeftNs, ptsRightNs, cpus, 'spt-getPTS').then((res): void => { + sliceSPTSender(ptsLeftNs, ptsRightNs, cpus, 'spt-getPTS', traceId).then((res): void => { this.ptsTbl!.loading = false; this.ptsTbl!.recycleDataSource = res; //@ts-ignore diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts index c5c6cac3cdcd714565a18dc59b8772be57b7c0d2..29e7688d1d8cb31bbc1135c684c21985d1eeb24f 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts @@ -41,7 +41,7 @@ export class TabPaneSPT extends BaseElement { // @ts-ignore `Selected range: ${parseFloat(((sptValue.rightNs - sptValue.leftNs) / 1000000.0).toFixed(5))} ms`; // @ts-ignore - this.getDataBySPT(sptValue.leftNs, sptValue.rightNs, sptValue.cpus); + this.getDataBySPT(sptValue.leftNs, sptValue.rightNs, sptValue.cpus, sptValue.traceId); } initElements(): void { @@ -55,9 +55,9 @@ export class TabPaneSPT extends BaseElement { resizeObserver(this.parentElement!, this.sptTbl!); } - getDataBySPT(leftNs: number, rightNs: number, cpus: Array): void { + getDataBySPT(leftNs: number, rightNs: number, cpus: Array, traceId?: string): void { this.sptTbl!.loading = true; - sliceSPTSender(leftNs, rightNs, cpus, 'spt-getSPT').then((res): void => { + sliceSPTSender(leftNs, rightNs, cpus, 'spt-getSPT', traceId).then((res): void => { this.sptTbl!.loading = false; this.sptTbl!.recycleDataSource = res; //@ts-ignore diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts index fb80075608bbbd91289000dfbf339d24832b35cd..2d3c2435e55ef1aac3139878a2dc6a445c2bea8b 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts @@ -91,7 +91,7 @@ export class TabPaneSchedPriority extends BaseElement { // thread_state表中runnable数据的Map const runnableMap = new Map(); // @ts-ignore - sliceSPTSender(sptParam.leftNs, sptParam.rightNs, [], 'spt-getCpuPriorityByTime').then((res): void => { + sliceSPTSender(sptParam.leftNs, sptParam.rightNs, [], 'spt-getCpuPriorityByTime', sptParam.traceId).then(res => { for (const item of res) { //@ts-ignore if (['R', 'R+'].includes(item.state)) { @@ -119,7 +119,7 @@ export class TabPaneSchedPriority extends BaseElement { if (args) { strArg = args!.split(','); } - const slice = Utils.SCHED_SLICE_MAP.get(`${item.id}-${item.startTime}`); + const slice = Utils.getInstance().getSchedSliceMap(Utils.currentSelectTrace).get(`${item.id}-${item.startTime}`); if (slice) { const runningPriority = new Priority(); runningPriority.priority = slice.priority; @@ -142,7 +142,8 @@ export class TabPaneSchedPriority extends BaseElement { private async fetchAndProcessData(): Promise { if (this.strValueMap.size === 0) { - await queryThreadStateArgsByName('next_info').then((value): void => { + await queryThreadStateArgsByName('next_info', this.selectionParam?.traceId || undefined). + then((value): void => { for (const item of value) { this.strValueMap.set(item.argset, item.strValue); } diff --git a/ide/src/trace/component/trace/sheet/dma-fence/DmaFenceBean.ts b/ide/src/trace/component/trace/sheet/dma-fence/DmaFenceBean.ts new file mode 100644 index 0000000000000000000000000000000000000000..8d448f951022025896a1cb7401e5c5eb8b6eb2b2 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/dma-fence/DmaFenceBean.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 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. + */ +export class DmaFenceDataBean { + cat: string = ''; + context: number = 0; + driver: string = ''; + dur: number = 0; + endTime: number = 0; + id: number = 0; + seqno: number = 0; + startTime: number = 0; + timeline: string = ''; + status: boolean = false +} + +export class DmaFenceTreeBean { + name: string = ''; + dur: number = 0; + average: number = 0; + occurrences: number = 0; + children?: DmaFenceTreeBean[] = []; + status: boolean = false; +} + +export class DmaFenceStringBean { + name: string = ''; + dur: string = ''; + average: string = ''; + occurrences: string = ''; + children?: DmaFenceStringBean[] = []; + status: boolean = false; +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/dma-fence/TabPaneDmaFenceSelect.ts b/ide/src/trace/component/trace/sheet/dma-fence/TabPaneDmaFenceSelect.ts new file mode 100644 index 0000000000000000000000000000000000000000..69292202c9ea2bcaa17ace7b545c12a3fdda5fb0 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/dma-fence/TabPaneDmaFenceSelect.ts @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2024 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'; +import { type LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; +import { type SelectionParam } from '../../../../bean/BoxSelection'; +import { resizeObserver } from '../SheetUtils'; +import { queryDmaFenceData } from '../../../../database/sql/dmaFence.sql'; +import { DmaFenceDataBean, DmaFenceTreeBean, DmaFenceStringBean } from './DmaFenceBean' + +@element('tabpane-dmafrence') +export class TabPaneDmaFence extends BaseElement { + private dmaFenceTbl: LitTable | null | undefined; + private currentSelectionParam: SelectionParam | undefined; + private timeSelection: HTMLLabelElement | null | undefined; + private finaldmaFenceData: Array = []; + private sortKey: string = 'name'; + private sortType: number = 0; + + set data(dmaFenceValue: SelectionParam) { + if (this.currentSelectionParam === dmaFenceValue) { + return; + }; + this.currentSelectionParam = dmaFenceValue; + this.dmaFenceTbl!.recycleDataSource = []; + this.dmaFenceTbl!.loading = true; + //@ts-ignore + this.dmaFenceTbl?.shadowRoot?.querySelector('.table')?.style?.height = this.parentElement!.clientHeight - 45 + 'px'; + queryDmaFenceData(dmaFenceValue.leftNs, dmaFenceValue.rightNs, dmaFenceValue.dmaFenceNameData).then((result: Array) => { + if (result !== null && result.length > 0) { + this.dmaFenceTbl!.loading = false; + let resultList: Array = JSON.parse(JSON.stringify(result)); + this.finaldmaFenceData = this.createTree(resultList); + this.timeSelection!.innerHTML = + 'Selection start: ' + (resultList[0].startTime / 1000000).toFixed(3) + ' ms' + '     ' + 'Selection extent: ' + ((resultList[resultList.length - 1].endTime / 1000000) - (resultList[0].startTime / 1000000)).toFixed(3) + ' ms'; + this.sortByColumn(this.sortKey, this.sortType, false); + } else { + this.dmaFenceTbl!.recycleDataSource = []; + this.dmaFenceTbl!.loading = false; + this.timeSelection!.innerHTML = + 'Selection start: ' + 0 + ' ms' + '     ' + 'Selection extent: ' + 0 + ' ms'; + } + }) + } + + private createTree(data: Array): Array { + const treeMap = new Map }>(); + data.forEach(item => { + const timeline = item.timeline; + const nameBase = item.cat.startsWith('dma_fence_signaled') ? 'fence_signal' : item.cat.split('dma_')[1]; + const name = `${nameBase}(${item.seqno})`; + const durValue = item.dur / 1000000; + + let timelineRecord = treeMap.get(timeline); + if (!timelineRecord) { + timelineRecord = { + dur: 0, + occurrences: 0, + children: [] + }; + treeMap.set(timeline, timelineRecord); + } + + let node = timelineRecord.children.find(child => child.name === name); + if (!node) { + node = { + name, + dur: durValue, + occurrences: 1, + average: durValue, + status: item.status, + }; + timelineRecord.children.push(node); + } else { + node.dur += durValue; + node.occurrences += 1; + node.average = node.dur / node.occurrences; + } + timelineRecord.dur += durValue; + timelineRecord.occurrences += 1; + }); + const root: DmaFenceTreeBean = { + name: 'totals', + dur: 0, + occurrences: 0, + children: [], + average: 0, + status: false + }; + + // 遍历treeMap来创建子节点,并按timeline分组 + treeMap.forEach((timelineRecord, timeline) => { + const timelineAverage = timelineRecord.dur / timelineRecord.occurrences; + const timelineNode: DmaFenceTreeBean = { + name: timeline, + dur: timelineRecord.dur, + occurrences: timelineRecord.occurrences, + average: timelineAverage, + children: timelineRecord.children, + status: false + }; + root.dur += timelineNode.dur; + root.occurrences += timelineNode.occurrences; + + root.children!.push(timelineNode); + }); + root.average = root.occurrences > 0 ? root.dur / root.occurrences : 0; + let rootList: Array = this.convertString([root]); + return rootList; + } + + private convertString(data: Array): Array { + const result: Array = []; + data.forEach(item => { + const stringBean: DmaFenceStringBean = { + name: item.name, + dur: item.dur.toFixed(3), + average: item.average.toFixed(3), + occurrences: String(item.occurrences), + children: item.children ? this.convertString(item.children) : undefined, + status: item.status + }; + result.push(stringBean); + }); + return result; + } + + private sortByColumn(key: string, type: number, isExpand: boolean) { + let sortObject = JSON.parse(JSON.stringify(this.finaldmaFenceData)); + let sortList: Array = []; + sortList.push(sortObject[0]); + if (type === 0) { + this.dmaFenceTbl!.recycleDataSource = this.finaldmaFenceData; + this.expandFunction(isExpand, this.finaldmaFenceData); + return; + } else { + sortList.forEach((item) => { + if (item.children) { + item.children.forEach((child) => { + if (child.children) { + child.children.sort((a, b) => { + let aValue: number | string, bValue: number | string; + if (key === 'name') { + aValue = a[key]; + bValue = b[key]; + } else { + // @ts-ignore + aValue = parseFloat(a[key]); + // @ts-ignore + bValue = parseFloat(b[key]); + } + if (typeof aValue === 'string' && typeof bValue === 'string') { + return type === 1 ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); + } else if (typeof aValue === 'number' && typeof bValue === 'number') { + return type === 1 ? aValue - bValue : bValue - aValue; + } else { + return 0; + } + }); + } + }); + } + }); + this.dmaFenceTbl!.recycleDataSource = sortList; + this.expandFunction(isExpand, sortList); + } + } + + private expandFunction(isExpand: boolean, list: Array) { + if (isExpand) { + this.dmaFenceTbl!.setStatus(list, true); + this.dmaFenceTbl!.recycleDs = this.dmaFenceTbl!.meauseTreeRowElement(list, RedrawTreeForm.Expand); + } + } + + initElements(): void { + this.dmaFenceTbl = this.shadowRoot?.querySelector('#tb-dmafence-slices'); + this.timeSelection = this.shadowRoot?.querySelector('#time-selection'); + this.dmaFenceTbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key; + // @ts-ignore + this.sortType = evt.detail.sort; + // @ts-ignore + this.sortByColumn(evt.detail.key, evt.detail.sort, true); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.dmaFenceTbl!); + } + + initHtml(): string { + return ` + + + + + + + + + + + + + `; + } + +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts b/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts index cc8e538bc18d0e867a189d83419419778bbf30e2..fc5f379c3b474636fdcf59b58e9c2538a40a0cb8 100644 --- a/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts +++ b/ide/src/trace/component/trace/sheet/energy/TabPaneEnergyAnomaly.ts @@ -24,11 +24,16 @@ import { queryAnomalyDetailedData } from '../../../../database/sql/ProcessThread @element('tabpane-anomaly-details') export class TabPaneEnergyAnomaly extends BaseElement { - private tblAnomaly: LitTable | null | undefined; private static KEY_INDEX: number = 2; private static VALUE_INDEX: number = 3; + private tblAnomaly: LitTable | null | undefined; + private currentSelection: SelectionParam | undefined; set data(selectionAnomaly: SelectionParam) { + if (selectionAnomaly === this.currentSelection) { + return; + } + this.currentSelection = selectionAnomaly; let div: HTMLElement | null | undefined = this?.shadowRoot?.querySelector('#anomaly-details'); let htmlText = ''; if (selectionAnomaly) { diff --git a/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts b/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts index 725d0baecf2f252c9ed4ca236293d46c395562c7..6ad61fe2b2a5e73b7e87aa2819b09070c871eb34 100644 --- a/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts +++ b/ide/src/trace/component/trace/sheet/energy/TabPaneSystemDetails.ts @@ -326,7 +326,7 @@ export class TabPaneSystemDetails extends BaseElement { if (i > -1) { // @ts-ignore fillMap.set(leftMap.get(filterData.pid), filterData); - watchIndex.splice(i); + delete watchIndex[i]; // @ts-ignore leftMap.delete(filterData.pid); } @@ -366,7 +366,7 @@ export class TabPaneSystemDetails extends BaseElement { if (i > -1) { // @ts-ignore fillMap.set(leftMap.get(filterData.message), filterData); - watchIndex.splice(i); + delete watchIndex[i]; // @ts-ignore leftMap.delete(filterData.message); } 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 424789f9588eca4d9d07e270b32cdc898335d7bc..8668b5dac8730c839895a8a45cdcf36bf9efb600 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneCallTree.ts @@ -394,7 +394,7 @@ export class TabPaneCallTree extends BaseElement { if (this.callTreeSelectedData && !this.callTreeSelectedData.canCharge) { return; } // @ts-ignore - if (this.callTreeSelectedData !== undefined && this.callTreeSelectedData.libName !== '') { + if (this.callTreeSelectedData !== undefined && this.callTreeSelectedData.lib !== '') { this.handleLibraryCase(data, callTreeFuncArgs); } else { return; @@ -408,10 +408,10 @@ export class TabPaneCallTree extends BaseElement { private handleLibraryCase(data: unknown, callTreeFuncArgs: unknown[]): void { // @ts-ignore - this.callTreeFilter!.addDataMining({ name: this.callTreeSelectedData.libName }, data.item); + this.callTreeFilter!.addDataMining({ name: this.callTreeSelectedData.lib }, data.item); callTreeFuncArgs.push({ funcName: 'splitTree', // @ts-ignore - funcArgs: [this.callTreeSelectedData.libName, false, false], + funcArgs: [this.callTreeSelectedData.lib, false, false], }); } 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 78f3f44418046e1c79d9dff9b6b5f0105472743c..caba7168a4bbbc7ef92c36fca1b8bf2bc28727ab 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemCalltree.ts @@ -329,7 +329,7 @@ export class TabpaneFilesystemCalltree extends BaseElement { if (this.fsCallTreeCurrentSelectedData && !this.fsCallTreeCurrentSelectedData.canCharge) { return; } // @ts-ignore - if (this.fsCallTreeCurrentSelectedData !== undefined && this.fsCallTreeCurrentSelectedData.libName !== '') { + if (this.fsCallTreeCurrentSelectedData !== undefined && this.fsCallTreeCurrentSelectedData.lib !== '') { this.handleLibraryCase(data, fsCallTreeFuncArgs); } else { return; @@ -352,10 +352,10 @@ export class TabpaneFilesystemCalltree extends BaseElement { private handleLibraryCase(data: unknown, fsCallTreeFuncArgs: unknown[]): void { // @ts-ignore - this.fsCallTreeFilter!.addDataMining({ name: this.fsCallTreeCurrentSelectedData.libName }, data.item); + this.fsCallTreeFilter!.addDataMining({ name: this.fsCallTreeCurrentSelectedData.lib }, data.item); fsCallTreeFuncArgs.push({ funcName: 'splitTree', // @ts-ignore - funcArgs: [this.fsCallTreeCurrentSelectedData.libName, false, false], + funcArgs: [this.fsCallTreeCurrentSelectedData.lib, false, false], }); } diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts index 9832d84bf166abe32256db4fc0a6784cf57dca36..d0aaebae89c20ec4776d8e2ffb1cb5c98b0fb657 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatistics.ts @@ -231,8 +231,6 @@ export class TabPaneFileStatistics extends BaseElement { } else if (this.fileStatisticsSortType === 2) { // @ts-ignore return fileStatisticsB.node[key] - fileStatisticsA.node[key]; - } else { - return 0; } }); // @ts-ignore fileStatisticsAllNode.children.forEach((item: unknown): void => { @@ -244,8 +242,6 @@ export class TabPaneFileStatistics extends BaseElement { } else if (this.fileStatisticsSortType === 2) { // @ts-ignore return fileStatisticsB.node[key] - fileStatisticsA.node[key]; - } else { - return 0; } }); }); diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatisticsAnalysis.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatisticsAnalysis.ts index fb0cb56ed970cda86aa1fc6fa50a945cddcb2b06..8b957285237a1622bafb57cd9bb5a9f7a4a910ad 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatisticsAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneFilesystemStatisticsAnalysis.ts @@ -247,10 +247,10 @@ export class TabPaneFilesystemStatisticsAnalysis extends BaseElement { if (fileSystemTable === showTable) { initSort(fileSystemTable!, this.fsSortColumn, this.fsSortType); fileSystemTable.style.display = 'grid'; - fileSystemTable.setAttribute('hideDownload', ''); + fileSystemTable!.removeAttribute('hideDownload'); } else { fileSystemTable!.style.display = 'none'; - fileSystemTable!.removeAttribute('hideDownload'); + fileSystemTable.setAttribute('hideDownload', ''); } } } diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts index 0ce9dafb63333345db0e9e305262d35ba37d7907..3bbf62bbb67522f5a9805e1e40e23c028fcff72e 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneIOTierStatistics.ts @@ -323,15 +323,13 @@ export class TabPaneIOTierStatistics extends BaseElement { sortTable(allNode: unknown, key: string): void { // @ts-ignore - allNode.children.sort((ioTierStatNodeA: unknown, ioTierStatNodeB: unknown): number => { + allNode.children.sort((ioTierStatNodeA: unknown, ioTierStatNodeB: unknown) => { if (this.ioTierStatisticsSortType === 1) { // @ts-ignore return ioTierStatNodeA.node[key] - ioTierStatNodeB.node[key]; } else if (this.ioTierStatisticsSortType === 2) { // @ts-ignore return ioTierStatNodeB.node[key] - ioTierStatNodeA.node[key]; - } else { - return 0; } }); // @ts-ignore allNode.children.forEach((item: unknown): void => { @@ -343,8 +341,6 @@ export class TabPaneIOTierStatistics extends BaseElement { } else if (this.ioTierStatisticsSortType === 2) { // @ts-ignore return ioTierStatItemB.node[key] - ioTierStatItemA.node[key]; - } else { - return 0; } }); // @ts-ignore item.children.forEach((ioTierStatItem: unknown): void => { @@ -356,8 +352,6 @@ export class TabPaneIOTierStatistics extends BaseElement { } else if (this.ioTierStatisticsSortType === 2) { // @ts-ignore return ioTierStatItemB.node[key] - ioTierStatItemA.node[key]; - } else { - return 0; } }); }); diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts index 7f061f1edc67533fd9d667d81d0852cdad210076..5861ada5d75720030db9c09c6bba217eca59220b 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatistics.ts @@ -29,21 +29,19 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { private vmStatisticsSelectionParam: SelectionParam | null | undefined; private vmStatisticsProgressEL: LitProgressBar | null | undefined; private vmStatisticsFilter: TabPaneFilter | null | undefined; - private loadingPage: unknown; + private loadingPage: any; private loadingList: number[] = []; - private vmStatisticsSource: Array = []; + private vmStatisticsSource: Array = []; private vmStatisticsSortKey: string = ''; private vmStatisticsSortType: number = 0; - private vmStatisticsResultData: Array = []; + private vmStatisticsResultData: Array = []; - set data(vmStatisticsSelection: SelectionParam | unknown) { + set data(vmStatisticsSelection: SelectionParam | any) { if (vmStatisticsSelection === this.vmStatisticsSelectionParam) { return; } this.vmStatisticsProgressEL!.loading = true; - // @ts-ignore this.loadingPage.style.visibility = 'visible'; - // @ts-ignore this.vmStatisticsSelectionParam = vmStatisticsSelection; // @ts-ignore this.vmStatisticsTbl!.shadowRoot!.querySelector('.table').style.height = `${ @@ -73,8 +71,34 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { } else { this.sortStatus(this.vmStatisticsResultData, 'type', 'ipid'); } - this.vmStatisticsTbl!.shadowRoot!.querySelector('div > div.thead > div > div:nth-child(1) > label')!.textContent = - type === 'operation' ? 'Process/Thread/Operation' : 'Operation/Process/Thread'; + const labels = this.vmStatisticsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label') as NodeListOf; + labels.forEach((label, index) => { + if (type === 'operation') { + switch (index) { + case 0: + label.textContent = 'Process'; + break; + case 1: + label.textContent = '/Thread'; + break; + case 2: + label.textContent = '/Operation'; + break; + } + } else { + switch (index) { + case 0: + label.textContent = 'Operation'; + break; + case 1: + label.textContent = '/Process'; + break; + case 2: + label.textContent = '/Thread'; + break; + } + } + }); }); } @@ -87,48 +111,36 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { this.parentElement!.clientHeight - 10 - 32 }px`; this.vmStatisticsTbl!.reMeauseHeight(); - // @ts-ignore this.loadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`; } }).observe(this.parentElement!); } - getInitData(initVmMemoryStatItem: unknown, nameTitle: unknown = 'pname', subtitle: unknown = null): unknown { + getInitData(initVmMemoryStatItem: any, nameTitle: any = 'pname', subtitle: any = null): any { // @ts-ignore let title = nameTitle === 'type' ? VM_TYPE_MAP[initVmMemoryStatItem[nameTitle]] : initVmMemoryStatItem[nameTitle]; return { - // @ts-ignore ...initVmMemoryStatItem, - // @ts-ignore title: title + (subtitle ? `(${initVmMemoryStatItem[subtitle]})` : ''), - // @ts-ignore allDuration: Utils.getProbablyTime(initVmMemoryStatItem.allDuration), - // @ts-ignore minDuration: Utils.getProbablyTime(initVmMemoryStatItem.minDuration), - // @ts-ignore maxDuration: Utils.getProbablyTime(initVmMemoryStatItem.maxDuration), - // @ts-ignore avgDuration: Utils.getProbablyTime(initVmMemoryStatItem.avgDuration), - // @ts-ignore node: { ...initVmMemoryStatItem, children: [] }, }; } - queryDataByDB(vmMemoryStatParam: SelectionParam | unknown): void { + queryDataByDB(vmMemoryStatParam: SelectionParam | any): void { this.loadingList.push(1); this.vmStatisticsProgressEL!.loading = true; - // @ts-ignore this.loadingPage.style.visibility = 'visible'; getTabPaneVirtualMemoryStatisticsData( - // @ts-ignore vmMemoryStatParam.leftNs + vmMemoryStatParam.recordStartNs, - // @ts-ignore vmMemoryStatParam.rightNs + vmMemoryStatParam.recordStartNs ).then((result) => { this.loadingList.splice(0, 1); if (this.loadingList.length === 0) { this.vmStatisticsProgressEL!.loading = false; - // @ts-ignore this.loadingPage.style.visibility = 'hidden'; } this.vmStatisticsResultData = JSON.parse(JSON.stringify(result)); @@ -136,10 +148,10 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { }); } - sortStatus(result: Array, firstLevel: string, secondLevel: string): void { - let vmMemoryStatFatherMap = new Map(); - let vmMemoryStatChildMap = new Map(); - let vmMemoryStatAllNode: unknown = { + sortStatus(result: Array, firstLevel: string, secondLevel: string): void { + let vmMemoryStatFatherMap = new Map(); + let vmMemoryStatChildMap = new Map(); + let vmMemoryStatAllNode: any = { title: 'All', count: 0, allDuration: 0, @@ -152,31 +164,21 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { this.processChildMap(vmMemoryStatChildMap, item, firstLevel, secondLevel); this.processFatherMap(vmMemoryStatFatherMap, item, firstLevel); if (idx === 0) { - // @ts-ignore vmMemoryStatAllNode.minDuration = item.minDuration; } else { - // @ts-ignore vmMemoryStatAllNode.minDuration = - // @ts-ignore vmMemoryStatAllNode.minDuration <= item.minDuration ? vmMemoryStatAllNode.minDuration : item.minDuration; } - // @ts-ignore vmMemoryStatAllNode.count += item.count; - // @ts-ignore vmMemoryStatAllNode.allDuration += item.allDuration; - // @ts-ignore vmMemoryStatAllNode.maxDuration = - // @ts-ignore vmMemoryStatAllNode.maxDuration >= item.maxDuration ? vmMemoryStatAllNode.maxDuration : item.maxDuration; }); this.handleFatherMap(vmMemoryStatFatherMap, firstLevel, vmMemoryStatChildMap, vmMemoryStatAllNode); - // @ts-ignore vmMemoryStatAllNode.avgDuration = vmMemoryStatAllNode.allDuration / vmMemoryStatAllNode.count; vmMemoryStatAllNode = this.getInitData(vmMemoryStatAllNode); - // @ts-ignore vmMemoryStatAllNode.title = 'All'; - // @ts-ignore vmMemoryStatAllNode.path = { type: null, tid: null, pid: null, value: 'All' }; this.vmStatisticsSource = result.length > 0 ? [vmMemoryStatAllNode] : []; if (this.vmStatisticsSortType !== 0 && result.length > 0) { @@ -185,19 +187,19 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { this.theadClick(this.vmStatisticsSource); this.vmStatisticsTbl!.recycleDataSource = this.vmStatisticsSource; } - private theadClick(res: Array): void { + private theadClick(res: Array): void { let labels = this.vmStatisticsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); if (labels) { for (let i = 0; i < labels.length; i++) { let label = labels[i].innerHTML; labels[i].addEventListener('click', (): void => { - if (label.includes('Operation') && i === 0) { + if (i === 0) { this.vmStatisticsTbl!.setStatus(res, false, 0, 1); this.vmStatisticsTbl!.recycleDs = this.vmStatisticsTbl!.meauseTreeRowElement(res, RedrawTreeForm.Retract); - } else if (label.includes('Process') && i === 1) { + } else if (i === 1) { this.vmStatisticsTbl!.setStatus(res, false, 0, 2); this.vmStatisticsTbl!.recycleDs = this.vmStatisticsTbl!.meauseTreeRowElement(res, RedrawTreeForm.Retract); - } else if (label.includes('Thread') && i === 2) { + } else if (i === 2) { this.vmStatisticsTbl!.setStatus(res, true); this.vmStatisticsTbl!.recycleDs = this.vmStatisticsTbl!.meauseTreeRowElement(res, RedrawTreeForm.Expand); } @@ -206,43 +208,36 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { } } private handleFatherMap( - vmMemoryStatFatherMap: Map, + vmMemoryStatFatherMap: Map, firstLevel: string, - vmMemoryStatChildMap: Map, - vmMemoryStatAllNode: unknown + vmMemoryStatChildMap: Map, + vmMemoryStatAllNode: any ): void { for (let ks of vmMemoryStatFatherMap.keys()) { let sp = vmMemoryStatFatherMap.get(ks); - // @ts-ignore sp!.children = []; - // @ts-ignore sp.avgDuration = sp.allDuration / sp.count; let vmMemoryStatNode = this.getInitData( sp, firstLevel === 'type' ? 'type' : 'pname', firstLevel === 'type' ? null : 'pid' ); - // @ts-ignore vmMemoryStatNode.path = { type: null, tid: null, pid: null, value: vmMemoryStatNode.title }; - // @ts-ignore vmMemoryStatNode.path[firstLevel === 'type' ? 'type' : 'pid'] = - // @ts-ignore vmMemoryStatNode[firstLevel === 'type' ? 'type' : 'pid']; this.handleChildMap(vmMemoryStatChildMap, ks, firstLevel, vmMemoryStatNode, sp); - // @ts-ignore vmMemoryStatAllNode.children.push(vmMemoryStatNode); } } private handleChildMap( - vmMemoryStatChildMap: Map, - ks: unknown, + vmMemoryStatChildMap: Map, + ks: any, firstLevel: string, - vmMemoryStatNode: unknown, - sp: unknown + vmMemoryStatNode: any, + sp: any ): void { for (let kst of vmMemoryStatChildMap.keys()) { - // @ts-ignore if (kst.startsWith(`${ks}_`)) { let spt = vmMemoryStatChildMap.get(kst); let data = this.getInitData( @@ -251,67 +246,45 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { firstLevel === 'type' ? 'pid' : 'tid' ); this.handleData(data, vmMemoryStatNode, firstLevel); - // @ts-ignore sp!.children.push(data); } } } - private handleData(data: unknown, vmMemoryStatNode: unknown, firstLevel: string): void { - // @ts-ignore + private handleData(data: any, vmMemoryStatNode: any, firstLevel: string): void { data.path = { type: null, tid: null, pid: null, - // @ts-ignore value: `All-${vmMemoryStatNode.title}-${data.title}`, }; - // @ts-ignore data.path[firstLevel === 'type' ? 'type' : 'pid'] = vmMemoryStatNode[firstLevel === 'type' ? 'type' : 'pid']; - // @ts-ignore data.path[firstLevel === 'type' ? 'pid' : 'tid'] = data[firstLevel === 'type' ? 'pid' : 'tid']; - // @ts-ignore - data.children.forEach((e: unknown) => { - // @ts-ignore + data.children.forEach((e: any) => { e.path = { type: null, tid: null, pid: null, - // @ts-ignore value: `All-${vmMemoryStatNode.title}-${data.title}-${e.title}`, }; - // @ts-ignore e.path[firstLevel === 'type' ? 'type' : 'pid'] = vmMemoryStatNode[firstLevel === 'type' ? 'type' : 'pid']; - // @ts-ignore e.path[firstLevel === 'type' ? 'pid' : 'tid'] = data[firstLevel === 'type' ? 'pid' : 'tid']; - // @ts-ignore e.path[firstLevel === 'type' ? 'tid' : 'type'] = e[firstLevel === 'type' ? 'tid' : 'type']; }); } - private processFatherMap(vmMemoryStatFatherMap: Map, item: unknown, firstLevel: string): void { - // @ts-ignore + private processFatherMap(vmMemoryStatFatherMap: Map, item: any, firstLevel: string): void { if (vmMemoryStatFatherMap.has(item[firstLevel])) { - // @ts-ignore let vmMemoryStatFatherObj = vmMemoryStatFatherMap.get(item[firstLevel]); - // @ts-ignore vmMemoryStatFatherObj.count += item.count; - // @ts-ignore vmMemoryStatFatherObj.allDuration += item.allDuration; - // @ts-ignore vmMemoryStatFatherObj.minDuration = - // @ts-ignore vmMemoryStatFatherObj.minDuration <= item.minDuration ? vmMemoryStatFatherObj.minDuration : item.minDuration; - // @ts-ignore vmMemoryStatFatherObj.maxDuration = - // @ts-ignore vmMemoryStatFatherObj.maxDuration >= item.maxDuration ? vmMemoryStatFatherObj.maxDuration : item.maxDuration; - // @ts-ignore vmMemoryStatFatherObj.children.push(this.getInitData(item)); } else { - // @ts-ignore vmMemoryStatFatherMap.set(item[firstLevel], { - // @ts-ignore ...item, children: [this.getInitData(item)], }); @@ -319,35 +292,24 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { } private processChildMap( - vmMemoryStatChildMap: Map, - item: unknown, + vmMemoryStatChildMap: Map, + item: any, firstLevel: string, secondLevel: string ): void { - // @ts-ignore if (vmMemoryStatChildMap.has(`${item[firstLevel]}_${item[secondLevel]}`)) { - // @ts-ignore let vmMemoryStatChildObj = vmMemoryStatChildMap.get(`${item[firstLevel]}_${item[secondLevel]}`); - // @ts-ignore vmMemoryStatChildObj.count += item.count; - // @ts-ignore vmMemoryStatChildObj.allDuration += item.allDuration; - // @ts-ignore vmMemoryStatChildObj.minDuration = - // @ts-ignore vmMemoryStatChildObj.minDuration <= item.minDuration ? vmMemoryStatChildObj.minDuration : item.minDuration; - // @ts-ignore vmMemoryStatChildObj.maxDuration = - // @ts-ignore vmMemoryStatChildObj.maxDuration >= item.maxDuration ? vmMemoryStatChildObj.maxDuration : item.maxDuration; - // @ts-ignore vmMemoryStatChildObj.children.push( this.getInitData(item, firstLevel === 'type' ? 'tname' : 'type', firstLevel === 'type' ? 'tid' : null) ); } else { - // @ts-ignore vmMemoryStatChildMap.set(`${item[firstLevel]}_${item[secondLevel]}`, { - // @ts-ignore ...item, children: [ this.getInitData(item, firstLevel === 'type' ? 'tname' : 'type', firstLevel === 'type' ? 'tid' : null), @@ -356,45 +318,28 @@ export class TabPaneVirtualMemoryStatistics extends BaseElement { } } - sortVmStatisticsTable(allNode: unknown, key: string): void { - // @ts-ignore - allNode.children.sort((vmStatNodeA: unknown, vmStatNodeB: unknown): number => { + sortVmStatisticsTable(allNode: any, key: string): void { + allNode.children.sort((vmStatNodeA: any, vmStatNodeB: any) => { if (this.vmStatisticsSortType === 1) { - // @ts-ignore return vmStatNodeA.node[key] - vmStatNodeB.node[key]; } else if (this.vmStatisticsSortType === 2) { - // @ts-ignore return vmStatNodeB.node[key] - vmStatNodeA.node[key]; - } else { - return 0; } }); - // @ts-ignore - allNode.children.forEach((item: unknown): void => { - // @ts-ignore - item.children.sort((vmStatNodeA: unknown, vmStatNodeB: unknown): number => { + allNode.children.forEach((item: any): void => { + item.children.sort((vmStatNodeA: any, vmStatNodeB: any) => { if (this.vmStatisticsSortType === 1) { - // @ts-ignore return vmStatNodeA.node[key] - vmStatNodeB.node[key]; } else if (this.vmStatisticsSortType === 2) { - // @ts-ignore return vmStatNodeB.node[key] - vmStatNodeA.node[key]; - } else { - return 0; } }); - // @ts-ignore - item.children.forEach((vmStatItem: unknown) => { - // @ts-ignore - vmStatItem.children.sort((vmStatItemA: unknown, vmStatItemB: unknown): number => { + item.children.forEach((vmStatItem: any) => { + vmStatItem.children.sort((vmStatItemA: any, vmStatItemB: any) => { if (this.vmStatisticsSortType === 1) { - // @ts-ignore return vmStatItemA.node[key] - vmStatItemB.node[key]; } else if (this.vmStatisticsSortType === 2) { - // @ts-ignore return vmStatItemB.node[key] - vmStatItemA.node[key]; - } else { - return 0; } }); }); diff --git a/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatisticsAnalysis.ts b/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatisticsAnalysis.ts index 155504f8a3630a8ef48d04d08e536f7d5c67141b..ea0f31af36e22f90bda3b42f839b37979eabb3ea 100644 --- a/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatisticsAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/file-system/TabPaneVirtualMemoryStatisticsAnalysis.ts @@ -247,10 +247,10 @@ export class TabPaneVirtualMemoryStatisticsAnalysis extends BaseElement { if (virtualMemoryTable === showTable) { initSort(virtualMemoryTable!, this.vmSortColumn, this.vmSortType); virtualMemoryTable.style.display = 'grid'; - virtualMemoryTable.setAttribute('hideDownload', ''); + virtualMemoryTable!.removeAttribute('hideDownload'); } else { virtualMemoryTable!.style.display = 'none'; - virtualMemoryTable!.removeAttribute('hideDownload'); + virtualMemoryTable.setAttribute('hideDownload', ''); } } } @@ -562,12 +562,6 @@ export class TabPaneVirtualMemoryStatisticsAnalysis extends BaseElement {
`; }, - angleClick: (it: Object): void => { - // @ts-ignore - if (it.tableName !== 'other') { - this.vmSoLevelClickEvent(it); - } - }, hoverHandler: (data): void => { if (data) { this.vmStatisticsAnalysisTableSo!.setCurrentHover(data); @@ -798,7 +792,7 @@ export class TabPaneVirtualMemoryStatisticsAnalysis extends BaseElement { durFormat: Utils.getProbablyTime(dur), duration: dur, }; - this.vmStatisticsAnalysisTypeData.push(vmTypeData); + this.vmStatisticsAnalysisTypeData.push(vmTypeData); }); // @ts-ignore this.vmStatisticsAnalysisTypeData.sort((a, b) => b.duration - a.duration); this.typeStatisticsData = this.totalDurationData(allDur); @@ -1011,6 +1005,9 @@ export class TabPaneVirtualMemoryStatisticsAnalysis extends BaseElement { `; }, + angleClick: (it): void => { + this.vmSoLevelClickEvent(it); + }, hoverHandler: (vmPieData): void => { if (vmPieData) { this.vmStatisticsAnalysisTableFunction!.setCurrentHover(vmPieData); @@ -1091,6 +1088,8 @@ export class TabPaneVirtualMemoryStatisticsAnalysis extends BaseElement { vmReleaseType = 'File Backed In'; } else if (type === 7) { vmReleaseType = 'Copy On Writer'; + } else { + vmReleaseType = 'Other'; } // @ts-ignore return vmReleaseType; diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts index a98bc0b29422385619baf53a0acfd66e20144f1d..0126dd5c553544ac897effe1080501752184d136 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts @@ -53,7 +53,9 @@ export class TabPaneFreqDataCut extends BaseElement { for (let i of processArr) { pidArr.push( new TabPaneFreqUsageConfig( - Utils.PROCESS_MAP.get(i) === null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, + Utils.getInstance().getProcessMap().get(i) === null + ? 'Process ' + i + : Utils.getInstance().getProcessMap().get(i) + ' ' + i, '', i, '', @@ -122,6 +124,14 @@ export class TabPaneFreqDataCut extends BaseElement { // @ts-ignore this.shadowRoot?.querySelector('#cycleQuery')!.style.display = 'none'; // @ts-ignore + this.shadowRoot?.querySelector('#dataCut')?.children[2].children[0].style.backgroundColor = '#fff'; + // @ts-ignore + this.shadowRoot?.querySelector('#dataCut')?.children[2].children[0].style.color = '#000'; + // @ts-ignore + this.shadowRoot?.querySelector('#dataCut')?.children[2].children[1].style.backgroundColor = '#fff'; + // @ts-ignore + this.shadowRoot?.querySelector('#dataCut')?.children[2].children[1].style.color = '#000'; + // @ts-ignore this.statisticsScatter!.config = undefined; this.parentElement!.style.overflow = 'hidden'; } @@ -176,7 +186,7 @@ export class TabPaneFreqDataCut extends BaseElement { if (needDeal.get(e.pid + '_' + e.tid) === undefined) { this.threadArr.push( new TabPaneFreqUsageConfig( - Utils.THREAD_MAP.get(e.tid) + ' ' + e.tid, + Utils.getInstance().getThreadMap().get(e.tid) + ' ' + e.tid, '', e.pid, e.tid, @@ -204,8 +214,14 @@ export class TabPaneFreqDataCut extends BaseElement { if (e.ts + e.dur > threadStatesParam.rightNs + threadStatesParam.recordStartNs) { e.dur = threadStatesParam.rightNs + threadStatesParam.recordStartNs - e.ts; } - e.process = Utils.PROCESS_MAP.get(e.pid) === null ? '[NULL]' : Utils.PROCESS_MAP.get(e.pid)!; - e.thread = Utils.THREAD_MAP.get(e.tid) === null ? '[NULL]' : Utils.THREAD_MAP.get(e.tid)!; + e.process = + Utils.getInstance().getProcessMap().get(e.pid) === null + ? '[NULL]' + : Utils.getInstance().getProcessMap().get(e.pid)!; + e.thread = + Utils.getInstance().getThreadMap().get(e.tid) === null + ? '[NULL]' + : Utils.getInstance().getThreadMap().get(e.tid)!; let arr: Array | undefined = needDeal.get(e.pid + '_' + e.tid); sum += e.dur; arr?.push(e); @@ -1189,6 +1205,7 @@ export class TabPaneFreqDataCut extends BaseElement { Number(threadArr[i].tid) === Number(totalData[j].tid) ) { totalData[j].thread = 'TotalData'; + totalData[j].flag = 't_cycle'; // @ts-ignore threadArr[i].children.unshift(totalData[j]); } @@ -1563,11 +1580,28 @@ export class TabPaneFreqDataCut extends BaseElement { this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { this.threadStatesTbl!.loading = true; // @ts-ignore + this.threadStatesDIV?.children[2].children[0].style.backgroundColor = '#666666'; + // @ts-ignore + this.threadStatesDIV?.children[2].children[0].style.color = '#fff'; + // @ts-ignore + this.threadStatesDIV?.children[2].children[1].style.backgroundColor = '#fff'; + // @ts-ignore + this.threadStatesDIV?.children[2].children[1].style.color = '#000'; + // @ts-ignore + this.dataSingleCut(this.threadStatesDIV?.children[0]!, this.threadStatesDIV?.children[1]!, this.initData); }); this.threadStatesDIV?.children[2].children[1].addEventListener('click', (e) => { this.threadStatesTbl!.loading = true; // @ts-ignore + this.threadStatesDIV?.children[2].children[1].style.backgroundColor = '#666666'; + // @ts-ignore + this.threadStatesDIV?.children[2].children[1].style.color = '#fff'; + // @ts-ignore + this.threadStatesDIV?.children[2].children[0].style.backgroundColor = '#fff'; + // @ts-ignore + this.threadStatesDIV?.children[2].children[0].style.color = '#000'; + // @ts-ignore this.dataLoopCut(this.threadStatesDIV?.children[0]!, this.threadStatesDIV?.children[1]!, this.initData); }); this.threadStatesDIV?.children[0].addEventListener('focus', (e) => { diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts index b871f6341869f8086332c58a83552a2c67b2604f..911f9628a8490614b792b5a01c1effc2c347a02c 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts @@ -75,7 +75,7 @@ export class TabPaneFreqUsage extends BaseElement { this.recursion(resultArr); this.result = JSON.parse(JSON.stringify(this.result)); mergeTotal(resultArr, fixTotal(this.result)); - this.fixedDeal(resultArr); + this.fixedDeal(resultArr, threadStatesParam.traceId); this.threadClick(resultArr); this.threadStatesTbl!.recycleDataSource = resultArr; this.threadStatesTbl!.loading = false; @@ -84,7 +84,7 @@ export class TabPaneFreqUsage extends BaseElement { /** * 递归整理数据小数位 */ - fixedDeal(arr: Array): void { + fixedDeal(arr: Array, traceId?: string | null): void { if (arr == undefined) { return; } @@ -104,15 +104,11 @@ export class TabPaneFreqUsage extends BaseElement { } if (arr[i].thread?.indexOf('P') !== -1) { trackId = Number(arr[i].thread?.slice(1)!); - arr[i].thread = - Utils.PROCESS_MAP.get(trackId) === null - ? 'Process ' + trackId - : Utils.PROCESS_MAP.get(trackId)! + ' ' + trackId; + arr[i].thread = `${ Utils.getInstance().getProcessMap(traceId).get(trackId) || 'Process' } ${trackId}`; } else if (arr[i].thread === 'summary data') { } else { trackId = Number(arr[i].thread!.split('_')[1]); - arr[i].thread = - Utils.THREAD_MAP.get(trackId) === null ? 'Thread ' + trackId : Utils.THREAD_MAP.get(trackId)! + ' ' + trackId; + arr[i].thread = `${ Utils.getInstance().getThreadMap(traceId).get(trackId) || 'Thread' } ${trackId}`; } if (arr[i].cpu < 0) { // @ts-ignore @@ -135,7 +131,7 @@ export class TabPaneFreqUsage extends BaseElement { arr[i].frequency = Number(arr[i].frequency) / FREQ_MUTIPLE; } } - this.fixedDeal(arr[i].children!); + this.fixedDeal(arr[i].children!, traceId); } } @@ -403,15 +399,6 @@ function returnObj( dur: item.dur, percent: (item.dur / sum) * PERCENT, }; - default: - return { - thread: item.pid + '_' + item.tid, - consumption: 0, - cpu: item.cpu, - frequency: 'unknown', - dur: item.dur, - percent: (item.dur / sum) * PERCENT, - }; } } diff --git a/ide/src/trace/component/trace/sheet/gpu-counter/TabPaneGpuCounter.ts b/ide/src/trace/component/trace/sheet/gpu-counter/TabPaneGpuCounter.ts new file mode 100644 index 0000000000000000000000000000000000000000..63908ef5521d46b57d30105b182b0e35d2d23e7e --- /dev/null +++ b/ide/src/trace/component/trace/sheet/gpu-counter/TabPaneGpuCounter.ts @@ -0,0 +1,79 @@ +/* + * 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'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { GpuCounter } from '../../../../bean/BoxSelection'; +import { GpuCounterStruct } from '../../../../database/ui-worker/ProcedureWorkerGpuCounter'; +import { resizeObserver } from '../SheetUtils'; + +@element('tabpane-gpu-counter') +export class TabPaneGpuCounter extends BaseElement { + private gpuCounterCounterTbl: LitTable | null | undefined; + private clockCounterSource: Array = []; + + set data(clickData: GpuCounterStruct) { + //@ts-ignore + this.gpuCounterCounterTbl?.shadowRoot?.querySelector('.table')?.style?.height = + this.parentElement!.clientHeight - 45 + 'px'; + this.getCounterData(clickData).then(); + } + + async getCounterData(clickData: GpuCounterStruct) { + let dataSource: Array = []; + let selectData = new GpuCounter(); + selectData.startNS = clickData.startNS!; + selectData.height = clickData.height!; + selectData.dur = clickData.dur!; + selectData.type = clickData.type!; + selectData.frame = clickData.frame!; + selectData.startTime = clickData.startTime!; + dataSource.push(selectData); + this.clockCounterSource = dataSource; + this.gpuCounterCounterTbl!.recycleDataSource = dataSource; + } + + initElements(): void { + this.gpuCounterCounterTbl = this.shadowRoot?.querySelector('#tb-counter'); + } + + + + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.gpuCounterCounterTbl!); + } + + initHtml(): string { + return ` + + + + + + + + `; + } +} diff --git a/ide/src/trace/component/trace/sheet/gpu-counter/TabPaneGpuCounterSelection.ts b/ide/src/trace/component/trace/sheet/gpu-counter/TabPaneGpuCounterSelection.ts new file mode 100644 index 0000000000000000000000000000000000000000..08e04c3d78d52745e1d4b9c910039192f18b5f4f --- /dev/null +++ b/ide/src/trace/component/trace/sheet/gpu-counter/TabPaneGpuCounterSelection.ts @@ -0,0 +1,157 @@ +/* + * 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'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { GpuCounter, SelectionParam } from '../../../../bean/BoxSelection'; +import { ns2x, Rect } from '../../../../database/ui-worker/ProcedureWorkerCommon'; +import { SpSystemTrace } from '../../../SpSystemTrace'; +import { TraceRow } from '../../base/TraceRow'; +import { TraceSheet } from '../../base/TraceSheet'; +import { Flag } from '../../timer-shaft/Flag'; +import { resizeObserver } from '../SheetUtils'; + +@element('tabpane-gpu-counter-selection') +export class TabPaneGpuCounterSelection extends BaseElement { + private gpuCounterCounterTbl: LitTable | null | undefined; + private clockCounterSource: Array = []; + private traceSheetEl: TraceSheet | undefined | null; + private spSystemTrace: SpSystemTrace | undefined | null; + + set data(gpuCounterValue: SelectionParam) { + //@ts-ignore + this.gpuCounterCounterTbl?.shadowRoot?.querySelector('.table')?.style?.height = + this.parentElement!.clientHeight - 45 + 'px'; + this.getCounterData(gpuCounterValue).then(); + } + + async getCounterData(gpuCounterValue: SelectionParam) { + let collect = gpuCounterValue.gpuCounter; + let dataSource: Array = []; + collect.forEach((it) => { + let selectData = new GpuCounter(); + //@ts-ignore + selectData.startNS = it.startNS; + //@ts-ignore + selectData.height = it.height; + //@ts-ignore + selectData.dur = it.dur; + //@ts-ignore + selectData.type = it.type; + //@ts-ignore + selectData.frame = it.frame; + //@ts-ignore + selectData.startTime = it.startTime; + dataSource.push(selectData); + }); + this.clockCounterSource = dataSource; + this.gpuCounterCounterTbl!.recycleDataSource = dataSource; + } + + initElements(): void { + this.gpuCounterCounterTbl = this.shadowRoot?.querySelector('#tb-counter'); + this.spSystemTrace = document + .querySelector('body > sp-application') + ?.shadowRoot?.querySelector('#sp-system-trace'); + this.traceSheetEl = this.spSystemTrace?.shadowRoot?.querySelector('.trace-sheet'); + this.gpuCounterCounterTbl!.addEventListener('column-click', (event) => { + // @ts-ignore + this.sortByColumn(event.detail.key, event.detail.sort); + }); + this.addRowClickEventListener(this.gpuCounterCounterTbl!); + this.gpuCounterCounterTbl?.addEventListener('mouseout', () => { + this.refreshTable(); + }); + } + + refreshTable(): void { + if (this.traceSheetEl) { + this.traceSheetEl.systemLogFlag = undefined; + this.spSystemTrace?.refreshCanvas(false); + } + } + + addRowClickEventListener(table: LitTable): void { + table.addEventListener('row-hover', (evt) => { + // @ts-ignore + const data = evt.detail.data; + if (data) { + let pointX: number = ns2x( + data.startNS - data.startTime || 0, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + new Rect(0, 0, TraceRow.FRAME_WIDTH, 0) + ); + this.traceSheetEl!.systemLogFlag = new Flag( + Math.floor(pointX), + 0, + 0, + 0, + data.startNS - data.startTime, + '#666666', + '', + true, + '' + ); + } + this.spSystemTrace?.refreshCanvas(false); + }); + } + + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.gpuCounterCounterTbl!); + } + + initHtml(): string { + return ` + + + + + + + + + + `; + } + + sortByColumn(sortColumn: string, sortType: number): void { + let key = sortColumn; + let type = sortType; + let arr = Array.from(this.clockCounterSource); + arr.sort((gpuCounterLeftData, gpuCounterRightData): number => { + if (key === 'startNS' || type === 0) { + return (type === 1 ? 1 : -1) * (gpuCounterLeftData.startNS - gpuCounterRightData.startNS); + } else if (key === 'height') { + return (type === 1 ? 1 : -1) * (gpuCounterLeftData.height - gpuCounterRightData.height); + } else { + return 0; + } + }); + this.gpuCounterCounterTbl!.recycleDataSource = arr; + } +} diff --git a/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts b/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts index 82bd6f633bb130f61d120f2084fa8b2eb73a2256..bb71a425f963a3fdc9b038a8062aab6d28f11002 100644 --- a/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts +++ b/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts @@ -18,13 +18,7 @@ import { SelectionParam } from '../../../../bean/BoxSelection'; import { getGpufreqData, getGpufreqDataCut } from '../../../../database/sql/Perf.sql'; import { resizeObserver } from '../SheetUtils'; import { SpSegmentationChart } from '../../../chart/SpSegmentationChart'; -import { - GpuCountBean, - TreeDataBean, - type SearchGpuFuncBean, - CycleDataBean, - TreeDataStringBean, -} from '../../../../bean/GpufreqBean'; +import { GpuCountBean, TreeDataBean, type SearchGpuFuncBean, CycleDataBean, TreeDataStringBean } from '../../../../bean/GpufreqBean'; @element('tabpane-gpufreqdatacut') export class TabPaneGpufreqDataCut extends BaseElement { @@ -47,35 +41,29 @@ export class TabPaneGpufreqDataCut extends BaseElement { return; } else { SpSegmentationChart.setChartData('GPU-FREQ', []); - } + }; this.currentSelectionParam = threadStatesParam; this.threadStatesTbl!.recycleDataSource = []; this.threadStatesTbl!.loading = true; this.getGpufreqData(threadStatesParam.leftNs, threadStatesParam.rightNs, false).then((result) => { if (result !== null && result.length > 0) { let resultList: Array = JSON.parse(JSON.stringify(result)); - resultList[0].dur = resultList[1] - ? resultList[1].startNS - threadStatesParam.leftNs - : threadStatesParam.rightNs - threadStatesParam.leftNs; + resultList[0].dur = resultList[1] ? resultList[1].startNS - threadStatesParam.leftNs : threadStatesParam.rightNs - threadStatesParam.leftNs; resultList[0].value = resultList[0].dur * resultList[0].val; - resultList[resultList.length - 1].dur = - resultList.length - 1 !== 0 - ? threadStatesParam.rightNs - resultList[resultList.length - 1].startNS - : resultList[0].dur; - resultList[resultList.length - 1].value = - resultList.length - 1 !== 0 - ? resultList[resultList.length - 1].dur * resultList[resultList.length - 1].val - : resultList[0].value; + resultList[resultList.length - 1].dur = resultList.length - 1 !== 0 ? threadStatesParam.rightNs - resultList[resultList.length - 1].startNS : resultList[0].dur; + resultList[resultList.length - 1].value = resultList.length - 1 !== 0 ? resultList[resultList.length - 1].dur * resultList[resultList.length - 1].val : resultList[0].value; this.initData = resultList; this.threadStatesTbl!.loading = false; } else { this.threadStatesTbl!.recycleDataSource = []; this.threadStatesTbl!.loading = false; - } + }; }); this._threadId!.style.border = '1px solid rgb(151, 151, 151)'; this._threadFunc!.style.border = '1px solid rgb(151, 151, 151)'; - } + this.isChangeSingleBtn(false); + this.isChangeLoopBtn(false); + }; initElements(): void { this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-gpufreq-percent'); @@ -87,10 +75,14 @@ export class TabPaneGpufreqDataCut extends BaseElement { this.threadFuncName = this._threadFunc!.value.trim(); //点击single this._single?.addEventListener('click', (e) => { + this.isChangeSingleBtn(true); + this.isChangeLoopBtn(false); this.clickFun(this._single!.innerHTML); }); //点击loop this._loop?.addEventListener('click', (e) => { + this.isChangeSingleBtn(false); + this.isChangeLoopBtn(true); this.clickFun(this._loop!.innerHTML); }); //点击周期,算力泳道对应周期实现高亮效果 @@ -100,25 +92,34 @@ export class TabPaneGpufreqDataCut extends BaseElement { if (event.detail.level === EVENT_LEVEL && event.detail.thread.includes('cycle')) { // @ts-ignore SpSegmentationChart.tabHover('GPU-FREQ', true, event.detail.data.cycle); - } + }; }); this.addInputBorderEvent(this._threadId!); this.addInputBorderEvent(this._threadFunc!); - } + }; async getGpufreqData(leftNs: number, rightNs: number, isTrue: boolean): Promise> { let result: Array = await getGpufreqData(leftNs, rightNs, isTrue); return result; - } - async getGpufreqDataCut( - tIds: string, - funcName: string, - leftNS: number, - rightNS: number, - single: boolean, - loop: boolean - ): Promise> { + }; + async getGpufreqDataCut(tIds: string, funcName: string, leftNS: number, rightNS: number, single: boolean, loop: boolean): Promise> { let result: Array = await getGpufreqDataCut(tIds, funcName, leftNS, rightNS, single, loop); return result; + }; + //是否改变single按钮颜色 + private isChangeSingleBtn(flag: boolean): void { + if (flag) { + this.setAttribute('single', ''); + } else { + this.removeAttribute('single'); + }; + } + //是否改变loop按钮颜色 + private isChangeLoopBtn(flag: boolean): void { + if (flag) { + this.setAttribute('loop', ''); + } else { + this.removeAttribute('loop'); + }; } private clickFun(fun: string): void { this.threadIdValue = this._threadId!.value.trim(); @@ -126,7 +127,7 @@ export class TabPaneGpufreqDataCut extends BaseElement { this.threadStatesTbl!.loading = true; SpSegmentationChart.tabHover('GPU-FREQ', false, -1); this.validationFun(this.threadIdValue, this.threadFuncName, fun); - } + }; private addInputBorderEvent(inputElement: HTMLInputElement): void { if (inputElement) { inputElement.addEventListener('change', function () { @@ -135,7 +136,7 @@ export class TabPaneGpufreqDataCut extends BaseElement { } }); } - } + }; private validationFun(threadIdValue: string, threadFuncName: string, fun: string): void { if (threadIdValue === '') { this.handleEmptyInput(this._threadId!); @@ -146,30 +147,27 @@ export class TabPaneGpufreqDataCut extends BaseElement { this._threadFunc!.style.border = '1px solid rgb(151, 151, 151)'; if (fun === 'Single') { this.isTrue(threadIdValue, threadFuncName, true, false); - } + }; if (fun === 'Loop') { this.isTrue(threadIdValue, threadFuncName, false, true); - } - } - } + }; + }; + }; private handleEmptyInput(input: HTMLInputElement): void { this.threadStatesTbl!.loading = false; input!.style.border = '1px solid rgb(255,0,0)'; this.threadStatesTbl!.recycleDataSource = []; - } + }; private isTrue(threadIdValue: string, threadFuncName: string, single: boolean, loop: boolean): void { - this.getGpufreqDataCut( - threadIdValue, - threadFuncName, + this.getGpufreqDataCut(threadIdValue, threadFuncName, this.currentSelectionParam!.leftNs, this.currentSelectionParam!.rightNs, - single, - loop + single, loop ).then((result: Array) => { let _initData = JSON.parse(JSON.stringify(this.initData)); this.handleDataCut(_initData, result); }); - } + }; private handleDataCut(initData: Array, dataCut: Array): void { if (initData.length > 0 && dataCut.length > 0) { let finalGpufreqData: Array = new Array(); @@ -184,24 +182,25 @@ export class TabPaneGpufreqDataCut extends BaseElement { let initItem: GpuCountBean = initData[j]; _lastList.push(...this.segmentationData(initItem, dataItem, i)); j++; - currentIndex++; + currentIndex++; if (currentIndex === initData.length) { i++; j = 0; - currentIndex = 0; - } - } + currentIndex = 0; + }; + }; let tree: TreeDataStringBean = this.createTree(_lastList); finalGpufreqData.push(tree); this.threadStatesTbl!.recycleDataSource = finalGpufreqData; this.threadStatesTbl!.loading = false; this.clickTableHeader(finalGpufreqData); + } else { this.threadStatesTbl!.recycleDataSource = []; this.threadStatesTbl!.loading = false; SpSegmentationChart.setChartData('GPU-FREQ', []); - } - } + }; + }; private segmentationData(j: GpuCountBean, e: SearchGpuFuncBean, i: number): Array { let lastList: Array = []; if (j.startNS <= e.startTime && j.endTime >= e.startTime) { @@ -231,7 +230,7 @@ export class TabPaneGpufreqDataCut extends BaseElement { i ) ); - } + }; } else if (j.startNS >= e.startTime && j.endTime <= e.endTime) { lastList.push( new GpuCountBean( @@ -258,10 +257,10 @@ export class TabPaneGpufreqDataCut extends BaseElement { i ) ); - } + }; return lastList; - } - // 创建树形结构 + }; + // 创建树形结构 private createTree(data: Array): TreeDataStringBean { if (data.length > 0) { const root: { @@ -270,9 +269,9 @@ export class TabPaneGpufreqDataCut extends BaseElement { dur: number; percent: number; level: number; - children: TreeDataBean[]; + children: TreeDataBean[]; } = { - thread: 'gpufreq Frequency', + thread: 'gpufreq Frequency', value: 0, dur: 0, percent: 100, @@ -287,48 +286,43 @@ export class TabPaneGpufreqDataCut extends BaseElement { item.level = 4; this.updateValueMap(item, parentIndex, freq, valueMap); }); - Object.values(valueMap).forEach((node: TreeDataBean) => { - const parentNode: TreeDataBean = valueMap[node.freq! - 1]; + Object.values(valueMap).forEach((node: TreeDataBean) => { + const parentNode: TreeDataBean = valueMap[node.freq! - 1]; if (parentNode) { parentNode.children.push(node); parentNode.dur += node.dur; parentNode.value += node.value; } else { - root.children.push(node); - root.dur += node.dur; + root.children.push(node); + root.dur += node.dur; root.value += node.value; } }); this.flattenAndCalculate(root, root); const firstLevelChildren = this.getFirstLevelChildren(root); SpSegmentationChart.setChartData('GPU-FREQ', firstLevelChildren); - let _root = this.RetainDecimals(root); + let _root = this.RetainDecimals(root) return _root; } else { return new TreeDataStringBean('', '', '', '', '', ''); - } - } - private updateValueMap( - item: GpuCountBean, - parentIndex: number, - freq: number, - valueMap: { [parentIndex: string]: TreeDataBean } - ): void { + }; + }; + private updateValueMap(item: GpuCountBean, parentIndex: number, freq: number, valueMap: { [parentIndex: string]: TreeDataBean }): void { if (!valueMap[parentIndex]) { valueMap[parentIndex] = { thread: `cycle ${parentIndex + 1} ${item.thread}`, value: item.value, dur: item.dur, startNS: item.startNS, - percent: 100, + percent: 100, level: 2, cycle: parentIndex + 1, children: [], }; - } else { + } else { valueMap[parentIndex].dur += item.dur; valueMap[parentIndex].value += item.value; - } + }; if (!valueMap[parentIndex].children[freq]) { valueMap[parentIndex].children[freq] = { thread: item.thread, @@ -341,67 +335,41 @@ export class TabPaneGpufreqDataCut extends BaseElement { } else { valueMap[parentIndex].children[freq].dur += item.dur; valueMap[parentIndex].children[freq].value += item.value; - } + }; valueMap[parentIndex].children[freq].children.push(item as unknown as TreeDataBean); - } + }; private getFirstLevelChildren(obj: TreeDataBean): Array { const result: Array = []; if (Array.isArray(obj.children)) { - obj.children.forEach((child) => { - if ( - child.cycle !== undefined && - child.dur !== undefined && - child.value !== undefined && - child.startNS !== undefined - ) { - result.push( - new CycleDataBean( - 7, - child.dur, - Number((child.value / this.KUNIT).toFixed(3)), - child.startNS, - child.cycle, - '', - 1 - ) - ); - } + obj.children.forEach((child) => { + if (child.cycle !== undefined && child.dur !== undefined && child.value !== undefined && child.startNS !== undefined) { + result.push(new CycleDataBean(7,child.dur, Number((child.value / this.KUNIT).toFixed(3)), child.startNS, child.cycle,'',1)); + }; }); - } + }; return result; - } + }; private flattenAndCalculate(node: TreeDataBean, root: TreeDataBean): void { - node.percent = (node.value / root.value) * 100; + node.percent = node.value / root.value * 100; if (node.children) { node.children = node.children.flat(); node.children.forEach((childNode) => this.flattenAndCalculate(childNode, root)); - } - } + }; + }; private RetainDecimals(root: TreeDataBean): TreeDataStringBean { - const treeDataString: TreeDataStringBean = new TreeDataStringBean( - root.thread!, - (root.value / this.KUNIT).toFixed(this.SUB_LENGTH), - (root.dur / this.UNIT).toFixed(this.SUB_LENGTH), - root.percent!.toFixed(this.PERCENT_SUB_LENGTH), - String(root.level), - '', - 0, - [], - '', - false - ); + const treeDataString: TreeDataStringBean = new TreeDataStringBean(root.thread!, (root.value / this.KUNIT).toFixed(this.SUB_LENGTH), (root.dur / this.UNIT).toFixed(this.SUB_LENGTH), root.percent!.toFixed(this.PERCENT_SUB_LENGTH), String(root.level), '', 0, [], '', false); if (root.children) { for (const child of root.children) { treeDataString.children!.push(this.convertChildToString(child) as TreeDataStringBean); - } - } + }; + }; return treeDataString; - } + }; private convertChildToString(child: TreeDataBean | TreeDataBean[]): TreeDataStringBean | TreeDataStringBean[] { - if (Array.isArray(child)) { - if (child.length > 0) { - return child.map((c) => this.convertChildToString(c) as TreeDataStringBean); - } else { + if (Array.isArray(child)) { + if (child.length > 0) { + return child.map(c => this.convertChildToString(c) as TreeDataStringBean); + } else { return []; } } else if (child && child.children) { @@ -423,11 +391,12 @@ export class TabPaneGpufreqDataCut extends BaseElement { freq: child.freq ? child.freq!.toFixed(this.SUB_LENGTH) : '', dur: (child.dur / this.UNIT).toFixed(this.SUB_LENGTH), percent: child.percent ? child.percent.toFixed(this.PERCENT_SUB_LENGTH) : '', - level: String(child.level), + level: String(child.level) }; } - } - // 表头点击事件 + + }; + // 表头点击事件 private clickTableHeader(data: Array): void { let labels = this.threadStatesTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); const THREAD_INDEX: number = 0; @@ -445,8 +414,8 @@ export class TabPaneGpufreqDataCut extends BaseElement { item.status = true; if (item.children !== undefined && item.children.length > 0) { this.threadStatesTbl!.setStatus(item.children, false); - } - } + }; + }; this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); } else if (label.includes('Freq') && i === FREQ_INDEX) { for (let item of data) { @@ -455,20 +424,20 @@ export class TabPaneGpufreqDataCut extends BaseElement { e.status = true; if (e.children !== undefined && e.children.length > 0) { this.threadStatesTbl!.setStatus(e.children, true); - } - } - } + }; + }; + }; this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); - } + }; }); - } - } - } + }; + }; + }; connectedCallback(): void { super.connectedCallback(); resizeObserver(this.parentElement!, this.threadStatesTbl!); - } + }; initHtml(): string { return `
@@ -519,5 +496,5 @@ export class TabPaneGpufreqDataCut extends BaseElement { `; - } + }; } diff --git a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts index 17a39b1a27a0a9bddc85ed44afb407883fd2f21d..85e3b154f918d69ce1d382359e09b941fe1004fb 100644 --- a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts +++ b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogSummary.ts @@ -21,6 +21,7 @@ import { LitTable } from '../../../../../base-ui/table/lit-table'; import { LitIcon } from '../../../../../base-ui/icon/LitIcon'; import { TabPaneHiLogSummaryHtml } from './TabPaneHiLogSummary.html'; import { NUM_30, NUM_40 } from '../../../../bean/NumBean'; +import { queryLogAllData } from '../../../../database/sql/SqlLite.sql'; @element('tab-hi-log-summary') export class TabPaneHiLogSummary extends BaseElement { @@ -47,9 +48,15 @@ export class TabPaneHiLogSummary extends BaseElement { this.expansionDownIcon!.name = 'down'; this.logSummaryTable!.innerHTML = ''; this.summaryDownLoadTbl!.recycleDataSource = []; - this.systemLogSource = systemLogDetailParam.sysAlllogsData; - if (this.systemLogSource?.length !== 0 && systemLogDetailParam) { - this.refreshRowNodeTable(); + // @ts-ignore + let oneDayTime = (window as unknown).recordEndNS - 86400000000000; + if (systemLogDetailParam.hiLogs.length > 0) { + queryLogAllData(oneDayTime, systemLogDetailParam.leftNs, systemLogDetailParam.rightNs).then((res) => { + this.systemLogSource = res; + if (this.systemLogSource?.length !== 0 && systemLogDetailParam) { + this.refreshRowNodeTable(); + } + }); } } diff --git a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts index a8faa7789bf0df2a8583d44e2abbc7abb8b5195d..d3a8420c97298bb76bbdaffbbaf9290a2d01a226 100644 --- a/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts +++ b/ide/src/trace/component/trace/sheet/hilog/TabPaneHiLogs.ts @@ -47,8 +47,13 @@ export class TabPaneHiLogs extends BaseElement { private ONE_DAY_NS = 86400000000000; private progressEL: LitProgressBar | null | undefined; private timeOutId: number | undefined; + private currentSelection: SelectionParam | undefined; set data(systemLogParam: SelectionParam) { + if (systemLogParam === this.currentSelection) { + return; + } + this.currentSelection = systemLogParam; if (this.hiLogsTbl) { this.hiLogsTbl.recycleDataSource = []; this.filterData = []; diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts index b9d128b42d34648a3cfef4c4e92cc8bb824b50f4..7ab5b147b333798f73271d72ec681d79e67e1922 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts @@ -204,7 +204,7 @@ export class TabPanePerfAnalysis extends BaseElement { const detail = evt.detail; // @ts-ignore const data = detail.data; - if (detail.button === 0 && data.tableName !== '' && data.count !== 0) { + if (detail.button === 0 && data.tableName && data.count !== 0) { clickEvent(data, this.currentSelection); } }); diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfAsyncList.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfAsyncList.ts new file mode 100644 index 0000000000000000000000000000000000000000..876adb73fa4a4a0fa7170a6c0c8435faee93030e --- /dev/null +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfAsyncList.ts @@ -0,0 +1,746 @@ +/* + * Copyright (C) 2024 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'; +import { SelectionParam } from '../../../../bean/BoxSelection'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; +import '../../../../../base-ui/slicer/lit-slicer'; +import '../../../../../base-ui/progress-bar/LitProgressBar'; +import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; +import { procedurePool } from '../../../../database/Procedure'; +import { Utils } from '../../base/Utils'; +import { FrameChart } from '../../../chart/FrameChart'; +import { FilterData, TabPaneFilter } from '../TabPaneFilter'; +import { ChartMode } from '../../../../bean/FrameChartStruct'; +import { SpSystemTrace } from '../../../SpSystemTrace'; + +@element('tabpane-perf-async') +export class TabPanePerfAsync extends BaseElement { + private mainTable: LitTable | undefined | null; + private showTable: LitTable | undefined | null; + private callStackTable: LitTable | undefined | null; + private progressEl: LitProgressBar | undefined; + private currentSelection: SelectionParam | undefined | null; + private currentData: Array = []; + private simpleData: Array = []; + private isChartShow: boolean = false; + private asyncFilter: TabPaneFilter | null | undefined; + private asyncFrameChart: FrameChart | null | undefined; + private searchValue: string = ''; + private isSearch: boolean = false; + private processMap: Map = new Map(); + private threadMap: Map = new Map(); + + /** + * 标签页点击后的入口 + */ + set data(perfAsyncSelection: SelectionParam | null | undefined) { + if (perfAsyncSelection === this.currentSelection) { + return; + } + this.searchValue = ''; + // 保存当前的框选区域 + this.currentSelection = perfAsyncSelection; + // 设置筛选框内容为空,切换图标显示成对应火焰图的 + this.asyncFilter!.filterValue = ''; + this.asyncFilter!.icon = 'block'; + // 私有变量存储进程与线程的Map,后续根据id找对应的名字 + this.processMap = Utils.getInstance().getProcessMap(); + this.threadMap = Utils.getInstance().getThreadMap(); + // 设置加载动画 + this.progressEl!.loading = true; + // 提交子线程进行数据查询 + this.submitQueryData( + { + tid: perfAsyncSelection?.perfThread!, + cpu: perfAsyncSelection?.perfCpus!, + pid: perfAsyncSelection?.perfProcess!, + leftNs: perfAsyncSelection?.leftNs!, + rightNs: perfAsyncSelection?.rightNs!, + eventId: perfAsyncSelection?.perfEventTypeId, + searchValue: this.searchValue + } + ); + } + + /** + * 提交线程查询数据库获取数据 + * @param args 框选的perf泳道线程id等相关数据构成的对象 + */ + submitQueryData(args: { + tid?: Array, + cpu?: Array, + pid?: Array, + leftNs: number, + rightNs: number, + eventId: number | undefined, + searchValue: string + }): void { + // 清空数据,保证筛选后没有数据时,相关的表格火焰图不会显示上次的结果 + this.mainTable!.recycleDataSource = []; + this.showTable!.recycleDataSource = []; + this.callStackTable!.recycleDataSource = []; + this.asyncFrameChart!.data = []; + procedurePool.submitWithName('logic0', 'perf-async', args, undefined, this.callBack.bind(this)); + } + + /** + * worker线程返回查询结果后执行的回调函数 + * @param result 数据库查询结果 + */ + callBack(result: Array): void { + // 若返回数据为空,跳出函数 + if (result.length === 0) { + this.progressEl!.loading = false; + // 切换显示火焰图还是表格 + this.switchTableOrChart(); + return; + } + // 用临时变量接收处理完的数据 + this.currentData = this.organizeData(result); + // 简表使用数据 + this.simpleData = this.generateSimpleData(this.simpleData); + // 设置表格数据 + // 设置表格展开 + if (this.isSearch) { + this.showTable!.isSearch = true; + this.showTable!.setStatus(this.simpleData, true); + this.isSearch = false; + } + this.tHeadClick(this.simpleData); + // 设置简表数据 + this.showTable!.recycleDataSource = this.simpleData; + // 设置详表数据 + this.mainTable!.recycleDataSource = this.currentData; + // 更新火焰图canvas + this.asyncFrameChart?.updateCanvas(true, this.clientWidth); + // 设置火焰图根据sampleCount还是eventCount分布绘制 + if (this.currentSelection!.perfEventTypeId === undefined) { + this.asyncFrameChart!.mode = ChartMode.Count; + } else { + this.asyncFrameChart!.mode = ChartMode.EventCount; + } + // 设置火焰图数据 + // @ts-ignore + this.asyncFrameChart!.data = this.currentData; + // 切换显示火焰图还是表格 + this.switchTableOrChart(); + this.progressEl!.loading = false; + }; + + /** + * 合并规则,进程->线程->callerStack_Id->栈顶->第一非相同栈->AsyncWorkCallback下一层结束 + * @param result 数据库查询结果 + * @returns 整理好的结果 + */ + organizeData(result: Array): Array { + // 最终显示到表格上的数组数据 + let finalResult: Array = []; + for (let i = 0; i < result.length; i++) { + // 处理每一条数据,配置基本项,并进行被调用栈切割,只保留asynccallback后的数据 + this.dealEveryData(result[i]); + // 拷贝临时数组处理,否则会清掉引用类型变量原址的数据 + let callStack: Array = result[i].callerCallStack?.concat(result[i].calleeCallStack!)!; + // 进程数据 + let processItem: perfAsyncList = { ...result[i] }; + processItem.isProcess = true; + processItem.symbol = this.processMap.get(result[i].pid!) === null ? + 'Process[' + result[i].pid! + ']' : this.processMap.get(result[i].pid!)! + '[' + result[i].pid! + ']'; + // 线程数据 + let threadItem: perfAsyncList = { ...result[i] }; + threadItem.isThread = true; + threadItem.symbol = this.threadMap.get(result[i].tid!) === null ? + 'Thread[' + result[i].tid! + ']' : this.threadMap.get(result[i].tid!)! + '[' + result[i].tid! + ']'; + // @ts-ignore + callStack.unshift(threadItem); + // @ts-ignore + callStack.unshift(processItem); + // 递归将一维数组整理成链表 + let callStackList: Array = this.recursionToTree(callStack!, result[i])!; + // 如果两条数据calleechainid相同,则只保留前一条,并让sampleCount+1。如果不同,则找到被调用栈一样的的最后一层,将该条数据及其子数据插入进去 + // 查找相同进程分组 + const index: number = finalResult.findIndex((item) => item.pid === callStackList[0].pid); + if (index >= 0) { + finalResult[index].parent = undefined; + // 如果两条数据calleechainid相同,则只保留前一条,并让sampleCount+1。如果不同,则找到被调用栈一样的的最后一层,将该条数据及其子数据插入进去 + recusion(callStackList[0], finalResult[index]); + } else { + finalResult.push(...callStackList); + } + } + // 保存数据,火焰图生成后处理简表数据 + this.simpleData = [...result]; + return finalResult; + } + + + /** + * 修改每一条数据的对应字段显示值 + * @param data 数据库查询结果中的每一条数据 + */ + dealEveryData(data: perfAsyncList): void { + data.eventType = data.eventType + '[' + data.eventTypeId + ']'; + data.sampleCount = 1; + data.symbol = Utils.getTimeString(data.time!); + const index: number | undefined = data.calleeCallStack?.findIndex((item) => + item.symbolName!.indexOf('AsyncWorkCallback') !== -1 + ); + // 若不保留AsyncWorkCallback这一层,则在截取时让index+1 + data.calleeCallStack = data.calleeCallStack?.slice(index!)!; + data.callStackList = data.callerCallStack?.concat(data.calleeCallStack!); + data.jsFuncName = data.callerCallStack![data.callerCallStack!.length - 1].symbolName; + data.asyncFuncName = data.calleeCallStack!.length > 1 ? data.calleeCallStack![1].symbolName : data.calleeCallStack![0].symbolName; + data.drawCount = 0; + data.drawDur = 0; + data.drawEventCount = 0; + data.drawSize = 0; + data.searchCount = 0; + data.searchDur = 0; + data.searchEventCount = 0; + data.searchSize = 0; + data.isChartSelect = false; + data.isChartSelectParent = false; + data.isDraw = false; + data.isJsStack = false; + data.isProcess = false; + data.isThread = false; + if (data.isSearch === undefined) { + data.isSearch = false; + } + data.count = 1; + data.size = 0; + data.dur = 1; + data.isCharged = false; + } + + /** + * 用于设置右侧调用栈与被调用栈表格信息 + * @param data 当前主表点击的行数据 + */ + setRightTableData(data: perfAsyncList): void { + const callStackList: Array<{ + head: string, + eventTypeId: number, + symbolName: string, + children: Array + }> = []; + if (!(data.isProcess || data.isThread)) { + if (data.callerCallchainid) { + callStackList.push({ + head: '', + eventTypeId: 0, + symbolName: 'callerStack', + children: [] + }); + callStackList[0].children.push(...data.callerCallStack!); + if (data.calleeCallchainid) { + callStackList.push({ + head: '', + eventTypeId: 0, + symbolName: 'calleeStack', + children: [] + }); + callStackList[1].children.push(...data.calleeCallStack!); + } + } + } + this.callStackTable!.recycleDataSource = callStackList; + } + + /** + * 过滤工具栏的功能函数 + * @param data 过滤工具栏相关数据 + */ + asyncListFilterGetFilter(data: FilterData): void { + if ((this.isChartShow && data.icon === 'tree') || (!this.isChartShow && data.icon === 'block')) { + this.switchTableOrChart(); + } else if (this.searchValue !== this.asyncFilter!.filterValue) { + this.searchValue = this.asyncFilter!.filterValue; + this.submitQueryData( + { + tid: this.currentSelection?.perfThread!, + cpu: this.currentSelection?.perfCpus!, + pid: this.currentSelection?.perfProcess!, + leftNs: this.currentSelection?.leftNs!, + rightNs: this.currentSelection?.rightNs!, + eventId: this.currentSelection?.perfEventTypeId, + searchValue: this.searchValue + } + ); + this.isSearch = true; + } else { + this.showTable!.setStatus(this.simpleData, true); + this.switchTableOrChart(); + } + } + + /** + * 点击按钮进行表格与火焰图的切换 + * @param data 过滤工具栏相关数据 + */ + switchTableOrChart(): void { + let perfProfilerPageTab = this.shadowRoot?.querySelector('#show_table'); + let perfProfilerPageChart = this.shadowRoot?.querySelector('#show_chart'); + // 根据过滤工具栏的切换图标,显示火焰图或者表格 + if (this.asyncFilter!.icon === 'block') { + perfProfilerPageChart?.setAttribute('class', 'show'); + perfProfilerPageTab?.setAttribute('class', ''); + this.isChartShow = true; + this.asyncFilter!.disabledMining = false; + this.asyncFrameChart?.calculateChartData(); + } else if (this.asyncFilter!.icon === 'tree') { + perfProfilerPageChart?.setAttribute('class', ''); + perfProfilerPageTab?.setAttribute('class', 'show'); + this.isChartShow = false; + this.asyncFilter!.disabledMining = false; + this.asyncFrameChart!.clearCanvas(); + this.showTable!.reMeauseHeight(); + } + } + + /** + * 递归,将一维数组的每一项作为上一项的子项整理成链表结构 + * @param list 待整理的一维数组 + * @param data 每一项增加属性值时需要读取内容的数据 + * @param flag 待传入的每一个节点 + * @returns 返回数组结构,一项套一项,例:原数据为长度12的数组,返回则为嵌套深度为12的单项数组 + */ + recursionToTree( + list: Array, + data: perfAsyncList, + flag: Array | null = null + ): Array | undefined { + if (list.length === 0) { + return; + } + // 最后返回的数组,内容是一个链表 + const tree: Array = flag || []; + // 链表的每一层数据结构 + let item: perfAsyncList = { ...data }; + item.children = []; + // 此处定义tsArray是为了避免引用类型变量在进行数据合并,出现最底层栈却有多条数据的问题 + item.tsArray = [item.time!]; + item.parent = data; + // 循环一维数组,将每一项填充到其父级数组中 + // @ts-ignore + item.symbol = list[0].symbolName || list[0].symbol; + // @ts-ignore + item.lib = list[0].lib || list[0].symbol; + // @ts-ignore + item.addr = list[0].addr || ''; + // @ts-ignore + item.isProcess = list[0].isProcess; + // @ts-ignore + item.isThread = list[0].isThread; + // 符合搜索字符串匹配的火焰图及表格特殊处理 + if (this.searchValue !== '' && item.symbol!.toLocaleLowerCase().indexOf(this.searchValue.toLocaleLowerCase()) !== -1) { + item.isSearch = true; + } else { + item.isSearch = false; + } + tree.push(item); + // 处理完的数据进行删除,每次循环只会拿到首项,也就是需要处理的子项 + list.splice(0, 1); + // 递归调用 + this.recursionToTree(list, item, tree[0].children!); + return tree; + } + + /** + * 将数据库返回数据进行整理,生成简表展示数据 + * @param data 数据库返回数据 + * @returns 简表展示的数据 + */ + generateSimpleData(data: Array): Array { + let result = new Array(); + for (let i = 0; i < data.length; i++) { + let list = new Array(); + // 进程数据 + let processItem: perfAsyncList = { ...data[i] }; + processItem.isProcess = true; + processItem.symbol = this.processMap.get(data[i].pid!) === null ? + 'Process[' + data[i].pid! + ']' : this.processMap.get(data[i].pid!)! + '[' + data[i].pid! + ']'; + // 线程数据 + let threadItem: perfAsyncList = { ...data[i] }; + threadItem.isThread = true; + threadItem.symbol = this.threadMap.get(data[i].tid!) === null ? + 'Thread[' + data[i].tid! + ']' : this.threadMap.get(data[i].tid!)! + '[' + data[i].tid! + ']'; + // js栈层 + let jsFuncItem: perfAsyncList = { ...data[i] }; + jsFuncItem.symbol = jsFuncItem.jsFuncName; + // asyncWorkCallBack下一层 + let asyncFuncItem: perfAsyncList = { ...data[i] }; + asyncFuncItem.symbol = asyncFuncItem.asyncFuncName; + // 被调用栈最底层 + let bottomItem: perfAsyncList = { ...data[i] }; + bottomItem.asyncFuncName = bottomItem.calleeCallStack![bottomItem.calleeCallStack!.length - 1].symbolName; + bottomItem.symbol = bottomItem.asyncFuncName; + // 填充到数组,整理成链表结构 + list.push(processItem, threadItem, jsFuncItem, asyncFuncItem, bottomItem); + // @ts-ignore + list = this.recursionToTree(list, data[i])!; + // 查找相同进程分组 + const index: number = result.findIndex((item) => item.pid === list[0].pid); + if (index >= 0) { + result[index].parent = undefined; + // 合并栈 + recusion(list[0], result[index], true); + } else { + result.push(...list); + } + } + return result; + } + + /** + * 表头点击事件 + */ + private tHeadClick(data: Array): void { + let labels = this.showTable?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('Process') && i === 0) { + this.showTable!.setStatus(data, false); + this.showTable!.recycleDs = this.showTable!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 1) { + this.showTable!.setStatus(data, false, 0, 1); + this.showTable!.recycleDs = this.showTable!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Js_Func') && i === 2) { + this.showTable!.setStatus(data, false, 0, 2); + this.showTable!.recycleDs = this.showTable!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Async_Func') && i === 3) { + this.showTable!.setStatus(data, false, 0, 3); + this.showTable!.recycleDs = this.showTable!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Bottom') && i === 4) { + this.showTable!.setStatus(data, true); + this.showTable!.recycleDs = this.showTable!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } + }); + } + } + } + + /** + * 初始化元素,并进行变量绑定,监听事件添加 + */ + initElements(): void { + this.mainTable = this.shadowRoot?.querySelector('#tb-perf-async'); + this.showTable = this.shadowRoot?.querySelector('#tb-perf-show'); + this.callStackTable = this.shadowRoot?.querySelector('#call-stack-list'); + this.progressEl = this.shadowRoot?.querySelector('.perf-async-progress') as LitProgressBar; + this.asyncFilter = this.shadowRoot?.querySelector('#filter'); + this.asyncFrameChart = this.shadowRoot?.querySelector('#framechart'); + let spApplication = document.querySelector('body > sp-application'); + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; + this.asyncFilter!.getFilterData(this.asyncListFilterGetFilter.bind(this)); + this.asyncFilter?.addEventListener('focus', () => { + spSystemTrace.focusTarget = 'bottomUpInput'; + }) + this.asyncFilter?.addEventListener('blur', () => { + spSystemTrace.focusTarget = ''; + }); + // 将主表绑定行点击事件,根据点击数据更新右侧的调用栈与被调用栈表格信息 + // @ts-ignore + this.showTable?.addEventListener('row-click', (evt: CustomEvent) => { + let data = evt.detail.data; + data.isSelected = true; + this.showTable?.clearAllSelection(data); + this.showTable?.setCurrentSelection(data); + this.setRightTableData(data); + document.dispatchEvent( + new CustomEvent('number_calibration', { + detail: { time: data.tsArray }, + }) + ); + if (evt.detail.callBack) { + evt.detail.callBack(true); + } + }); + // @ts-ignore + this.callStackTable?.addEventListener('row-click', (evt: CustomEvent) => { + let data = evt.detail.data; + data.isSelected = true; + this.callStackTable?.clearAllSelection(data); + this.callStackTable?.setCurrentSelection(data); + if (evt.detail.callBack) { + evt.detail.callBack(true); + } + }); + } + + /** + * 生命周期函数,用于调整表格高度 + */ + connectedCallback(): void { + super.connectedCallback(); + // 设置火焰图滚动高度,更新火焰图时会 + this.parentElement!.onscroll = (): void => { + this.asyncFrameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; + }; + let filterHeight = 0; + // 动态监听视图窗口变化 + new ResizeObserver((entries): void => { + let asyncTabFilter = this.shadowRoot!.querySelector('#filter') as HTMLElement; + // 获取过滤工具栏高度 + if (asyncTabFilter.clientHeight > 0) { + filterHeight = asyncTabFilter.clientHeight; + } + // 动态调整过滤工具栏的显隐 + if (this.parentElement!.clientHeight > filterHeight) { + asyncTabFilter.style.display = 'flex'; + } else { + asyncTabFilter.style.display = 'none'; + } + // 如果数据表隐藏,则让过滤工具栏也隐藏 + if (this.showTable!.style.visibility === 'hidden') { + asyncTabFilter.style.display = 'none'; + } + if (this.parentElement?.clientHeight !== 0) { + // 更新火焰图 + if (this.isChartShow) { + this.asyncFrameChart?.updateCanvas(false, entries[0].contentRect.width); + this.asyncFrameChart?.calculateChartData(); + } + // 调整表格高度 + // @ts-ignore + this.showTable?.shadowRoot.querySelector('.table').style.height = + // @ts-ignore + `${this.parentElement.clientHeight - 45}px`; + this.showTable?.reMeauseHeight(); + // @ts-ignore + this.callStackTable?.shadowRoot.querySelector('.table').style.height = + `${this.parentElement!.clientHeight - 45}px`; + this.callStackTable?.reMeauseHeight(); + } + }).observe(this.parentElement!); + } + + /** + * 前端渲染的节点及样式 + * @returns html元素字符串 + */ + initHtml(): string { + return this.initStyle() + ` +
+ + + +
+ + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+
+ + + + +
+ `; + } + + /** + * 前端渲染节点的样式 + * @returns style标签 + */ + initStyle(): string { + return ` + + `; + } +} + +interface perfAsyncList { + tid?: number; + pid?: number; + time?: number; + symbol?: string; + traceid?: string; + eventCount?: number; + sampleCount?: number; + jsFuncName?: string; + callerCallchainid?: number; + calleeCallchainid?: number; + asyncFuncName?: string; + eventType?: string; + children?: Array; + eventTypeId?: number; + symbolName?: string; + callerCallStack?: Array; + calleeCallStack?: Array; + callStackList?: Array; + parent?: perfAsyncList; + isProcess?: boolean; + isThread?: boolean; + depth?: number; + isSearch?: boolean; + isJsStack?: boolean; + lib?: string; + isChartSelectParent?: boolean; + isChartSelect?: boolean; + isDraw?: boolean; + drawDur?: number; + drawEventCount?: number; + drawCount?: number; + drawSize?: number; + searchEventCount?: number; + searchCount?: number; + searchDur?: number; + searchSize?: number; + size?: number; + count?: number; + dur?: number; + tsArray?: Array; + isCharged?: boolean; + addr?: string; +} + +/** + * 递归整理合并相同调用栈与被调用栈 + * @param data 需要合并给目标数据的数据 + * @param targetData 目标数据 + * @param index 递归次数 + */ +export function recusion(data: perfAsyncList, targetData: perfAsyncList, flag?: boolean) { + // 将新元素合并到目标元素时,将目标元素的sampleCount和eventCount进行累加,每次进来都是要合并的值 + targetData.sampleCount! += data.sampleCount!; + targetData.count! += data.count!; + targetData.dur! += data.dur!; + targetData.eventCount! += data.eventCount!; + targetData.tsArray?.push(data.time!); + targetData.tsArray = [...new Set(targetData.tsArray)]; + data.parent = targetData.parent; + targetData.children?.sort((a, b) => b.count! - a.count!); + if (data.callerCallchainid !== targetData.callerCallchainid) { + targetData.jsFuncName = ''; + // @ts-ignore + targetData.callerCallchainid = ''; + targetData.traceid = ''; + } + if (data.calleeCallchainid !== targetData.calleeCallchainid) { + targetData.asyncFuncName = ''; + // @ts-ignore + targetData.calleeCallchainid = ''; + } + // 需要根据子级是否有值判断如何合并,两者都有子级 + if (data.children!.length !== 0 && targetData.children!.length !== 0) { + // 目标栈可能已经保存了多条数据,需要找到合并栈子级与被合并栈子级相同的分支进行栈合并 + // 筛选出子项最多的那个 + const num: number = targetData?.children?.findIndex((item) => item.symbol === data.children![0].symbol)!; + // 去重 + targetData.tsArray = [...new Set(targetData.tsArray)]; + // 若存在symbol相同的子级,则进入下一层合并。若不存在,则证明是新的分支,将新的子级填充到目标元素子级中 + if (num >= 0) { + //此处是为了区分简表和详表。简表只有5层,存在首尾相同,中间不同的情况 + if (flag && targetData.children![num].calleeCallchainid !== data.children![0].calleeCallchainid && data.children![0].children!.length === 0) { + targetData.children!.push(data.children![0]); + data.children![0].parent = targetData; + } else { + recusion(data.children![0], targetData.children![num], flag); + } + } else { + targetData.children?.push(data.children![0]); + data.children![0].parent = targetData; + targetData.children?.sort((a, b) => b.count! - a.count!); + } + } else if (data.children!.length !== 0 && targetData.children!.length === 0) { + // 若目标元素不存在子级,当前元素存在子级。证明目标元素中需要添加一个子级更多的元素,并将其填充到队首,方便查找相同分支时拿到的是子级更多的分支。 + const num: number = targetData?.children?.findIndex((item) => item.symbol === data.children![0].symbol)!; + targetData.children?.splice(num, 0, data.children![0]); + data.children![0].parent = targetData; + } +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfBottomUp.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfBottomUp.ts index b497e22e790e0400a562c57e0f5aebc4ce0c7151..32b04cf06a5d6b98bdc307667a038aa1c51a5be1 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfBottomUp.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfBottomUp.ts @@ -25,6 +25,7 @@ import { procedurePool } from '../../../../database/Procedure'; import { type LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; import { type PerfBottomUpStruct } from '../../../../bean/PerfBottomUpStruct'; import { findSearchNode } from '../../../../database/ui-worker/ProcedureWorkerCommon'; +import { SpSystemTrace } from '../../../SpSystemTrace'; @element('tabpane-perf-bottom-up') export class TabpanePerfBottomUp extends BaseElement { @@ -43,6 +44,10 @@ export class TabpanePerfBottomUp extends BaseElement { this.stackTable = this.shadowRoot?.querySelector('#stackTable') as LitTable; this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; this.bottomUpFilter = this.shadowRoot?.querySelector('#filter') as TabPaneFilter; + let spApplication = document.querySelector('body > sp-application'); + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; this.bottomUpTable!.addEventListener('row-click', (evt) => this.bottomUpTableRowClickHandler(evt)); this.stackTable!.addEventListener('row-click', (evt) => this.stackTableRowClick(evt)); this.bottomUpTable!.addEventListener('column-click', (evt) => this.bottomUpTableColumnClickHandler(evt)); @@ -54,6 +59,12 @@ export class TabpanePerfBottomUp extends BaseElement { this.bottomUpTable!.setStatus(this.bottomUpSource, true); this.setBottomUpTableData(this.bottomUpSource); }); + this.bottomUpFilter?.addEventListener('focus', () => { + spSystemTrace.focusTarget = 'bottomUpInput'; + }) + this.bottomUpFilter?.addEventListener('blur', () => { + spSystemTrace.focusTarget = ''; + }); } private getDataByWorker(val: SelectionParam, handler: (results: Array) => void): void { diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts index 6b2d05e0f5026e4191f78a6b1d1b2012c510b694..220499eb08e29711dd2ad536e6d7d65303f71ebe 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts @@ -30,13 +30,15 @@ import { showButtonMenu } from '../SheetUtils'; import '../../../../../base-ui/headline/lit-headline'; import { LitHeadLine } from '../../../../../base-ui/headline/lit-headline'; import { TabPerfProfileHtml } from './TabPerfProfile.html'; +import { SpSystemTrace } from '../../../SpSystemTrace'; const InvertOptionIndex: number = 0; const hideSystemLibraryOptionIndex: number = 1; const hideThreadOptionIndex: number = 3; const hideThreadStateOptionIndex: number = 4; const isOnlyKernelOptionIndex: number = 5; -const callTreeValueNoSample: number[] = [InvertOptionIndex, hideSystemLibraryOptionIndex, hideThreadOptionIndex, hideThreadStateOptionIndex, isOnlyKernelOptionIndex]; +const callTreeValueNoSample: number[] = [InvertOptionIndex, hideSystemLibraryOptionIndex, hideThreadOptionIndex, + hideThreadStateOptionIndex, isOnlyKernelOptionIndex]; @element('tabpane-perf-profile') export class TabpanePerfProfile extends BaseElement { @@ -155,6 +157,7 @@ export class TabpanePerfProfile extends BaseElement { this.perfProfileFrameChart!.mode = ChartMode.EventCount; } this.perfProfileFrameChart?.updateCanvas(true, initWidth); // @ts-ignore + this.perfProfileFrameChart!.totalRootData = this.perfProfilerDataSource;// @ts-ignore this.perfProfileFrameChart!.data = this.perfProfilerDataSource; this.switchFlameChart(); this.perfProfilerFilter!.icon = 'block'; @@ -301,6 +304,10 @@ export class TabpanePerfProfile extends BaseElement { this.perfProfileProgressEL = this.shadowRoot?.querySelector('.perf-profile-progress') as LitProgressBar; this.perfProfileFrameChart = this.shadowRoot?.querySelector('#framechart'); this.perfProfileLoadingPage = this.shadowRoot?.querySelector('.perf-profile-loading'); + let spApplication = document.querySelector('body > sp-application'); + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; this.addEventListener('contextmenu', (event) => { event.preventDefault(); // 阻止默认的上下文菜单弹框 }); @@ -313,6 +320,12 @@ export class TabpanePerfProfile extends BaseElement { this.perfProfilerFilter = this.shadowRoot?.querySelector('#filter'); this.perfProfilerList = this.shadowRoot?.querySelector('#tb-perf-list'); this.initPerfProfilerDataAndListener(); + this.perfProfilerFilter?.addEventListener('focus', () => { + spSystemTrace.focusTarget = 'bottomUpInput'; + }) + this.perfProfilerFilter?.addEventListener('blur', () => { + spSystemTrace.focusTarget = ''; + }); } private initPerfProfilerDataAndListener(): void { diff --git a/ide/src/trace/component/trace/sheet/hisysevent/TabPaneHiSysEventSummary.ts b/ide/src/trace/component/trace/sheet/hisysevent/TabPaneHiSysEventSummary.ts index 96dcfe30444148877f934a31efc89fc720bd25f1..692ee3c677da77b1b772d3148b0c69ece633cfe5 100644 --- a/ide/src/trace/component/trace/sheet/hisysevent/TabPaneHiSysEventSummary.ts +++ b/ide/src/trace/component/trace/sheet/hisysevent/TabPaneHiSysEventSummary.ts @@ -21,6 +21,7 @@ import { LitTable } from '../../../../../base-ui/table/lit-table'; import { ColorUtils } from '../../base/ColorUtils'; import { TabPaneHiSysEventSummaryHtml } from './TabPaneHiSysEventSummary.html'; import { NUM_30, NUM_40 } from '../../../../bean/NumBean'; +import { queryHiSysEventTabData } from '../../../../database/sql/Perf.sql'; @element('tab-hi-sysevent-summary') export class TabPaneHiSysEventSummary extends BaseElement { @@ -45,7 +46,13 @@ export class TabPaneHiSysEventSummary extends BaseElement { this.expansionDownIcon!.name = 'down'; this.eventSummaryTable!.innerHTML = ''; this.summaryTable!.recycleDataSource = []; - this.summarySource = systemEventParam.sysAllEventsData; + queryHiSysEventTabData(systemEventParam.leftNs, systemEventParam.rightNs).then((res) => { + this.currentSelection = systemEventParam; + systemEventParam.sysAllEventsData = res; + this.summarySource = systemEventParam.sysAllEventsData; + this.summaryTable!.recycleDataSource = res; + this.refreshRowNodeTable(); + }); if (this.summarySource?.length !== 0 && systemEventParam) { this.refreshRowNodeTable(); } diff --git a/ide/src/trace/component/trace/sheet/jank/TabPaneFrames.ts b/ide/src/trace/component/trace/sheet/jank/TabPaneFrames.ts index e51aee4ba4f2c747e1a84a2f9c1e9bd1d112ec0b..1e617607456336edd09ff6e51654c55363ac98e6 100644 --- a/ide/src/trace/component/trace/sheet/jank/TabPaneFrames.ts +++ b/ide/src/trace/component/trace/sheet/jank/TabPaneFrames.ts @@ -59,9 +59,9 @@ export class TabPaneFrames extends BaseElement { this.frameTimelineJankDataHandle(item, appJank, noJank); }); // @ts-ignore result.forEach((structValue: JanksStruct) => { - if (structValue.frame_type === 'app') { + if (structValue.frameType === 'app') { this.appJankDataHandle(structValue, appJank, noJank); - } else if (structValue.frame_type === 'render_service') { + } else if (structValue.frameType === 'render_service') { this.rsJankDataHandle(structValue, rsJank, noJank); } }); diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts index 2dc0057755d48dc03e71d87039acd72ac81baa96..e9fe2e9726144440db7fa810e1d0900c3aa58d1f 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMCallTree.ts @@ -183,12 +183,13 @@ export class TabpaneNMCalltree extends BaseElement { if (data.type === 'AllocEvent') { data.type = '1'; } + const that = this; if (this.subTypeArr.length > 0) { this.subTypeArr.map((memory): void => { selections.push({ memoryTap: memory, }); - if (this.currentSelection?.nativeMemory && this.currentSelection.nativeMemory.length > 0) { + if (that.currentSelection?.nativeMemory && that.currentSelection.nativeMemory.length > 0) { const typeName = SpSystemTrace.DATA_DICT.get(memory); if ((data.type === 'MmapEvent' && memory === -1) || data.type === typeName) { data.type = `${selections.length + 2}`; @@ -338,16 +339,17 @@ export class TabpaneNMCalltree extends BaseElement { async initFilterTypes(): Promise { this.currentNMCallTreeFilter = this.shadowRoot?.querySelector('#nm-call-tree-filter'); let secondFilterList = ['All Heap & Anonymous VM', 'All Heap', 'All Anonymous VM']; - const addSubType = (subTypeList: unknown): void => { + let that = this; + function addSubType(subTypeList: unknown): void { if (!subTypeList) { return; } - this.subTypeArr = []; // @ts-ignore + that.subTypeArr = []; // @ts-ignore for (let data of subTypeList) { secondFilterList.push(data.subType); - this.subTypeArr.push(data.subTypeId); + that.subTypeArr.push(data.subTypeId); } - }; + } if (this.currentSelection!.nativeMemory!.length > 0) { let subTypeList = await queryNativeHookSubType( this.currentSelection!.leftNs, @@ -415,10 +417,14 @@ export class TabpaneNMCalltree extends BaseElement { this.nmCallTreeTbl!.rememberScrollTop = true; this.nmCallTreeTbl!.exportTextHandleMap.set('heapSizeStr', (value) => { // @ts-ignore - return `${value.size}`; + return `${value['size']}`; }); this.nmCallTreeFilter = this.shadowRoot?.querySelector('#nm-call-tree-filter'); this.filesystemTbr = this.shadowRoot?.querySelector('#tb-filesystem-list'); + let spApplication = document.querySelector('body > sp-application'); + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; let filterFunc = (nmCallTreeFuncData: unknown): void => { let nmCallTreeFuncArgs: unknown[] = []; // @ts-ignore if (nmCallTreeFuncData.type === 'check') { @@ -450,6 +456,12 @@ export class TabpaneNMCalltree extends BaseElement { this.nmCallTreeFilter!.getCallTreeConstraintsData(this.getCallTreeConByNMCallTreeFilter.bind(this)); this.nmCallTreeFilter!.getFilterData(this.getFilterDataByNMCallTreeFilter.bind(this)); this.initCloseCallBackByHeadLine(); + this.nmCallTreeFilter?.addEventListener('focus', () => { + spSystemTrace.focusTarget = 'bottomUpInput'; + }) + this.nmCallTreeFilter?.addEventListener('blur', () => { + spSystemTrace.focusTarget = ''; + }); } private getFilterDataByNMCallTreeFilter(nmCallTreeData: FilterData): void { diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts index 15100276d53d8935a13638d9bc8c81b755f29acf..8b6a1c4609f2d0204376ff52459842637d8da64c 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMSampleList.ts @@ -322,11 +322,11 @@ export class TabPaneNMSampleList extends BaseElement { TabPaneNMSampleList.filter!.firstSelect = TabPaneNMSampleList.filterSelect; TabPaneNMSampleList.sampleTbl!.exportTextHandleMap.set('totalGrowth', (value) => { // @ts-ignore - return `${value.total}`; + return `${value['total']}`; }); TabPaneNMSampleList.sampleTbl!.exportTextHandleMap.set('growth', (value) => { // @ts-ignore - return `${value.heapSize}`; + return `${value['heapSize']}`; }); } 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 beb10971cdc7099e6012266f987461cf55b802fb..7ad1bb8b00503a4bcef311cc4b57455ef9c05a69 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts @@ -98,7 +98,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { private threadData!: Array; private soData!: Array; private functionData!: Array; - private tableType: LitTable | null | undefined; + private typeUsageTbl: LitTable | null | undefined; private threadUsageTbl: LitTable | null | undefined; private soUsageTbl: LitTable | null | undefined; private functionUsageTbl: LitTable | null | undefined; @@ -137,7 +137,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { if (statisticAnalysisParam === this.currentSelection) { // @ts-ignore this.eventTypeData.unshift(this.typeStatisticsData); - this.tableType!.recycleDataSource = this.eventTypeData; + this.typeUsageTbl!.recycleDataSource = this.eventTypeData; // @ts-ignore this.eventTypeData.shift(this.typeStatisticsData); return; @@ -152,21 +152,8 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { Utils.getInstance().setCurrentSelectIPid(statisticAnalysisParam.nativeMemoryCurrentIPid); Utils.getInstance().initResponseTypeList(statisticAnalysisParam); } - if (this.tableType) { - // @ts-ignore - this.tableType.shadowRoot.querySelector('.table').style.height = this.parentElement.clientHeight - 30 + 'px'; - } - if (this.soUsageTbl) { - // @ts-ignore - this.soUsageTbl.shadowRoot.querySelector('.table').style.height = this.parentElement.clientHeight - 30 + 'px'; - } - if (this.functionUsageTbl) { - // @ts-ignore - this.functionUsageTbl.shadowRoot.querySelector('.table').style.height = `${ - this.parentElement!.clientHeight - 30 - }px`; - } - this.reset(this.tableType!, false); + this.resizeTable(); + this.reset(this.typeUsageTbl!, false); this.currentSelection = statisticAnalysisParam; this.titleEl!.textContent = ''; this.tabName!.textContent = ''; @@ -178,7 +165,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { this.threadName = ''; } this.getNMEventTypeSize(statisticAnalysisParam); - this.showAssignLevel(this.tableType!, this.functionUsageTbl!, 0, this.eventTypeData); + this.showAssignLevel(this.typeUsageTbl!, this.functionUsageTbl!, 0, this.eventTypeData); } initNmTableArray(): void { @@ -225,7 +212,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { } initTable(): void { - this.tableType!.addEventListener('row-click', (evt) => { + this.typeUsageTbl!.addEventListener('row-click', (evt) => { // @ts-ignore let button = evt.detail.button; // @ts-ignore @@ -259,7 +246,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { this.range = this.shadowRoot?.querySelector('#time-range'); this.nmPieChart = this.shadowRoot!.querySelector('#nm-chart-pie'); this.nmTableBox = this.shadowRoot!.querySelector('.nm-table-box'); - this.tableType = this.shadowRoot!.querySelector('#tb-eventtype-usage'); + this.typeUsageTbl = this.shadowRoot!.querySelector('#tb-eventtype-usage'); this.threadUsageTbl = this.shadowRoot!.querySelector('#tb-thread-usage'); this.soUsageTbl = this.shadowRoot!.querySelector('#tb-so-usage'); this.functionUsageTbl = this.shadowRoot!.querySelector('#tb-function-usage'); @@ -273,8 +260,8 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { let popover = this.filterEl!.shadowRoot!.querySelector('#check-popover'); this.hideThreadCheckBox = popover!!.querySelector('div > #hideThread'); this.hideThreadCheckBox?.addEventListener('change', () => { - this.reset(this.tableType!, false); - this.showAssignLevel(this.tableType!, this.functionUsageTbl!, 0, this.eventTypeData); // @ts-ignore + this.reset(this.typeUsageTbl!, false); + this.showAssignLevel(this.typeUsageTbl!, this.functionUsageTbl!, 0, this.eventTypeData); // @ts-ignore this.getNMTypeSize(this.currentSelection, this.processData); }); this.initNmTableArray(); @@ -297,7 +284,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { // @ts-ignore return `${value.releaseSize}`; }); - this.tableType!.exportTextHandleMap = exportHandlerMap; + this.typeUsageTbl!.exportTextHandleMap = exportHandlerMap; this.threadUsageTbl!.exportTextHandleMap = exportHandlerMap; this.soUsageTbl!.exportTextHandleMap = exportHandlerMap; this.functionUsageTbl!.exportTextHandleMap = exportHandlerMap; @@ -383,7 +370,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { private clearData(): void { this.nmPieChart!.dataSource = []; - this.tableType!.recycleDataSource = []; + this.typeUsageTbl!.recycleDataSource = []; this.threadUsageTbl!.recycleDataSource = []; this.soUsageTbl!.recycleDataSource = []; this.functionUsageTbl!.recycleDataSource = []; @@ -406,12 +393,12 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { private getBack(): void { this.nmBack!.addEventListener('click', () => { if (this.tabName!.textContent === 'Statistic By Thread Existing') { - this.showAssignLevel(this.tableType!, this.threadUsageTbl!, 0, this.eventTypeData); + this.showAssignLevel(this.typeUsageTbl!, this.threadUsageTbl!, 0, this.eventTypeData); this.nmBack!.style.visibility = 'hidden'; this.typePieChart(); } else if (this.tabName!.textContent === 'Statistic By Library Existing') { if (this.hideThreadCheckBox?.checked || this.isStatistic) { - this.showAssignLevel(this.tableType!, this.soUsageTbl!, 0, this.eventTypeData); + this.showAssignLevel(this.typeUsageTbl!, this.soUsageTbl!, 0, this.eventTypeData); this.nmBack!.style.visibility = 'hidden'; this.typePieChart(); } else { @@ -456,9 +443,9 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { }, hoverHandler: (nmData): void => { if (nmData) { - this.tableType!.setCurrentHover(nmData); + this.typeUsageTbl!.setCurrentHover(nmData); } else { - this.tableType!.mouseOut(); + this.typeUsageTbl!.mouseOut(); } }, interactions: [ @@ -472,10 +459,10 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { this.tabName!.textContent = 'Statistic By Event Type Existing'; // @ts-ignore this.eventTypeData.unshift(this.typeStatisticsData); - this.tableType!.recycleDataSource = this.eventTypeData; + this.typeUsageTbl!.recycleDataSource = this.eventTypeData; // @ts-ignore this.eventTypeData.shift(this.typeStatisticsData); - this.tableType?.reMeauseHeight(); + this.typeUsageTbl?.reMeauseHeight(); this.currentLevelData = this.eventTypeData; } @@ -656,11 +643,11 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { private nativeProcessLevelClickEvent(it: unknown): void { if (this.hideThreadCheckBox?.checked || this.isStatistic) { this.reset(this.soUsageTbl!, true); - this.showAssignLevel(this.soUsageTbl!, this.tableType!, 1, this.eventTypeData); + this.showAssignLevel(this.soUsageTbl!, this.typeUsageTbl!, 1, this.eventTypeData); this.getNMLibSize(it); } else { this.reset(this.threadUsageTbl!, true); - this.showAssignLevel(this.threadUsageTbl!, this.tableType!, 1, this.eventTypeData); + this.showAssignLevel(this.threadUsageTbl!, this.typeUsageTbl!, 1, this.eventTypeData); this.getNMThreadSize(it); } // @ts-ignore const typeName = it.typeName === TYPE_MAP_STRING ? TYPE_OTHER_MMAP : it.typeName; @@ -1066,12 +1053,12 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { other.existSizeFormat = Utils.getBinaryByteWithUnit(other.existSize); // @ts-ignore other.applySizeFormat = Utils.getBinaryByteWithUnit(other.applySize); // @ts-ignore other.releaseSizeFormat = Utils.getBinaryByteWithUnit(other.releaseSize); // @ts-ignore - other.existSizePercent = ((other.existSize / this.currentLevelExistSize) * 100).toFixed(2); // @ts-ignore - other.existCountPercent = ((other.existCount / this.currentLevelExistCount) * 100).toFixed(2); // @ts-ignore - other.applySizePercent = ((other.applySize / this.currentLevelApplySize) * 100).toFixed(2); // @ts-ignore - other.applyCountPercent = ((other.applyCount / this.currentLevelApplyCount) * 100).toFixed(2); // @ts-ignore - other.releaseSizePercent = ((other.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); // @ts-ignore - other.releaseCountPercent = ((other.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2); + other.existSizePercent = this.currentLevelExistSize === 0 ? 0 : ((other.existSize / this.currentLevelExistSize) * 100).toFixed(2); // @ts-ignore + other.existCountPercent = this.currentLevelExistCount === 0 ? 0 : ((other.existCount / this.currentLevelExistCount) * 100).toFixed(2); // @ts-ignore + other.applySizePercent = this.currentLevelApplySize === 0 ? 0 : ((other.applySize / this.currentLevelApplySize) * 100).toFixed(2); // @ts-ignore + other.applyCountPercent = this.currentLevelApplyCount === 0 ? 0 : ((other.applyCount / this.currentLevelApplyCount) * 100).toFixed(2); // @ts-ignore + other.releaseSizePercent = this.currentLevelReleaseSize === 0 ? 0 : ((other.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); // @ts-ignore + other.releaseCountPercent = this.currentLevelReleaseCount === 0 ? 0 : ((other.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2); } } // @ts-ignore pieChartArr.push(other); @@ -1118,12 +1105,12 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { } private calPercent(item: AnalysisObj): void { - item.applySizePercent = ((item.applySize / this.currentLevelApplySize) * 100).toFixed(2); - item.applyCountPercent = ((item.applyCount / this.currentLevelApplyCount) * 100).toFixed(2); - item.releaseSizePercent = ((item.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); - item.releaseCountPercent = ((item.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2); - item.existSizePercent = ((item.existSize / this.currentLevelExistSize) * 100).toFixed(2); - item.existCountPercent = ((item.existCount / this.currentLevelExistCount) * 100).toFixed(2); + item.applySizePercent = this.currentLevelApplySize === 0 ? '0' : ((item.applySize / this.currentLevelApplySize) * 100).toFixed(2); + item.applyCountPercent = this.currentLevelApplyCount === 0 ? '0' : ((item.applyCount / this.currentLevelApplyCount) * 100).toFixed(2); + item.releaseSizePercent = this.currentLevelReleaseSize === 0 ? '0' : ((item.releaseSize / this.currentLevelReleaseSize) * 100).toFixed(2); + item.releaseCountPercent = this.currentLevelReleaseCount === 0 ? '0' : ((item.releaseCount / this.currentLevelReleaseCount) * 100).toFixed(2); + item.existSizePercent = this.currentLevelExistSize === 0 ? '0' : ((item.existSize / this.currentLevelExistSize) * 100).toFixed(2); + item.existCountPercent = this.currentLevelExistCount === 0 ? '0' : ((item.existCount / this.currentLevelExistCount) * 100).toFixed(2); } private resetCurrentLevelData(parent?: unknown): void { @@ -1151,23 +1138,25 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { return typeMap; } - const setSize = (item: unknown): void => { + let that = this; + + function setSize(item: unknown): void { // @ts-ignore - this.currentLevelApplySize += item.size; // @ts-ignore - this.currentLevelApplyCount += item.count; - if (this.isStatistic) { + that.currentLevelApplySize += item.size; // @ts-ignore + that.currentLevelApplyCount += item.count; + if (that.isStatistic) { // @ts-ignore - this.currentLevelReleaseSize += item.releaseSize; // @ts-ignore - this.currentLevelReleaseCount += item.releaseCount; + that.currentLevelReleaseSize += item.releaseSize; // @ts-ignore + that.currentLevelReleaseCount += item.releaseCount; } else { // @ts-ignore if (item.isRelease) { // @ts-ignore - this.currentLevelReleaseSize += item.size; // @ts-ignore - this.currentLevelReleaseCount += item.count; + that.currentLevelReleaseSize += item.size; // @ts-ignore + that.currentLevelReleaseCount += item.count; } } - }; + } for (let itemData of dbArray) { // @ts-ignore @@ -1239,17 +1228,17 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { private totalData(total: {}): {} { total = { existSizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelExistSize), - existSizePercent: ((this.currentLevelExistSize / this.currentLevelExistSize) * 100).toFixed(2), + existSizePercent: this.currentLevelExistSize === 0 ? 0 : ((this.currentLevelExistSize / this.currentLevelExistSize) * 100).toFixed(2), existCount: this.currentLevelExistCount, - existCountPercent: ((this.currentLevelExistCount / this.currentLevelExistCount) * 100).toFixed(2), + existCountPercent: this.currentLevelExistCount === 0 ? 0 : ((this.currentLevelExistCount / this.currentLevelExistCount) * 100).toFixed(2), releaseSizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelReleaseSize), - releaseSizePercent: ((this.currentLevelReleaseSize / this.currentLevelReleaseSize) * 100).toFixed(2), + releaseSizePercent: this.currentLevelReleaseSize === 0 ? 0 : ((this.currentLevelReleaseSize / this.currentLevelReleaseSize) * 100).toFixed(2), releaseCount: this.currentLevelReleaseCount, - releaseCountPercent: ((this.currentLevelReleaseCount / this.currentLevelReleaseCount) * 100).toFixed(2), + releaseCountPercent: this.currentLevelReleaseCount === 0 ? 0 : ((this.currentLevelReleaseCount / this.currentLevelReleaseCount) * 100).toFixed(2), applySizeFormat: Utils.getBinaryByteWithUnit(this.currentLevelApplySize), - applySizePercent: ((this.currentLevelApplySize / this.currentLevelApplySize) * 100).toFixed(2), + applySizePercent: this.currentLevelApplySize === 0 ? 0 : ((this.currentLevelApplySize / this.currentLevelApplySize) * 100).toFixed(2), applyCount: this.currentLevelApplyCount, - applyCountPercent: ((this.currentLevelApplyCount / this.currentLevelApplyCount) * 100).toFixed(2), + applyCountPercent: this.currentLevelApplyCount === 0 ? 0 : ((this.currentLevelApplyCount / this.currentLevelApplyCount) * 100).toFixed(2), existSize: 0, tableName: '', tName: '', @@ -1263,7 +1252,7 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { let nmCurrentTable: LitTable | null | undefined; switch (this.currentLevel) { case 0: - nmCurrentTable = this.tableType; + nmCurrentTable = this.typeUsageTbl; break; case 1: nmCurrentTable = this.threadUsageTbl; @@ -1430,26 +1419,26 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { } } + resizeTable(): void { + this.resize(this.typeUsageTbl); + this.resize(this.threadUsageTbl); + this.resize(this.soUsageTbl); + this.resize(this.functionUsageTbl); + } + + resize(table?: LitTable | null): void { + if (table) { + // @ts-ignore + table.shadowRoot.querySelector('.table').style.height = `${this.parentElement.clientHeight - 65}px`; + table.reMeauseHeight(); + } + } + public connectedCallback(): void { new ResizeObserver(() => { + this.resizeTable(); // @ts-ignore if (this.parentElement?.clientHeight !== 0) { - if (this.tableType) { - // @ts-ignore - this.tableType.shadowRoot.querySelector('.table').style.height = this.parentElement.clientHeight - 40 + 'px'; - } - this.tableType?.reMeauseHeight(); - if (this.soUsageTbl) { - // @ts-ignore - this.soUsageTbl.shadowRoot.querySelector('.table').style.height = this.parentElement.clientHeight - 40 + 'px'; - } - if (this.functionUsageTbl) { - // @ts-ignore - this.functionUsageTbl.shadowRoot.querySelector('.table').style.height = - this.parentElement!.clientHeight - 40 + 'px'; - } - this.soUsageTbl?.reMeauseHeight(); - this.functionUsageTbl?.reMeauseHeight(); if ((this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) || this.isStatistic) { this.filterEl!.style.display = 'none'; this.nmPieChart!.style.marginBottom = '0px'; diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts index 34b75983a143508f022b5b466eff324faf02f365..2b09465d2ee77d0ba68f75bc3f8cda537d1f2afd 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts @@ -33,6 +33,8 @@ import { import { SpNativeMemoryChart } from '../../../chart/SpNativeMemoryChart'; import { Utils } from '../../base/Utils'; import { TabPaneNMemoryHtml } from './TabPaneNMemory.html'; +import { SpSystemTrace } from '../../../SpSystemTrace'; +import { TabPaneFlag } from '../../timer-shaft/TabPaneFlag'; @element('tabpane-native-memory') export class TabPaneNMemory extends BaseElement { @@ -56,6 +58,7 @@ export class TabPaneNMemory extends BaseElement { private sortType: number = 0; private responseTypes: unknown[] = []; private eventTypes: string[] = []; + private systemTrace: SpSystemTrace | undefined | null; set data(memoryParam: SelectionParam | unknown) { if (memoryParam === this.currentSelection) { @@ -274,6 +277,9 @@ export class TabPaneNMemory extends BaseElement { } initElements(): void { + this.systemTrace = document + .querySelector('body > sp-application') + ?.shadowRoot!.querySelector('#sp-system-trace'); this.loadingPage = this.shadowRoot?.querySelector('.loading'); this.progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar; this.memoryTbl = this.shadowRoot?.querySelector('#tb-native-memory'); @@ -282,8 +288,30 @@ export class TabPaneNMemory extends BaseElement { this.memoryTbl!.addEventListener('row-click', (e) => { // @ts-ignore let data = e.detail.data as NativeMemory; + data.isSelected = true; this.rowSelectData = data; this.setRightTableData(data); + // @ts-ignore + if ((e.detail as unknown).callBack) { + // @ts-ignore + (e.detail as unknown).callBack(true); + } + let flagList = this.systemTrace?.timerShaftEL!.sportRuler?.flagList || []; + flagList.forEach((it, i) => { + if (it.type === 'triangle') { + flagList.splice(i, 1); + } + }); + + for (let i = 0; i < flagList!.length; i++) { + if (flagList[i].time === data.startTs) { + flagList[i].type = 'triangle'; + flagList[i].selected = true; + } else { + flagList[i].type = ''; + flagList[i].selected = false; + } + } document.dispatchEvent( new CustomEvent('triangle-flag', { detail: { time: [data.startTs], type: 'triangle' }, @@ -415,7 +443,7 @@ export class TabPaneNMemory extends BaseElement { this.startNmMemoryWorker('native-memory-action', args, (results: unknown[]) => { let thread = new NativeHookCallInfo(); thread.threadId = nativeMemoryHook.threadId; - thread.threadName = Utils.THREAD_MAP.get(thread.threadId) || 'Thread'; + thread.threadName = Utils.getInstance().getThreadMap().get(thread.threadId) || 'Thread'; thread.symbol = `${nativeMemoryHook.threadName ?? ''}【${nativeMemoryHook.threadId}】`; thread.type = -1; let currentSource = []; diff --git a/ide/src/trace/component/trace/sheet/parallel/ParallelUtil.ts b/ide/src/trace/component/trace/sheet/parallel/ParallelUtil.ts new file mode 100644 index 0000000000000000000000000000000000000000..ad53acd3d75f3620727833b52ab9e4bd111d3dc1 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/parallel/ParallelUtil.ts @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2024 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 { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; + +//并行度逻辑处理 +export function HanldParalLogic( + func: (dumpObj: any, value?: any, param?: any) => any, + value: any, + param?: any): any { + let arr = value.stateItem; + let waitArr: any = []; + let globalTs: number = 0; + let index: number = 0; + while (index < arr.length || waitArr.length > 0) { + let minEndTs = Math.min(...waitArr.map((item: any) => item.endTs)); + let minIndex = waitArr.findIndex((item: any) => item.endTs === minEndTs); + //当waitArr为空时 + if (waitArr.length === 0) { + globalTs = arr[index].ts; + waitArr.push(arr[index]); + index++; + continue; + } + //当全局Ts等于minEndTs时,只做删除处理 + if (globalTs === minEndTs) { + if (minIndex !== -1) { waitArr.splice(minIndex, 1) }; + continue; + } + let list = JSON.parse(JSON.stringify(waitArr)); + let dumpObj = { + ts: 0, + endTs: 0, + listSlice: [], + len: 0 + } + //判断原队列的数据是否被用完,即是否为空 + if (index < arr.length) { + if (arr[index].ts < minEndTs) { + if (globalTs === arr[index].ts) { + waitArr.push(arr[index]); + index++; + continue; + } else { + dumpObj = { + ts: globalTs, + endTs: arr[index].ts, + listSlice: list, + len: list.length + }; + waitArr.push(arr[index]); + globalTs = arr[index].ts; + index++; + } + } else if (arr[index].ts >= minEndTs) { + dumpObj = { + ts: globalTs, + endTs: minEndTs, + listSlice: list, + len: list.length + }; + globalTs = minEndTs; + if (minIndex !== -1) { waitArr.splice(minIndex, 1) }; + } + } else { + dumpObj = { + ts: globalTs, + endTs: minEndTs, + listSlice: list, + len: list.length + }; + globalTs = minEndTs; + if (minIndex !== -1) { waitArr.splice(minIndex, 1) }; + } + param = func(dumpObj, value, param); + } + return param +} + +//表头点击事件 +export function MeterHeaderClick(tab: LitTable | null | undefined, data: Array): void { + let labels = tab?.shadowRoot + ?.querySelector('.th > .td')! + .querySelectorAll('label'); + if (labels) { + for (let i = 0; i < labels.length; i++) { + let label = labels[i].innerHTML; + labels[i].addEventListener('click', (e) => { + if (label.includes('Process') && i === 0) { + tab!.setStatus(data, false); + tab!.recycleDs = + tab!.meauseTreeRowElement( + data, + RedrawTreeForm.Retract + ); + } else if (label.includes('Core') && i === 1) { + tab!.setStatus(data, true); + tab!.recycleDs = + tab!.meauseTreeRowElement( + data, + RedrawTreeForm.Expand + ); + } + }); + } + } +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts b/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts new file mode 100644 index 0000000000000000000000000000000000000000..ee25795d0939f0af5b30847a9342e71b3ebaef88 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts @@ -0,0 +1,435 @@ +/* + * 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'; +import '../../../../../base-ui/radiobox/LitRadioBox'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; +import '../../../../../base-ui/popover/LitPopoverV'; +import { LitPopover } from '../../../../../base-ui/popover/LitPopoverV'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; +import { queryCoreRunningThread } from '../../../../database/sql/ProcessThread.sql'; +import { MtSettingHtml } from '../TabPaneMt.html'; +import { LitCheckBox } from '../../../../../base-ui/checkbox/LitCheckBox'; +import '../../../../../base-ui/checkbox/LitCheckBox'; +import { MeterHeaderClick, HanldParalLogic } from './ParallelUtil'; +import { TabPaneFilter } from '../TabPaneFilter'; +import { Utils } from '../../base/Utils'; + +const UNIT: number = 1000000.0; +const NUM_DIGITS: number = 3; +const CORE_NUM: number = 12; +const SMALL_CPU_NUM: Array = [0, 1, 2, 3]; +const MID_CPU_NUM12: Array = [4, 5, 6, 7, 8, 9]; +const LARGE_CPU_NUM12: Array = [10, 11]; +const CORE_JSON = { + 'group1': [4, 5], + 'group2': [6, 7], + 'group3': [8, 9], + 'group4': [10, 11], +}; +export class CpuStatus { + cpu: number = 0; + small: boolean = false; + medium: boolean = false; + large: boolean = false; +} +@element('tabpane-mt-parallel') +export class TabPaneMtParallel extends BaseElement { + private parallelTable: LitTable | null | undefined; + private litSettingPopoverEl: LitPopover | null | undefined; + private litGourpPopoverEl: LitPopover | null | undefined; + private cpuTbl: HTMLDivElement | null | undefined; + private groupContentDiv: HTMLDivElement | null | undefined; + private selectionParam: SelectionParam | undefined; + private dataSourceMap: Map = new Map(); + private leftStartNs: number = 0; + private rightEndNs: number = 0; + private midCores: Array = []; + private largeCores: Array = []; + private smallCores: Array = []; + private isCreateCpu: boolean = true; + private isCreateGroup: boolean = true; + private coreTypeMap: Map = new Map(); + private bottomFilterEl: TabPaneFilter | null | undefined; + private addGroupArr: Array = []; + private bufferGroupMap: Map> = new Map(); + private isReset: boolean = true; + + set data(threadStatesParam: SelectionParam) { + if (this.selectionParam === threadStatesParam) { return; }; + this.selectionParam = threadStatesParam; + this.leftStartNs = this.selectionParam!.leftNs + this.selectionParam!.recordStartNs; + this.rightEndNs = this.selectionParam!.rightNs + this.selectionParam!.recordStartNs; + this.isCreateCpu = true; + this.parallelTable!.recycleDataSource = []; + this.initDefaultConfig(); + this.resetSomeConfig(false); + } + initElements(): void { + this.parallelTable = this.shadowRoot!.querySelector('#tb-parallel'); + this.bottomFilterEl = this.shadowRoot?.querySelector('#filter'); + this.litSettingPopoverEl = this.bottomFilterEl?.shadowRoot?.querySelector('#data-core-popover'); + this.litGourpPopoverEl = this.bottomFilterEl?.shadowRoot?.querySelector('#group-mining-popover'); + this.cpuTbl = this.litGourpPopoverEl!.querySelector('#tb_cpu'); + this.groupContentDiv = this.litGourpPopoverEl!.querySelector('.add_content'); + this.cpuSettingElListener(); + this.groupSettingElListener(); + } + //Cpu Setting 气泡相关按钮监听 + cpuSettingElListener(): void { + this.litSettingPopoverEl!.querySelector('#core-mining')!.onclick = (e): void => { + if (this.isCreateCpu) { + this.initDefaultConfig(); + this.isCreateCpu = false; + this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.smallCores, this.midCores, this.largeCores); + }; + } + this.litSettingPopoverEl!.querySelector('.confirm-button')!.addEventListener('click', (e: any) => { + this.resetSomeConfig(true); + }); + this.litSettingPopoverEl!.querySelector('.reset-button')!.addEventListener('click', (e: any) => { + this.isCreateCpu = true; + this.initDefaultConfig(); + this.resetSomeConfig(false); + }); + } + //Group Setting 气泡相关按钮监听 + groupSettingElListener(): void { + this.litGourpPopoverEl!.querySelector('#group-mining')!.addEventListener('click', (e: any) => { + this.addGroupArr = []; + if (this.isCreateGroup) { + this.groupContentDiv!.innerHTML = ''; + this.getGroupTableLine(); + //如果核数为12,默认配置分组 + if (Utils.getInstance().getWinCpuCount() == CORE_NUM && this.isReset) { + this.isReset = false; + const myMap = new Map(Object.entries(CORE_JSON)); + for (const val of myMap.values()) { + this.initGroupFn(val); + } + } + } else { + this.getGroupTableLine(); + } + }); + this.litGourpPopoverEl!.querySelector('.add_group_button')!.addEventListener('click', (e: any) => { + this.initGroupFn(this.addGroupArr); + //每次需要添加的数组,在每次添加完后清空 + this.addGroupArr = []; + }) + this.litGourpPopoverEl!.querySelector('.cut_group_button')!.addEventListener('click', (e: any) => { + //支持撤回已配置好的分组 + if (!this.groupContentDiv!.childNodes.length) { return }; + let parts: any = this.groupContentDiv!.lastChild!.textContent?.split(':'); + if (this.bufferGroupMap.has(parts[0])) { this.bufferGroupMap.delete(parts[0]) }; + this.groupContentDiv!.removeChild(this.groupContentDiv!.lastChild!); + this.addGroupArr = []; + this.getGroupTableLine('cut'); + }) + this.litGourpPopoverEl!.querySelector('.confirm-group-button')!.addEventListener('click', (e: any) => { + this.updateDataSource(true); + // @ts-ignore + this.litGourpPopoverEl!.visible = false; + }) + this.litGourpPopoverEl!.querySelector('.reset-group-button')!.addEventListener('click', (e: any) => { + this.resetGroup(false); + this.isCreateCpu = true; + this.initDefaultConfig(); + this.updateDataSource(false); + // @ts-ignore + this.litGourpPopoverEl!.visible = false; + }); + } + //group setting 重置 + resetGroup(isRest: boolean): void { + this.isCreateGroup = true; + this.bufferGroupMap.clear(); + this.isReset = !isRest; + } + //当cpu setting点击重置或者确认时,需要重置Group setting的数据 + resetSomeConfig(isRest: boolean): void { + this.resetGroup(isRest); + this.updateDataSource(isRest); + // @ts-ignore + this.litSettingPopoverEl!.visible = false; + } + //更新treeData + updateDataSource(flag: boolean): void { + let param = flag ? this.bufferGroupMap.size !== 0 : Utils.getInstance().getWinCpuCount() === CORE_NUM; + let value = flag ? this.bufferGroupMap : new Map(Object.entries(CORE_JSON)); + if ((this.midCores.length || this.largeCores.length || this.smallCores.length) && param) { + this.coreTypeMap.clear(); + this.dataSourceMap.clear(); + this.parallelTable!.loading = true; + this.getMtParallelData(value).then(() => { + this.parallelTable!.recycleDataSource = [...this.dataSourceMap.values()]; + this.parallelTable!.loading = false; + MeterHeaderClick(this.parallelTable, [...this.dataSourceMap.values()]); + }); + } else { + this.parallelTable!.recycleDataSource = []; + MeterHeaderClick(this.parallelTable, []); + } + } + async getMtParallelData(obj: Map) { + let cpuObj: any = { 'L': this.largeCores, 'M': this.midCores, 'S': this.smallCores }; + let processIds: Array = [...new Set(this.selectionParam!.processIds)]; + for (const [key, cpuGroup] of obj.entries()) { + //判断配的的组是否在同一个核分类中,如果在,返回是那个核分类,反之,返回null + let core = this.handleSamePhysicsCore(cpuGroup, cpuObj); + if (core === null) { continue }; + let res: any = await queryCoreRunningThread(processIds, this.selectionParam!.threadIds, cpuGroup, this.leftStartNs, this.rightEndNs); + this.handleTreeProcessData(res, core, key, cpuGroup); + } + //计算根节点数据并处理第二层数据的单位及保留位数 + for (const [i, item] of this.coreTypeMap) { + if (this.dataSourceMap.has(`${item.pid}`)) { + let obj = this.dataSourceMap.get(`${item.pid}`); + item.allParallel = ((item.parallelDur * item.parallelNum / item.dur) * 100).toFixed(NUM_DIGITS); + obj.dur += item.dur; + obj.parallelDur += item.parallelDur; + obj.load += item.load; + obj.parallelNum = item.parallelNum; + item.dur = (item.dur / UNIT).toFixed(NUM_DIGITS); + item.parallelDur = (item.parallelDur / UNIT).toFixed(NUM_DIGITS); + item.load = item.load.toFixed(NUM_DIGITS); + obj.children.push(item); + } + } + //处理根节点数据的单位及保留位数 + for (const [i, item] of this.dataSourceMap) { + item.allParallel = ((item.parallelDur * item.parallelNum / item.dur) * 100).toFixed(NUM_DIGITS); + item.dur = (item.dur / UNIT).toFixed(NUM_DIGITS); + item.parallelDur = (item.parallelDur / UNIT).toFixed(NUM_DIGITS); + item.load = item.load.toFixed(NUM_DIGITS); + } + } + + //判断自配的相同物理核是否符合计算MT并行度的要求 + handleSamePhysicsCore(arr: any, obj: { 'L': Array; 'M': Array; 'S': Array }): string | null { + let core = null; + if (arr.length > 2) { return null } + for (const [key, val] of Object.entries(obj)) { + let isSet = val.includes(arr[0]) && val.includes(arr[1]) + if (isSet) { + core = key; + } + } + return core + } + + handleTreeProcessData(result: any, key: string, gourpKey: string, gourp: Array): void { + let coreMap: Map = new Map(); + for (let i = 0; i < result.length; i++) { + let stateItem = result[i]; + //处理框选区域前后的边界ts + if (stateItem.ts < this.leftStartNs) { + stateItem.ts = this.leftStartNs; + } + if (stateItem.endTs > this.rightEndNs) { + stateItem.endTs = this.rightEndNs; + } + let dur = stateItem.endTs - stateItem.ts; + //以pid为key值添加MTTable数据源的最外层数据结构 + if (!this.dataSourceMap.has(`${stateItem.pid}`)) { + this.dataSourceMap.set(`${stateItem.pid}`, { + pid: stateItem.pid, + tid: stateItem.tid, + title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`, + group: '', + dur: null, + parallelNum: null, + parallelDur: null, + allParallel: null, + load: null, + tCount: null, + children: [] + }); + }; + if (coreMap.has(`${stateItem.pid}`)) { + let obj = coreMap.get(`${stateItem.pid}`); + let setArr = new Set(obj.tidArr); + if (!(setArr.has(stateItem.tid))) { + setArr.add(stateItem.tid); + obj.tidArr.push(stateItem.tid); + } + obj.gourpDur += dur; + obj.stateItem.push(stateItem); + } else { + coreMap.set(`${stateItem.pid}`, { + pid: stateItem.pid, + tid: stateItem.tid, + gourpDur: dur, + tidArr: [stateItem.tid], + stateItem: [stateItem], + }); + }; + }; + this.mergeTreeCoreData(coreMap, key, gourpKey, gourp) + } + //处理树结构最终需要的信息数据 + mergeTreeCoreData(map: Map, coreKey: string, gourpKey: string, gourp: Array): void { + let str = gourp.join(','); + for (const [key, value] of map) { + let pDur: number = 0; + pDur = HanldParalLogic(this.hanldMapLogic, value, pDur); + let paral = (pDur * gourp.length / value.gourpDur) * 100; + let load = value.gourpDur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount()); + let groupObj = { + pid: value.pid, + tid: value.tid, + title: '', + group: `${gourpKey}:${str}`, + dur: (value.gourpDur / UNIT).toFixed(NUM_DIGITS), + parallelNum: gourp.length, + parallelDur: (pDur / UNIT).toFixed(NUM_DIGITS), + allParallel: paral.toFixed(NUM_DIGITS), + load: load.toFixed(NUM_DIGITS), + tCount: value.tidArr.length, + children: [] + } + if (this.coreTypeMap.has(`${value.pid} ${coreKey}`)) { + let obj = this.coreTypeMap.get(`${value.pid} ${coreKey}`); + obj.dur += value.gourpDur; + obj.parallelDur += pDur; + obj.load += load; + obj.children.push(groupObj); + } else { + this.coreTypeMap.set(`${value.pid} ${coreKey}`, { + pid: value.pid, + tid: value.tid, + title: `${coreKey}`, + group: '', + dur: value.gourpDur, + parallelNum: gourp.length, + parallelDur: pDur, + allParallel: null, + load: load, + tCount: null, + children: [groupObj] + }); + } + } + } + + //每次stateItem计算的的结果 + hanldMapLogic(dumpObj: any, value?: any, param?: any): void { + if (dumpObj.len !== 1) { + param += dumpObj.endTs - dumpObj.ts; + } + return param + } + //初始化cpu check状态 + initDefaultConfig(): void { + if (this.isCreateCpu) { + if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { + this.smallCores = [...SMALL_CPU_NUM]; + this.midCores = [...MID_CPU_NUM12]; + this.largeCores = [...LARGE_CPU_NUM12]; + } else { + this.smallCores = []; + this.midCores = []; + this.largeCores = []; + } + } + } + + //初始化分组 + initGroupFn(arr: any): void { + let info = [...this.bufferGroupMap.values()].reduce((acc, val) => acc.concat(val), []); + let flag = arr.filter((item: any) => info.includes(item)).length > 0; + if (arr.length && arr.length > 1 && !flag) { + let len = this.groupContentDiv!.childNodes.length + 1; + let str = arr.join(','); + this.bufferGroupMap.set(`group${len}`, arr); + this.groupContentDiv!.innerHTML += `
group${len}:${str}
`; + } + } + //更新Group Setting Cpu列的展示与操作状态 + getGroupTableLine(str?: string): void { + this.isCreateGroup = false; + this.cpuTbl!.innerHTML = ''; + this.creatCpuHeaderDiv(); + let bufferInfo = [...this.bufferGroupMap.values()].reduce((acc, val) => acc.concat(val), []); + let switchArr = Object.values(CORE_JSON).flat(); + for (let i = 0; i < Utils.getInstance().getWinCpuCount(); i++) { + let obj = { + cpu: i, + isCheck: Utils.getInstance().getWinCpuCount() == CORE_NUM && str !== 'cut' && this.isReset ? switchArr.includes(i) : bufferInfo.includes(i), + disabled: + Utils.getInstance().getWinCpuCount() == CORE_NUM && str !== 'cut' && this.isReset ? + !(switchArr.includes(i)) : + !([...this.smallCores, ...this.midCores, ...this.largeCores].includes(i)) + }; + this.creatGroupLineDIv(obj); + } + } + //创建cpu表头 + creatCpuHeaderDiv(): void { + let cpuIdLine = document.createElement('div'); + cpuIdLine.className = 'core_line'; + cpuIdLine.style.fontWeight = 'bold'; + cpuIdLine.style.fontStyle = '12px'; + cpuIdLine.textContent = 'Cpu'; + cpuIdLine.style.textAlign = 'center'; + this.cpuTbl?.append(...[cpuIdLine]); + } + //Gropu容器中新增Tbl的cpu Line值 + creatGroupLineDIv(obj: any): void { + let id = `${obj.cpu}`.toString(); + let checkBoxId = `box${id}`; + // 创建一个包裹div来容纳checkbox和cpuLine + let wrapperDiv = document.createElement('div'); + wrapperDiv.className = 'check-content'; + wrapperDiv.id = checkBoxId; + // 创建checkBox实例 + let checkBox: LitCheckBox = new LitCheckBox(); + checkBox.checked = obj.isCheck; + checkBox.disabled = obj.disabled; + checkBox.setAttribute('not-close', ''); + // 添加事件监听器到checkBox + checkBox.addEventListener('change', (e: any) => { + checkBox.checked = e.detail.checked; + this.bottomFilterEl!.canUpdateCheckList(e.detail.checked, this.addGroupArr, obj.cpu); + }); + wrapperDiv.appendChild(checkBox); + // 创建cpuLine div + let cpuLine = document.createElement('div'); + cpuLine.textContent = obj.cpu + ''; + cpuLine.style.textAlign = 'center'; + cpuLine.style.fontWeight = 'normal'; + // 将cpuLine也添加到wrapperDiv + wrapperDiv.appendChild(cpuLine); + this.cpuTbl!.append(wrapperDiv); + } + //回调函数,首次插入DOM时执行的初始化回调 + connectedCallback(): void { + new ResizeObserver(() => { + if (this.parentElement?.clientHeight !== 0) { + // @ts-ignore + this.parallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight - 31}px`; + this.parallelTable?.reMeauseHeight(); + if (this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) { + this.bottomFilterEl!.style.display = 'none'; + } else { + this.bottomFilterEl!.style.display = 'flex'; + } + } + }).observe(this.parentElement!); + } + initHtml(): string { + return MtSettingHtml; + } +} diff --git a/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts b/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts new file mode 100644 index 0000000000000000000000000000000000000000..8edb6c098d477d3fd625f7a05bcc787ae4976376 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts @@ -0,0 +1,379 @@ +/* + * 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'; +import '../../../../../base-ui/checkbox/LitCheckBox'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import '../../../../../base-ui/popover/LitPopoverV'; +import { LitPopover } from '../../../../../base-ui/popover/LitPopoverV'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; +import { queryRunningThread, queryCoreRunningThread } from '../../../../database/sql/ProcessThread.sql'; +import { ClassifyCoreSettingHtml } from '../TabPaneTime.html'; +import { HanldParalLogic, MeterHeaderClick } from './ParallelUtil'; +import { TabPaneFilter } from '../TabPaneFilter'; +import { Utils } from '../../base/Utils'; + + +const UNIT: number = 1000000.0; +const NUM_DIGITS: number = 3; +const CORE_NUM: number = 12; +const SMALL_CPU_NUM: Array = [0, 1, 2, 3]; +const MID_CPU_NUM12: Array = [4, 5, 6, 7, 8, 9]; +const LARGE_CPU_NUM12: Array = [10, 11]; + +@element('tabpane-time-parallel') +export class TabPaneTimeParallel extends BaseElement { + private bottomFilterEl: TabPaneFilter | undefined | null; + private parallelTable: LitTable | null | undefined; + private coreParallelTable: LitTable | null | undefined; + private litPopoverEl: LitPopover | null | undefined; + private selectionParam: SelectionParam | undefined; + private initMap: Map = new Map(); + private leftStartNs: number = 0; + private rightEndNs: number = 0; + private midCores: Array = []; + private largeCores: Array = []; + private smallCores: Array = []; + private initStatus: boolean = true; + + set data(threadStatesParam: SelectionParam) { + if (this.selectionParam === threadStatesParam) { return; }; + this.selectionParam = threadStatesParam; + this.leftStartNs = this.selectionParam!.leftNs + this.selectionParam!.recordStartNs; + this.rightEndNs = this.selectionParam!.rightNs + this.selectionParam!.recordStartNs; + //每次新款选线程时清空Map对象 + this.initMap.clear(); + this.initStatus = true; + this.initDefaultConfig(); + this.parallelTable!.recycleDataSource = []; + this.coreParallelTable!.recycleDataSource = []; + this.switchTableInfo(); + } + initElements(): void { + this.parallelTable = this.shadowRoot!.querySelector('#tb-parallel'); + this.coreParallelTable = this.shadowRoot!.querySelector('#tb-core-parallel') + this.bottomFilterEl = this.shadowRoot?.querySelector('#filter'); + this.litPopoverEl = this.bottomFilterEl?.shadowRoot?.querySelector('#data-core-popover'); + this.litPopoverEl!.querySelector('#core-mining')!.onclick = (e): void => { + if (this.initStatus) { + this.initDefaultConfig(); + this.initStatus = false; + this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.smallCores, this.midCores, this.largeCores); + } + } + this.litPopoverEl!.querySelector('.confirm-button')!.addEventListener('click', (e: any) => { + this.switchTableInfo(); + }); + this.litPopoverEl!.querySelector('.reset-button')!.addEventListener('click', (e: any) => { + this.initStatus = true; + this.reset(); + }); + } + switchTableInfo(): void { + // @ts-ignore + this.litPopoverEl!.visible = false; + //当大中小核未分组时,默认查询所有核 + if (!this.midCores.length && !this.largeCores.length && !this.smallCores.length) { + this.assignAllCore(); + } else { + this.assignGroupCore(); + } + } + + reset() { + // @ts-ignore + this.litPopoverEl!.visible = false; + if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { + this.coreParallelTable!.style.display = 'grid' + this.parallelTable!.style.display = 'none'; + this.coreParallelTable!.loading = true; + this.coreParallelTable!.recycleDataSource = [...this.initMap.values()]; + this.coreParallelTable!.loading = false; + MeterHeaderClick(this.coreParallelTable, [...this.initMap.values()]); + } else { + this.parallelTable!.style.display = 'grid' + this.coreParallelTable!.style.display = 'none'; + this.parallelTable!.loading = true; + this.parallelTable!.recycleDataSource = [...this.initMap.values()]; + this.parallelTable!.loading = false; + } + } + + assignAllCore() { + this.parallelTable!.style.display = 'grid' + this.coreParallelTable!.style.display = 'none'; + this.parallelTable!.loading = true; + this.getAllCoreData().then((res) => { + if (this.initMap.size === 0) { this.initMap = res; } + this.parallelTable!.recycleDataSource = [...res.values()]; + this.parallelTable!.loading = false; + }); + } + + assignGroupCore() { + this.coreParallelTable!.style.display = 'grid' + this.parallelTable!.style.display = 'none'; + this.coreParallelTable!.loading = true; + this.getCoreGroupData().then((res) => { + if (this.initMap.size === 0) { this.initMap = res; } + this.coreParallelTable!.recycleDataSource = [...res.values()]; + this.coreParallelTable!.loading = false; + MeterHeaderClick(this.coreParallelTable, [...res.values()]); + }); + } + + initDefaultConfig(): void { + if (this.initStatus) { + if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { + this.smallCores = [...SMALL_CPU_NUM]; + this.midCores = [...MID_CPU_NUM12]; + this.largeCores = [...LARGE_CPU_NUM12]; + } else { + this.smallCores = []; + this.midCores = []; + this.largeCores = []; + } + } + } + + //获取每次被框选线程对应的state数据 + async getAllCoreData(): Promise { + let dataSourceMap: Map = new Map(); + let processIds: Array = [...new Set(this.selectionParam!.processIds)]; + let res: any = await queryRunningThread(processIds, this.selectionParam!.threadIds, this.leftStartNs, this.rightEndNs); + this.handleAllParallelData(res, dataSourceMap); + return dataSourceMap + } + //获取核分类数据 + async getCoreGroupData(): Promise { + let dataSourceMap: Map = new Map(); + let processIds: Array = [...new Set(this.selectionParam!.processIds)]; + let cpuObj: Object = { + 'L': this.largeCores, + 'M': this.midCores, + 'S': this.smallCores + } + for (const [key, val] of Object.entries(cpuObj)) { + if (val.length) { + let res: any = await queryCoreRunningThread(processIds, this.selectionParam!.threadIds, val, this.leftStartNs, this.rightEndNs); + this.hanldeGroupParalleData(res, key, dataSourceMap); + }; + } + //转换最外层数据单位即保留三位小数 + for (const [i, item] of dataSourceMap) { + item.dur = (item.dur / UNIT).toFixed(NUM_DIGITS); + item.load = item.load.toFixed(NUM_DIGITS) + } + return dataSourceMap + } + //处理未按核分组的数据 + handleAllParallelData(param: any, dataSourceMap: Map): void { + for (let i = 0; i < param.length; i++) { + let stateItem = param[i]; + if (stateItem.ts < this.leftStartNs) { + stateItem.ts = this.leftStartNs; + } + if (stateItem.endTs > this.rightEndNs) { + stateItem.endTs = this.rightEndNs; + } + let dur = stateItem.endTs - stateItem.ts; + if (dataSourceMap.has(`${stateItem.pid}`)) { + let obj = dataSourceMap.get(`${stateItem.pid}`); + let setArr = new Set(obj.tidArr); + if (!(setArr.has(stateItem.tid))) { + setArr.add(stateItem.tid); + obj.tidArr.push(stateItem.tid); + } + obj.dur += dur; + obj!.stateItem.push(stateItem) + } else { + dataSourceMap.set(`${stateItem.pid}`, { + pid: stateItem.pid, + tid: stateItem.tid, + title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`, + tidArr: [stateItem.tid], + dur: dur, + parallelNum: null, + allParallel: null, + stateItem: [stateItem], + tCount: null, + load: null, + pDur: null, + children: [] + }); + }; + }; + this.showTreeChart(dataSourceMap); + } + //处理核分组数据 + hanldeGroupParalleData(val: any, key: string, dataSourceMap: Map): void { + let coreMap: Map = new Map(); + for (let i = 0; i < val.length; i++) { + let stateItem = val[i]; + if (stateItem.ts < this.leftStartNs) { + stateItem.ts = this.leftStartNs; + } + if (stateItem.endTs > this.rightEndNs) { + stateItem.endTs = this.rightEndNs; + } + let dur = stateItem.endTs - stateItem.ts; + if (!dataSourceMap.has(`${stateItem.pid}`)) { + dataSourceMap.set(`${stateItem.pid}`, { + pid: stateItem.pid, + tid: stateItem.tid, + title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`, + dur: null, + parallelNum: null, + parallelDur: null, + allParallel: null, + tCount: null, + load: null, + pDur: null, + children: [] + }); + }; + if (coreMap.has(`${stateItem.pid} ${key}`)) { + let obj = coreMap.get(`${stateItem.pid} ${key}`); + let setArr = new Set(obj.tidArr); + if (!(setArr.has(stateItem.tid))) { + setArr.add(stateItem.tid); + obj.tidArr.push(stateItem.tid); + } + obj.dur += dur; + obj!.stateItem.push(stateItem) + } else { + coreMap.set(`${stateItem.pid} ${key}`, { + pid: stateItem.pid, + tid: stateItem.tid, + title: `${key}`, + tidArr: [stateItem.tid], + dur: dur, + parallelNum: null, + parallelDur: null, + allParallel: null, + stateItem: [stateItem], + tCount: null, + load: null, + pDur: null, + children: [] + }); + }; + }; + this.showCoreTreeChart(coreMap, dataSourceMap) + } + + showTreeChart(param: Map): void { + for (let [key, value] of param) { + let pMap: Map = new Map(); + HanldParalLogic(this.hanldMapLogic, value, pMap); + value.tCount = value.tidArr.length; + value.load = (value.dur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount())).toFixed(NUM_DIGITS); + value.dur = (value.dur / UNIT).toFixed(NUM_DIGITS); + if (pMap.size === 0) { + value.allParallel = 0.000.toFixed(NUM_DIGITS); + } else { + for (const [i, item] of pMap) { + value.allParallel += item.allParallel; + item.allParallel = item.allParallel.toFixed(NUM_DIGITS); + } + value.allParallel = value.allParallel.toFixed(NUM_DIGITS); + value.children = [...pMap.values()]; + } + } + } + + showCoreTreeChart(param: any, dataSourceMap: Map): void { + for (let [key, value] of param) { + let pMap: Map = new Map(); + pMap = HanldParalLogic(this.hanldMapLogic, value, pMap); + value.load = (value.dur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount())); + if (pMap.size === 0) { + value.allParallel = 0.000; + value.parallelNum = '-'; + value.parallelDur = '-'; + } else { + for (const [i, item] of pMap) { + value.allParallel += item.allParallel; + item.allParallel = item.allParallel; + item.allParallel = item.allParallel.toFixed(NUM_DIGITS); + } + value.children = [...pMap.values()]; + } + if (dataSourceMap.has(`${value.pid}`)) { + let obj = dataSourceMap.get(`${value.pid}`); + value.tCount = value.tidArr.length; + obj.dur += value.dur; + obj.load += value.load; + value.allParallel = value.allParallel.toFixed(NUM_DIGITS); + value.dur = (value.dur / UNIT).toFixed(NUM_DIGITS); + value.load = value.load.toFixed(NUM_DIGITS); + obj.children.push(value); + } + } + } + //每次stateItem计算的的结果,处理对应map的值 + hanldMapLogic(dumpObj: any, value?: any, pMap?: any) { + let pDur = dumpObj.endTs - dumpObj.ts; + let pSlice = ((dumpObj.len * pDur) / value.dur) * 100; + if (pMap!.has(dumpObj.len.toString())) { + let pObj = pMap!.get(dumpObj.len.toString()); + pObj.allParallel += pSlice; + pObj.pDur += pDur; + pObj.parallelDur = `${((pObj.pDur) / UNIT).toFixed(NUM_DIGITS)}`; + } else { + if (dumpObj.len !== 1) { + pMap!.set(dumpObj.len.toString(), { + pid: null, + tid: null, + title: '', + tidArr: value.tidArr, + dur: null, + allParallel: pSlice, + parallelNum: dumpObj.len, + parallelDur: ((pDur) / UNIT).toFixed(NUM_DIGITS), + pDur: pDur, + stateItem: value.stateItem, + tCount: null, + load: '-', + children: [] + }) + } + } + return pMap + } + + //回调函数,首次插入DOM时执行的初始化回调 + connectedCallback(): void { + super.connectedCallback(); + new ResizeObserver(() => { + if (this.parentElement?.clientHeight !== 0) { + // @ts-ignore + this.parallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight -31}px`; + this.parallelTable?.reMeauseHeight(); + // @ts-ignore + this.coreParallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight -31}px`;; + this.coreParallelTable?.reMeauseHeight(); + if (this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) { + this.bottomFilterEl!.style.display = 'none'; + } else { + this.bottomFilterEl!.style.display = 'flex'; + } + } + }).observe(this.parentElement!); + } + initHtml(): string { + return ClassifyCoreSettingHtml; + } +} diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts index c67283191feb02c7116e88c986f61e4363ddc28a..4cbca41cfc03a83f7185ccf64e2eae1539ab5284 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts @@ -16,14 +16,14 @@ import { BaseElement, element } from '../../../../../base-ui/BaseElement'; import { LitTable } from '../../../../../base-ui/table/lit-table'; import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; -import { SpAllocations } from '../../../setting/SpAllocations'; import { SpSystemTrace } from '../../../SpSystemTrace'; import { TraceRow } from '../../base/TraceRow'; import { LitSearch } from '../../search/Search'; import { resizeObserver } from '../SheetUtils'; -import { getTabSlicesAsyncFunc, getTabSlicesAsyncCatFunc} from '../../../../database/sql/Func.sql'; +import { getTabSlicesAsyncFunc, getTabSlicesAsyncCatFunc } from '../../../../database/sql/Func.sql'; import { getTabSlices } from '../../../../database/sql/ProcessThread.sql'; -import { FuncStruct } from '.././../../../database/ui-worker/ProcedureWorkerFunc'; +import { FuncStruct } from '../../../../database/ui-worker/ProcedureWorkerFunc'; +import { Utils } from '../../base/Utils'; @element('tabpane-slices') export class TabPaneSlices extends BaseElement { @@ -31,6 +31,7 @@ export class TabPaneSlices extends BaseElement { private slicesRange: HTMLLabelElement | null | undefined; private slicesSource: Array = []; private currentSelectionParam: SelectionParam | undefined; + private sliceSearchCount: Element | undefined | null; set data(slicesParam: SelectionParam | unknown) { if (this.currentSelectionParam === slicesParam) { @@ -48,10 +49,9 @@ export class TabPaneSlices extends BaseElement { asyncNames.push(it.name); //@ts-ignore asyncPid.push(it.pid); }); - let asyncCatNames: Array = []; let asyncCatPid: Array = [];//@ts-ignore - slicesParam.funCatAsync.forEach((it: unknown) => {//@ts-ignore + slicesParam.funCatAsync.forEach((it: unknown) => { //@ts-ignore asyncCatNames.push(it.threadName);//@ts-ignore asyncCatPid.push(it.pid); }); @@ -84,17 +84,17 @@ export class TabPaneSlices extends BaseElement { count.process = ' '; count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); count.occurrences = sumOcc; - processSlicesResult.splice(0, 0, count); + processSlicesResult.splice(0, 0, count); //@ts-ignore + this.slicesSource = processSlicesResult; + this.slicesTbl!.recycleDataSource = processSlicesResult; + this.sliceSearchCount!.textContent = this.slicesSource.length - 1 + ''; if (filterNameEL && filterNameEL.value.trim() !== '') { this.findName(filterNameEL.value); - } else { - //@ts-ignore - this.slicesSource = processSlicesResult; - this.slicesTbl!.recycleDataSource = processSlicesResult; } } else { this.slicesSource = []; this.slicesTbl!.recycleDataSource = this.slicesSource; + this.sliceSearchCount!.textContent = '0'; } } ); @@ -103,8 +103,14 @@ export class TabPaneSlices extends BaseElement { } initElements(): void { + this.sliceSearchCount = this.shadowRoot?.querySelector('#search-count'); this.slicesTbl = this.shadowRoot?.querySelector('#tb-slices'); this.slicesRange = this.shadowRoot?.querySelector('#time-range'); + let slicesInput = this.shadowRoot?.querySelector('#filterName'); + let spApplication = document.querySelector('body > sp-application'); + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; this.slicesTbl!.addEventListener('column-click', (evt) => { // @ts-ignore this.sortByColumn(evt.detail); @@ -118,31 +124,39 @@ export class TabPaneSlices extends BaseElement { this.slicesTbl!.addEventListener('click', () => { FuncStruct.funcSelect = false; // @ts-ignore - this.orgnazitionData(data); + data && this.orgnazitionData(data); }); this.slicesTbl!.addEventListener('contextmenu', () => { FuncStruct.funcSelect = true; // @ts-ignore - this.orgnazitionData(data); + data && this.orgnazitionData(data); }); - this.shadowRoot?.querySelector('#filterName')?.addEventListener('input', (e) => { + slicesInput?.addEventListener('input', (e) => { // @ts-ignore this.findName(e.target.value); }); + slicesInput?.addEventListener('focus', (e) => { + spSystemTrace.focusTarget = 'slicesInput'; + }); + slicesInput?.addEventListener('blur', (e) => { + spSystemTrace.focusTarget = ''; + }); } async orgnazitionData(data: Object): Promise { - let spApplication = document.querySelector('body > sp-application') as SpAllocations; + let spApplication = document.querySelector('body > sp-application'); let spSystemTrace = spApplication?.shadowRoot?.querySelector( 'div > div.content > sp-system-trace' ) as SpSystemTrace; - let search = spApplication.shadowRoot?.querySelector('#lit-search') as LitSearch; + let search = spApplication!.shadowRoot?.querySelector('#lit-search') as LitSearch; spSystemTrace?.visibleRows.forEach((it) => { it.highlight = false; it.draw(); }); spSystemTrace?.timerShaftEL?.removeTriangle('inverted'); // @ts-ignore - await spSystemTrace!.searchFunction([], data.name).then((mixedResults) => { + let asyncFuncArr = spSystemTrace!.seachAsyncFunc(data.name); + // @ts-ignore + await spSystemTrace!.searchFunction([], asyncFuncArr, data.name).then((mixedResults) => { if (mixedResults && mixedResults.length === 0) { return; } @@ -190,14 +204,17 @@ export class TabPaneSlices extends BaseElement { ) { // 异步调用栈 if (traceRow.asyncFuncName) { - // @ts-ignore - if (`${searchItem.pid}` === `${traceRow.asyncFuncNamePID}`) { + if ( + // @ts-ignore + `${searchItem.pid}` === `${traceRow.asyncFuncNamePID}` && + traceRow.traceId === Utils.currentSelectTrace + ) { rangeSelectList.push(searchItem); } } else { // 线程调用栈 // @ts-ignore - if (`${searchItem.tid}` === traceRow.rowId) { + if (Utils.getDistributedRowId(searchItem.tid) === traceRow.rowId) { rangeSelectList.push(searchItem); } } @@ -209,6 +226,8 @@ export class TabPaneSlices extends BaseElement { return; } //@ts-ignore input.value = data.name; + //@ts-ignore + search.currenSearchValue = data.name; search.list = rangeSelectList; search.total = search.list.length; search.index = spSystemTrace!.showStruct(true, 1, search.list); @@ -236,9 +255,12 @@ export class TabPaneSlices extends BaseElement { outline: none; } -
- - +
+
+ +   Count: 0 +
+
= JSON.parse(JSON.stringify(this.slicesTbl!.recycleDataSource)); + // 取出汇总数据,同时将排序数据去掉汇总数据进行后续排序 + let headData: SelectionData = sortData.splice(0,1)[0]; //@ts-ignore if (slicesDetail.key === 'name') { //@ts-ignore - this.slicesSource.sort(compare(slicesDetail.key, slicesDetail.sort, 'string')); + sortData.sort(compare(slicesDetail.key, slicesDetail.sort, 'string')); } else { //@ts-ignore - this.slicesSource.sort(compare(slicesDetail.key, slicesDetail.sort, 'number')); + sortData.sort(compare(slicesDetail.key, slicesDetail.sort, 'number')); } - this.slicesTbl!.recycleDataSource = this.slicesSource; + // 排序完成后将汇总数据插入到头部 + sortData.unshift(headData); + this.slicesTbl!.recycleDataSource = sortData; + this.sliceSearchCount!.textContent = sortData.length - 1 + ''; } findName(str: string): void { - // 有一个问题就是,是否要在筛选之后的表格上方显示总数据 let searchData: Array = []; let sumWallDuration: number = 0; let sumOccurrences: number = 0; if (str === '') { this.slicesTbl!.recycleDataSource = this.slicesSource; + this.sliceSearchCount!.textContent = this.slicesSource.length - 1 + ''; } else { this.slicesSource.forEach((item) => { if (item.name.toLowerCase().indexOf(str.toLowerCase()) !== -1) { @@ -319,6 +348,7 @@ export class TabPaneSlices extends BaseElement { count.occurrences = sumOccurrences; searchData.unshift(count); this.slicesTbl!.recycleDataSource = searchData; + this.sliceSearchCount!.textContent = searchData.length - 1 + ''; } } } diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts b/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts index a43b913953e8ad27db2af57419276b2bfc764a3a..d9722e988dd7045a3e4dc8d4be41c300640291f7 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneThreadStates.ts @@ -202,14 +202,15 @@ export class TabPaneThreadStates extends BaseElement { let sumWall = 0.0; let sumOcc = 0; let targetList = []; - + // @ts-ignore + let traceId = threadStatesParam.traceId; for (let e of targetListTemp) { // @ts-ignore if (threadStatesParam.processIds.includes(e.pid)) { // @ts-ignore - let process = Utils.PROCESS_MAP.get(e.pid); + let process = Utils.getInstance().getProcessMap(traceId).get(e.pid); // @ts-ignore - let thread = Utils.THREAD_MAP.get(e.tid); + let thread = Utils.getInstance().getThreadMap(traceId).get(e.tid); // @ts-ignore e.process = process || '[NULL]'; // @ts-ignore @@ -320,7 +321,7 @@ export class TabPaneThreadStates extends BaseElement { sortByColumn(treadStatesDetail: unknown): void { function compare(property: unknown, treadStatesSort: unknown, type: unknown) { - return function (threadStatesLeftData: SelectionData | unknown, threadStatesRightData: SelectionData | unknown) { + return function (threadStatesLeftData: SelectionData | unknown, threadStatesRightData: SelectionData | unknown): number { // @ts-ignore if (threadStatesLeftData.process === ' ' || threadStatesRightData.process === ' ') { return 0; diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts b/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts index ec029cff1d9dce62143b4f4dbc9da631bfba1a81..7a40e8c556db52a8b4978b43b42c6f591b5b41d2 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts @@ -55,9 +55,11 @@ export class TabPaneThreadUsage extends BaseElement { } // @ts-ignore this.currentSelectionParam = threadUsageParam; - if (this.cpuCount !== CpuStruct.cpuCount) { - this.cpuCount = CpuStruct.cpuCount; - this.threadUsageTbl!.innerHTML = this.getTableColumns(); + // @ts-ignore + let traceId = threadUsageParam.traceId; + if (this.cpuCount !== Utils.getInstance().getCpuCount(traceId)) { + this.cpuCount = Utils.getInstance().getCpuCount(traceId); // @ts-ignore + this.threadUsageTbl!.innerHTML = this.getTableColumns(traceId); } //@ts-ignore this.threadUsageTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${ @@ -114,9 +116,9 @@ export class TabPaneThreadUsage extends BaseElement { map.get(resultEl.tid).wallDurationTimeStr = getThreadUsageProbablyTime(map.get(resultEl.tid).wallDuration); } else { // @ts-ignore - let process = Utils.PROCESS_MAP.get(resultEl.pid); + let process = Utils.getInstance().getProcessMap(threadUsageParam.traceId).get(resultEl.pid); // @ts-ignore - let thread = Utils.THREAD_MAP.get(resultEl.tid); + let thread = Utils.getInstance().getThreadMap(threadUsageParam.traceId).get(resultEl.tid); let threadStatesStruct: unknown = { // @ts-ignore tid: resultEl.tid, @@ -161,9 +163,9 @@ export class TabPaneThreadUsage extends BaseElement { } } - getTableColumns(): string { + getTableColumns(traceId?: string | null): string { let threadUsageHtml = `${this.pubColumns}`; - let cpuCount = CpuStruct.cpuCount; + let cpuCount = Utils.getInstance().getCpuCount(traceId); for (let index = 0; index < cpuCount; index++) { threadUsageHtml = `${threadUsageHtml} ('#tb-running'); @@ -217,6 +217,10 @@ export class TabPaneSchedSwitch extends BaseElement { //@ts-ignore let data = evt.detail.data; if (data.level === 'process') { + //点击树节点时节点高亮 + data.isSelected = true; + this.schedSwitchTbl!.clearAllSelection(data); + this.schedSwitchTbl!.setCurrentSelection(data); //点击进程canvans相关内容隐藏 this.isCanvansHidden(true); SpSegmentationChart.setChartData('SCHED-SWITCH', []); @@ -246,12 +250,13 @@ export class TabPaneSchedSwitch extends BaseElement { color: '#2f72f8', }; this.histogramSource.push(this.rangeTotal); - //点击树节点时高亮 - data.isSelected = true; + //清空高亮的树节点 this.schedSwitchTbl!.clearAllSelection(data); - this.schedSwitchTbl!.setCurrentSelection(data); this.drawHistogramChart(); } + //点击树节点时高亮 + data.isSelected = true; + this.schedSwitchTbl!.setCurrentSelection(data); //点击线程绘制对应泳道图 SpSegmentationChart.setChartData('SCHED-SWITCH', data.children); } else if (data.level === 'cycle') { @@ -352,9 +357,9 @@ export class TabPaneSchedSwitch extends BaseElement { let group: { [key: number]: SchedSwitchCountBean } = {}; for (let value of this.threadMap.values()) { let cyclesArr: Array = []; - let processInfo: string | undefined = Utils.PROCESS_MAP.get(value[0].pid); + let processInfo: string | undefined = Utils.getInstance().getProcessMap().get(value[0].pid); let process: string | undefined = processInfo === null || processInfo!.length === 0 ? '[NULL]' : processInfo; - let threadInfo: string | undefined = Utils.THREAD_MAP.get(value[0].tid); + let threadInfo: string | undefined = Utils.getInstance().getThreadMap().get(value[0].tid); let thread: string | undefined = threadInfo === null || threadInfo!.length === 0 ? '[NULL]' : threadInfo; //整理出一个对象并将周期空数组放进对象里 let cutDataObj: CutDataObjConfig = { @@ -585,10 +590,7 @@ export class TabPaneSchedSwitch extends BaseElement { let tip = ''; //@ts-ignore for (let obj of a) { tip = `${tip} -
-
-
${obj.xLabel}:${obj.obj.average}
-
+
Average count:${obj.obj.average}
`; } return tip; diff --git a/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts b/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts index 9cf58e320803aa9a6845a579aeac476e2c2893e7..ea40b9952c97e63beed82c629de411f868e4fbb7 100644 --- a/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts +++ b/ide/src/trace/component/trace/sheet/sdk/TabPaneSdkSlice.ts @@ -376,8 +376,6 @@ export class TabPaneSdkSlice extends BaseElement { default: if (typeof sliceValue === 'string') { return sliceValue.replace(//gi, '>'); - } else { - return ''; } } } diff --git a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsComparison.ts b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsComparison.ts index 20edaf8e165e536659db84e4101e189901f7f1f6..3789db3376e8112738a6bdbec1a513c0da87df47 100644 --- a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsComparison.ts +++ b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsComparison.ts @@ -63,6 +63,7 @@ export class TabPaneSmapsComparison extends TabPaneSmapsStatistics { this.querySmapsData(data.leftNs, fileArr[0].startNs); } private initSelect(fileStartNs: number, smapsComFileArr: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; let option = new LitSelectOption(); @@ -82,7 +83,7 @@ export class TabPaneSmapsComparison extends TabPaneSmapsStatistics { // @ts-ignore if (input.value === f.name) { // @ts-ignore - this.querySmapsData(fileStartNs, f.startNs); + that.querySmapsData(fileStartNs, f.startNs); } } // @ts-ignore e.stopPropagation(); diff --git a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts index da1de4d16cc2961738495dee43b3a1b078803ed2..a067177d5f641eeeedc80470150f658997c5cf96 100644 --- a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts +++ b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsRecord.ts @@ -38,7 +38,7 @@ export class TabPaneSmapsRecord extends BaseElement { set data(smapsValue: SelectionParam | unknown) { this.smapsRecordDataSource = []; if (smapsValue) { - if (this.pixelmapId === -1) { + if (this.pixelmapId == -1) { for (let [key, value] of SpSystemTrace.DATA_DICT) { if (value === 'pixelmap') { this.pixelmapId = key; @@ -106,7 +106,7 @@ export class TabPaneSmapsRecord extends BaseElement { this.smapsRecordTable = this.shadowRoot?.querySelector('#smaps-record-tbl'); } - connectedCallback(): void { + connectedCallback() { super.connectedCallback(); resizeObserver(this.parentElement!, this.smapsRecordTable!); new ResizeObserver(() => { diff --git a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsSample.ts b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsSample.ts index fe622d0ceb6401a780397041da64bed356cad8d2..bd8211a375b769a2a9291525833efc2b064a1332 100644 --- a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsSample.ts +++ b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsSample.ts @@ -109,7 +109,7 @@ export class TabPaneSmapsSample extends BaseElement { smaps.permission = SpSystemTrace.DATA_DICT.get(smaps.pid)?.split('/'); let resideS = smaps.reside.toFixed(2); if (resideS === '0.00') { - smaps.resideStr = '0 %'; + smaps.resideStr = '0%'; } else { smaps.resideStr = resideS + '%'; } diff --git a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts index 327f5733322a10314c3ff767b282b9f52da55d55..6582c67845b5fd1860fc8abdbeba1fe97f2662fd 100644 --- a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts +++ b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts @@ -78,7 +78,6 @@ export class TabPaneSmapsStatistics extends BaseElement { async queryDataByDB(smapsVal: SelectionParam): Promise { getTabSmapsMaxSize(smapsVal.leftNs, smapsVal.rightNs, (MemoryConfig.getInstance().interval * 1000_000) / 5).then( (maxRes) => { - // @ts-ignore this.sumSize = maxRes[0].max_value; } ); @@ -118,7 +117,7 @@ export class TabPaneSmapsStatistics extends BaseElement { smapsTreeObj.rssStr = Utils.getBinaryByteWithUnit(smapsTreeObj.rss); smapsTreeObj.pssStr = Utils.getBinaryByteWithUnit(smapsTreeObj.pss); smapsTreeObj.sizePro = this.calculatePercentage(smapsTreeObj.size, sumSize!); - smapsTreeObj.sizeProStr = smapsTreeObj.sizePro.toFixed(2) + '%'; + smapsTreeObj.sizeProStr = smapsTreeObj.sizePro.toFixed(2) + '%' == '0.00%' ? '0%' : smapsTreeObj.sizePro.toFixed(2) + '%'; smapsTreeObj.sharedCleanStr = Utils.getBinaryByteWithUnit(smapsTreeObj.sharedClean); smapsTreeObj.sharedDirtyStr = Utils.getBinaryByteWithUnit(smapsTreeObj.sharedDirty); smapsTreeObj.privateCleanStr = Utils.getBinaryByteWithUnit(smapsTreeObj.privateClean); @@ -139,7 +138,7 @@ export class TabPaneSmapsStatistics extends BaseElement { objTree.path = SpSystemTrace.DATA_DICT.get(Number(smaps.path))?.split('/'); if (sumSize) { objTree.sizePro = this.calculatePercentage(smaps.size, sumSize); - objTree.sizeProStr = objTree.sizePro.toFixed(2) + '%'; + objTree.sizeProStr = objTree.sizePro.toFixed(2) + '%' == '0.00%' ? '0%' : objTree.sizePro.toFixed(2) + '%' ; } objTree.size = smaps.size; objTree.sizeStr = Utils.getBinaryByteWithUnit(smaps.size); @@ -195,7 +194,7 @@ export class TabPaneSmapsStatistics extends BaseElement { if (sumSize) { treeObj.sizePro = this.calculatePercentage(smaps.size, sumSize || 0); - treeObj.sizeProStr = treeObj.sizePro.toFixed(2) + '%'; + treeObj.sizeProStr = treeObj.sizePro.toFixed(2) + '%' == '0.00%' ? '0%' : treeObj.sizePro.toFixed(2) + '%'; } if (smapsStatDataTree.children.length >= 1 && smapsStatDataTree.path !== '< multiple >') { @@ -217,7 +216,6 @@ export class TabPaneSmapsStatistics extends BaseElement { async setSmaps(data: SelectionParam): Promise { getTabSmapsStatisticMaxSize(data.leftNs).then((maxRes) => { - // @ts-ignore this.sumSize = maxRes[0].max_value; }); await getTabSmapsStatisticData(data.leftNs).then((result) => { diff --git a/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts b/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts index adcacaa63db629f97866c783a7ece5daa15e2e69..b32dc9cd69ed096a165ee7bc4856a5ce23931717 100644 --- a/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts +++ b/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts @@ -77,8 +77,8 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.clickSingle(false); this.currentSelectionParam = threadStatesParam; // 清空表格数据 - this.threadBindersTbl!.recycleDataSource = []; // @ts-ignore - this.theadClick(this.threadBindersTbl!.recycleDataSource); + this.threadBindersTbl!.recycleDataSource = []; + this.theadClick(this.threadBindersTbl!.recycleDataSource as Array); } initTabSheetEl(traceSheet: TraceSheet): void { @@ -154,7 +154,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { for (let i = 0; i < this.funcNameCycleArr!.length; i++) { if ( // @ts-ignore - stateItem.ts > this.funcNameCycleArr[i].cycleStartTime && + stateItem.ts + stateItem.dur > this.funcNameCycleArr[i].cycleStartTime && // @ts-ignore stateItem.ts + stateItem.dur < this.funcNameCycleArr[i].endTime && (stateItem.state === 'S' || @@ -162,10 +162,18 @@ export class TabPaneFreqStatesDataCut extends BaseElement { stateItem.state === 'D' || stateItem.state === 'Running') ) { + stateItem.startTs = stateItem.ts; + stateItem.chartDur = stateItem.dur; + // @ts-ignore 周期第一条数据开始时间设置为周期开始时间 + if (stateItem.ts + stateItem.dur > this.funcNameCycleArr[i].cycleStartTime && stateItem.ts < this.funcNameCycleArr[i].cycleStartTime) { + stateItem.dur = stateItem.ts + stateItem.dur! - this.funcNameCycleArr![i].cycleStartTime + stateItem.ts = this.funcNameCycleArr![i].cycleStartTime; + } this.filterState!.push(stateItem); } } }); + this.filterState = Array.from(new Set(this.filterState)); // 周期内有数据 if (this.filterState.length !== 0) { for (let i = 0; i < processIds.length; i++) { @@ -175,12 +183,11 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.threadBindersTbl!.recycleDataSource = stateCutArr; this.threadBindersTbl!.loading = false; // 表格添加点击事件 - // @ts-ignore - this.theadClick(this.threadBindersTbl!.recycleDataSource); + this.theadClick(this.threadBindersTbl!.recycleDataSource as Array); } else { this.threadBindersTbl!.recycleDataSource = []; - this.threadBindersTbl!.loading = false; // @ts-ignore - this.theadClick(this.threadBindersTbl!.recycleDataSource); + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource as Array); } } else { this.verifyInputIsEmpty(threadIdValue, threadFuncName, threadId, threadFunc); @@ -219,7 +226,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { for (let i = 0; i < this.funcNameCycleArr!.length; i++) { if ( // @ts-ignore - stateItem.ts > this.funcNameCycleArr[i].cycleStartTime && + stateItem.ts + stateItem.dur > this.funcNameCycleArr[i].cycleStartTime && // @ts-ignore stateItem.ts + stateItem.dur < this.funcNameCycleArr[i].endTime && (stateItem.state === 'S' || @@ -227,6 +234,13 @@ export class TabPaneFreqStatesDataCut extends BaseElement { stateItem.state === 'D' || stateItem.state === 'Running') ) { + stateItem.startTs = stateItem.ts; + stateItem.chartDur = stateItem.dur; + // @ts-ignore 周期第一条数据开始时间设置为周期开始时间 + if (stateItem.ts + stateItem.dur > this.funcNameCycleArr[i].cycleStartTime && stateItem.ts < this.funcNameCycleArr[i].cycleStartTime) { + stateItem.dur = stateItem.ts + stateItem.dur! - this.funcNameCycleArr![i].cycleStartTime + stateItem.ts = this.funcNameCycleArr![i].cycleStartTime; + } this.filterState!.push(stateItem); } } @@ -237,12 +251,12 @@ export class TabPaneFreqStatesDataCut extends BaseElement { } } this.threadBindersTbl!.recycleDataSource = stateCutArr; - this.threadBindersTbl!.loading = false; // @ts-ignore - this.theadClick(this.threadBindersTbl!.recycleDataSource); + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource as BinderGroup[]); } else { this.threadBindersTbl!.recycleDataSource = []; - this.threadBindersTbl!.loading = false; // @ts-ignore - this.theadClick(this.threadBindersTbl!.recycleDataSource); + this.threadBindersTbl!.loading = false; + this.theadClick(this.threadBindersTbl!.recycleDataSource as BinderGroup[]); } } else { this.verifyInputIsEmpty(threadIdValue, threadFuncName, threadId, threadFunc); @@ -259,24 +273,41 @@ export class TabPaneFreqStatesDataCut extends BaseElement { if (filterItem.pid === processId) { processArr.push(filterItem); filterObj.totalCount! += 1; - filterItem.state === 'R' - ? (filterObj.RunnableCount += 1) - : filterItem.state === 'Running' - ? (filterObj.RunningCount += 1) + filterItem.state === 'R' + ? (filterObj.RunnableCount += 1, filterObj.RunnableDur += filterItem.dur!) + : filterItem.state === 'Running' + ? (filterObj.RunningCount += 1, filterObj.RunningDur += filterItem.dur!) : filterItem.state === 'D' - ? (filterObj.DCount += 1) - : (filterObj.SleepingCount += 1); - filterObj.title = (Utils.PROCESS_MAP.get(processId) || 'Process') + processId; + ? (filterObj.DCount += 1, filterObj.DDur += filterItem.dur!) + : (filterObj.SleepingCount += 1, filterObj.SleepingDur += filterItem.dur!) + filterObj.title = (Utils.getInstance().getProcessMap().get(processId) || 'Process') + processId; filterObj.pid = processId; filterObj.type = 'process'; + // @ts-ignore + filterObj.cycleDur! += filterItem.dur!; } }); + // @ts-ignore + filterObj.RunningDur = this.formatNumber(filterObj.RunningDur/1000000); + // @ts-ignore + filterObj.RunnableDur = this.formatNumber(filterObj.RunnableDur/1000000); + // @ts-ignore + filterObj.DDur = this.formatNumber(filterObj.DDur/1000000); + // @ts-ignore + filterObj.SleepingDur = this.formatNumber(filterObj.SleepingDur/1000000); + // @ts-ignore + filterObj.cycleDur = this.formatNumber(filterObj.cycleDur!/1000000); if (processArr.length > 0) { filterObj.children = this.setThreadData(processArr); } stateCutArr.push(filterObj); } + // 是0为0,非0保留三位小数 + formatNumber(num: number) { + return num === 0 ? 0 : num.toFixed(3); + } + // 处理线程数据 setThreadData(threadData: Array) { // 进程下面的线程,相当于process的children @@ -289,7 +320,8 @@ export class TabPaneFreqStatesDataCut extends BaseElement { threadObj.pid = threadData[0].pid; threadObj.children = new Array(); threadObj.type = 'thread'; - (threadObj.title = (Utils.THREAD_MAP.get(threads[i]) || 'Process') + threads[i]), threadArr.push(threadObj); + (threadObj.title = (Utils.getInstance().getProcessMap().get(threads[i]) || 'Process') + threads[i]), + threadArr.push(threadObj); } for (let i = 0; i < threadArr.length; i++) { let threadList = new Array(); @@ -300,16 +332,24 @@ export class TabPaneFreqStatesDataCut extends BaseElement { threadItem.state === 'R' ? ((threadArr[i].RunnableCount += 1), (threadArr[i].RunnableDur += threadItem.dur!)) : threadItem.state === 'Running' - ? ((threadArr[i].RunningCount += 1), (threadArr[i].RunningDur += threadItem.dur!)) - : threadItem.state === 'S' - ? ((threadArr[i].SleepingCount += 1), (threadArr[i].SleepingDur += threadItem.dur!)) - : ((threadArr[i].DCount += 1), (threadArr[i].DDur += threadItem.dur!)); + ? ((threadArr[i].RunningCount += 1), (threadArr[i].RunningDur += threadItem.dur!)) + : threadItem.state === 'S' + ? ((threadArr[i].SleepingCount += 1), (threadArr[i].SleepingDur += threadItem.dur!)) + : ((threadArr[i].DCount += 1), (threadArr[i].DDur += threadItem.dur!)); + // @ts-ignore + threadArr[i].cycleDur! += threadItem.dur! } }); - threadArr[i].SleepingDur = Number((threadArr[i].SleepingDur / 1000000).toFixed(3)); - threadArr[i].RunnableDur = Number((threadArr[i].RunnableDur / 1000000).toFixed(3)); - threadArr[i].RunningDur = Number((threadArr[i].RunningDur / 1000000).toFixed(3)); - threadArr[i].DDur = Number((threadArr[i].DDur / 1000000).toFixed(3)); + // @ts-ignore + threadArr[i].SleepingDur = this.formatNumber(threadArr[i].SleepingDur/1000000); + // @ts-ignore + threadArr[i].RunnableDur = this.formatNumber(threadArr[i].RunnableDur/1000000); + // @ts-ignore + threadArr[i].RunningDur = this.formatNumber(threadArr[i].RunningDur/1000000); + // @ts-ignore + threadArr[i].DDur = this.formatNumber(threadArr[i].DDur/1000000); + // @ts-ignore + threadArr[i].cycleDur = this.formatNumber(threadArr[i].cycleDur/1000000); if (threadList.length > 0) { threadArr[i].children = this.setCycleData(threadList); } @@ -329,25 +369,31 @@ export class TabPaneFreqStatesDataCut extends BaseElement { cycleItem.title = `cycle-${i + 1}`; cycleItem.cycle = i; threadData.map((v) => { - // @ts-ignore - if (v.ts > this.funcNameCycleArr[i].cycleStartTime && v.dur + v.ts < this.funcNameCycleArr[i].endTime) { + if ( + // @ts-ignore + v.ts + v.dur > this.funcNameCycleArr[i].cycleStartTime && + // @ts-ignore + v.dur + v.ts < this.funcNameCycleArr[i].endTime + ) { cycleItem.totalCount! += 1; v.state === 'R' ? ((cycleItem.RunnableCount += 1), (cycleItem.RunnableDur += v.dur!)) : v.state === 'Running' - ? ((cycleItem.RunningCount += 1), (cycleItem.RunningDur += v.dur!)) - : v.state === 'S' - ? ((cycleItem.SleepingCount += 1), (cycleItem.SleepingDur += v.dur!)) - : ((cycleItem.DCount += 1), (cycleItem.DDur += v.dur!)); + ? ((cycleItem.RunningCount += 1), (cycleItem.RunningDur += v.dur!)) + : v.state === 'S' + ? ((cycleItem.SleepingCount += 1), (cycleItem.SleepingDur += v.dur!)) + : ((cycleItem.DCount += 1), (cycleItem.DDur += v.dur!)); } }); - cycleItem.SleepingDur = Number((cycleItem.SleepingDur / 1000000).toFixed(3)); - cycleItem.RunningDur = Number((cycleItem.RunningDur / 1000000).toFixed(3)); - cycleItem.RunnableDur = Number((cycleItem.RunnableDur / 1000000).toFixed(3)); - cycleItem.DDur = Number((cycleItem.DDur / 1000000).toFixed(3)); - cycleItem.cycleDur! = Number( - ((this.funcNameCycleArr[i].endTime - this.funcNameCycleArr[i].cycleStartTime) / 1000000).toFixed(3) - ); + // @ts-ignore + cycleItem.SleepingDur = this.formatNumber(cycleItem.SleepingDur/1000000); + // @ts-ignore + cycleItem.RunningDur = this.formatNumber(cycleItem.RunningDur/1000000); + // @ts-ignore + cycleItem.RunnableDur = this.formatNumber(cycleItem.RunnableDur/1000000); + // @ts-ignore + cycleItem.DDur = this.formatNumber(cycleItem.DDur/1000000); + cycleItem.cycleDur! = this.formatNumber((this.funcNameCycleArr[i].endTime - this.funcNameCycleArr[i].cycleStartTime)/1000000); cycleItem.type = 'cycle'; cycleArr.push(cycleItem); } @@ -437,6 +483,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.cycleIsClick = false; this.lineCycleNum = -1; this.traceSheetEl!.systemLogFlag = undefined; + SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; TabPaneFreqStatesDataCut.isStateTabHover = false; this.spSystemTrace?.refreshCanvas(false); }); @@ -470,9 +517,11 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.threadBindersTbl!.setCurrentSelection(currentData); if (currentData.cycle === this.lineCycleNum && this.cycleIsClick === true) { this.traceSheetEl!.systemLogFlag = undefined; + SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; TabPaneFreqStatesDataCut.isStateTabHover = false; this.cycleIsClick = false; } else { + SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 }; let pointX: number = ns2x( this.funcNameCycleArr![currentData.cycle].cycleStartTime || 0, TraceRow.range!.startNS, @@ -480,6 +529,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { TraceRow.range!.totalNS, new Rect(0, 0, TraceRow.FRAME_WIDTH, 0) ); + SpSegmentationChart.tabHoverObj.key = 'STATES'; SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag( Math.floor(pointX), 0, @@ -503,13 +553,17 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.shadowRoot?.querySelector('#query-btn')?.addEventListener('click', () => { this.cycleARangeArr = this.rowCycleData?.filter((it: StateGroup) => { return ( + // @ts-ignore it.cycleDur! >= Number(this.cycleAStartRangeDIV!.value) && + // @ts-ignore it.cycleDur! < Number(this.cycleAEndRangeDIV!.value) ); }); this.cycleBRangeArr = this.rowCycleData?.filter((it: StateGroup) => { return ( + // @ts-ignore it.cycleDur! >= Number(this.cycleBStartRangeDIV!.value) && + // @ts-ignore it.cycleDur! < Number(this.cycleBEndRangeDIV!.value) ); }); @@ -539,9 +593,9 @@ export class TabPaneFreqStatesDataCut extends BaseElement { // 筛选出点击的线程数据 filCycleData(pid: number, tid: number): Array { return this.filterState?.filter((v: StateGroup) => { - return v.pid === pid && v.tid === tid && v.ts > this.cycleStartTime! && v.ts + v.dur! < this.cycleEndTime!; - }); - } + return v.pid === pid && v.tid === tid && v.ts + v.dur! > this.cycleStartTime! && v.ts + v.dur! < this.cycleEndTime!; + }) + }; // 清空dur筛选输入框内容 clearCycleRange(): void { @@ -564,11 +618,12 @@ export class TabPaneFreqStatesDataCut extends BaseElement { notSort: true, color: (a) => { //@ts-ignore - if (a.xName === 'Total') { - return '#2f72f8'; //@ts-ignore - } else if (a.xName === 'cycleA') { - return '#ffab67'; //@ts-ignore - } else if (a.xName === 'cycleB') { + const xName = a.xName; + if (xName === 'Total') { + return '#2f72f8'; + } else if (xName === 'cycleA') { + return '#ffab67'; + } else if (xName === 'cycleB') { return '#a285d2'; } else { return '#0a59f7'; @@ -577,12 +632,11 @@ export class TabPaneFreqStatesDataCut extends BaseElement { tip: (a) => { //@ts-ignore if (a && a[0]) { + //@ts-ignore + const obj = a[0]; let tip: string = ''; tip = `
-
Average count: ${ - //@ts-ignore - a[0].obj.yAverage - }
+
Average count: ${obj.obj.yAverage}
`; return tip; } else { @@ -712,6 +766,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { } .chart_area{ margin-top:40px; + height:0; } .chart_title{ line-height: 40px; @@ -734,30 +789,30 @@ export class TabPaneFreqStatesDataCut extends BaseElement { - + - + - + - + - + - + - + - + - + - +
-
+
Cycle A: diff --git a/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgPinComparisonVM.ts b/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgPinComparisonVM.ts index f90d4b1a2364791ecdff2b89408b6627107aa0fa..e59c271b8c097ab1e4bb177e6633c240817ded3d 100644 --- a/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgPinComparisonVM.ts +++ b/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgPinComparisonVM.ts @@ -55,6 +55,7 @@ export class TabPanePurgPinComparisonVM extends BaseElement { this.updateComparisonData(data.startNs, fileArr[0].startNs); } private initSelect(fileStartNs: number, purgePinComVmList: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; let option = new LitSelectOption(); @@ -77,7 +78,7 @@ export class TabPanePurgPinComparisonVM extends BaseElement { // @ts-ignore if (input.value === f.name) { // @ts-ignore - this.updateComparisonData(fileStartNs, f.startNs); + that.updateComparisonData(fileStartNs, f.startNs); } } // @ts-ignore diff --git a/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgTotalComparisonVM.ts b/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgTotalComparisonVM.ts index 13c748b5037eee5e717075226963445626207b81..8fcd6c18b106a67f5d028c48698be43d4d0a9e49 100644 --- a/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgTotalComparisonVM.ts +++ b/ide/src/trace/component/trace/sheet/vmtracker/TabPanePurgTotalComparisonVM.ts @@ -58,6 +58,7 @@ export class TabPanePurgTotalComparisonVM extends BaseElement { } private initSelect(fileStartNs: number, purgeTotalComList: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; let option = new LitSelectOption(); @@ -80,7 +81,7 @@ export class TabPanePurgTotalComparisonVM extends BaseElement { // @ts-ignore if (input.value === f.name) { // @ts-ignore - this.updateComparisonsData(fileStartNs, f.startNs); + that.updateComparisonsData(fileStartNs, f.startNs); } } // @ts-ignore diff --git a/ide/src/trace/component/trace/sheet/vmtracker/TabPaneVmTrackerShmComparison.ts b/ide/src/trace/component/trace/sheet/vmtracker/TabPaneVmTrackerShmComparison.ts index 536fad48d2ec6b159105ee21c0cd1616b663959b..468574b07abeb553937482f7925eafb324acddba 100644 --- a/ide/src/trace/component/trace/sheet/vmtracker/TabPaneVmTrackerShmComparison.ts +++ b/ide/src/trace/component/trace/sheet/vmtracker/TabPaneVmTrackerShmComparison.ts @@ -55,6 +55,7 @@ export class TabPaneVmTrackerShmComparison extends BaseElement { setShmData(data: SnapshotStruct, dataList: Array): void { let fileArr: SnapshotStruct[] = []; + let that = this; for (let file of dataList) { if (file.startNs !== data.startNs) { fileArr.push(file); @@ -64,7 +65,7 @@ export class TabPaneVmTrackerShmComparison extends BaseElement { this.baseFileTs = data.startNs; this.initSelect(data.startNs, fileArr); this.targetFileTs = fileArr[0].startNs; - this.updateComparisonData(data.startNs, fileArr[0].startNs); + that.updateComparisonData(data.startNs, fileArr[0].startNs); } async updateComparisonData(baseFileTs: number, targetFileTs: number): Promise { @@ -100,6 +101,7 @@ export class TabPaneVmTrackerShmComparison extends BaseElement { } initSelect(fileId: number, fileArr: Array): void { + let that = this; let input = this.selectEl!.shadowRoot?.querySelector('input') as HTMLInputElement; this.selectEl!.innerHTML = ''; let option = new LitSelectOption(); @@ -117,7 +119,7 @@ export class TabPaneVmTrackerShmComparison extends BaseElement { this.comparisonTableEl!.scrollTop = 0; for (let f of fileArr) { if (input.value === f.name) { - this.updateComparisonData(fileId, f.startNs); + that.updateComparisonData(fileId, f.startNs); } } e.stopPropagation(); diff --git a/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts b/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts index 1323c2b5c34b744d58a1294e559281f424628346..8e1b143fc10db51d4be99dd34ac121c52a6c1a94 100644 --- a/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts +++ b/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts @@ -17,8 +17,8 @@ import { Graph } from './Graph'; import { Rect } from './Rect'; import { ns2UnitS, TimerShaftElement } from '../TimerShaftElement'; import { ColorUtils, interpolateColorBrightness } from '../base/ColorUtils'; -import { CpuStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { CurrentSlicesTime, SpSystemTrace } from '../../SpSystemTrace'; +import { Utils } from '../base/Utils'; const MarkPadding = 5; const FIT_TOTALX_MIN: number = 280; @@ -167,12 +167,12 @@ export class RangeRuler extends Graph { drawCpuUsage(): void { this.context2D.clearRect(this.frame.x, this.frame.y, this.frame.width, this.frame.height); - let miniHeight = Math.round(this.frame.height / CpuStruct.cpuCount); //每格高度 + let miniHeight = Math.round(this.frame.height / Utils.getInstance().getCpuCount()); //每格高度 let miniWidth = Math.ceil(this.frame.width / 100); //每格宽度 - this._cpuCountData = CpuStruct.cpuCount; + this._cpuCountData = Utils.getInstance().getCpuCount(); if (sessionStorage.getItem('expand') === 'true') { //展开 - miniHeight = Math.round(this.frame.height / CpuStruct.cpuCount); + miniHeight = Math.round(this.frame.height / Utils.getInstance().getCpuCount()); } else if (sessionStorage.getItem('expand') === 'false') { miniHeight = Math.round(this.frame.height / 2); } diff --git a/ide/src/trace/component/trace/timer-shaft/SportRuler.ts b/ide/src/trace/component/trace/timer-shaft/SportRuler.ts index 06118e24a58c97081f3826a2441ee1c8d5ff7a9a..60bae19e11fd602f9a03229bbaeeaee5a68ed747 100644 --- a/ide/src/trace/component/trace/timer-shaft/SportRuler.ts +++ b/ide/src/trace/component/trace/timer-shaft/SportRuler.ts @@ -98,6 +98,7 @@ export class SportRuler extends Graph { private timeArray: Array = []; private countArray: Array = []; private durArray: Array = []; + private mouseIn: boolean = false; constructor( timerShaftEL: TimerShaftElement, frame: Rect, @@ -331,6 +332,8 @@ export class SportRuler extends Graph { TraceRow.rangeSelectObject!.startX! + (rangeSelectWidth / section) * (i - 1) + (rangeSelectWidth / section - countTextWidth) / 2; + this.context2D.fillStyle = `#f00`; + this.context2D.font = `12px sans-serif`; this.context2D.fillText(String(countArr[i - 1]), textY, this.frame.y + 22 + 12); } @@ -373,7 +376,7 @@ export class SportRuler extends Graph { return inRange; } - drawTriangle(time: number, type: string): number { + drawTriangle(time: number, type: string): unknown { if (time !== null && typeof time !== undefined) { let i = this.flagList.findIndex((it) => it.time === time); if (type === 'triangle') { @@ -400,11 +403,7 @@ export class SportRuler extends Graph { if (triangle !== -1) { this.flagList[triangle].type = ''; this.draw(); - this.notifyHandler && - this.notifyHandler( - !this.hoverFlag.hidden ? this.hoverFlag : null, - this.flagList.find((it) => it.selected) || null - ); + this.flagChangeHandler('1'); return this.flagList[triangle].time; } } @@ -412,25 +411,29 @@ export class SportRuler extends Graph { this.invertedTriangleTime = time; } this.draw(); - this.notifyHandler && - this.notifyHandler( - !this.hoverFlag.hidden ? this.hoverFlag : null, - this.flagList.find((it) => it.selected) || null - ); + this.flagChangeHandler('2'); + return; } - return 0; + } + + flagChangeHandler(from?: string): void { + this.notifyHandler && + this.notifyHandler( + !this.hoverFlag.hidden ? this.hoverFlag : null, + this.flagList.find((it) => it.selected) || null + ); } removeTriangle(type: string): void { if (type === 'inverted') { + if (this.invertedTriangleTime !== null) { + this.flagChangeHandler('3'); + } this.invertedTriangleTime = null; + } else { + this.flagChangeHandler('3'); } this.draw(); - this.notifyHandler && - this.notifyHandler( - !this.hoverFlag.hidden ? this.hoverFlag : null, - this.flagList.find((it) => it.selected) || null - ); } drawInvertedTriangle(time: number, color: string = '#000000'): void { @@ -779,6 +782,7 @@ export class SportRuler extends Graph { mouseMove(ev: MouseEvent): void { if (this.edgeDetection(ev)) { + this.mouseIn = true; let x = ev.offsetX - (this.canvas?.offsetLeft || 0); let flg = this.flagList.find((it) => x >= it.x && x <= it.x + 18); if (flg) { @@ -788,27 +792,25 @@ export class SportRuler extends Graph { this.hoverFlag.x = x; this.hoverFlag.color = '#999999'; } + this.flagChangeHandler('4'); + this.draw(); } else { this.hoverFlag.hidden = true; } - this.draw(); - this.notifyHandler && - this.notifyHandler( - !this.hoverFlag.hidden ? this.hoverFlag : null, - this.flagList.find((it) => it.selected) || null - ); + } mouseOut(ev: MouseEvent): void { if (!this.hoverFlag.hidden) { this.hoverFlag.hidden = true; - this.notifyHandler && - this.notifyHandler( - !this.hoverFlag.hidden ? this.hoverFlag : null, - this.flagList.find((it) => it.selected) || null - ); + if (this.mouseIn) { + this.flagChangeHandler('5'); + } + } + if (this.mouseIn) { + this.mouseIn = false; + this.draw(); } - this.draw(); } edgeDetection(ev: MouseEvent): boolean { diff --git a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts index d8204e3e9ca236d3528f1ee908392ce53d3850a5..8c2c810221331e3e9d2bcbf25d501e8e022ed44c 100644 --- a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts +++ b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts @@ -71,6 +71,11 @@ export class TabPaneFlag extends BaseElement { }, { capture: true } ); + new ResizeObserver((entries) => { + if (this.parentElement!.style.display !== 'none') { + this.setTableData(); + } + }).observe(this); } public setCurrentFlag(flag: Flag): void {