diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index 7b2f793a28726fcf3274eec1a02243f7111461d3..ba7b9d8dbbcd12e3f05f1e1ba554e0d9a9aba098 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -631,11 +631,11 @@ export let tabConfig: any = { 'tabpane-frequsage': { title: 'Freq Usage', type: TabPaneFreqUsage, - require: (param: SelectionParam) => param.threadIds.length > 0 && param.threadIds.length < 2, + require: (param: SelectionParam) => param.threadIds.length > 0, }, 'tabpane-freqdatacut': { title: 'Freq DataCut', type: TabPaneFreqDataCut, - require: (param: SelectionParam) => param.threadIds.length > 0 && param.threadIds.length < 2, + require: (param: SelectionParam) => param.threadIds.length > 0, }, }; diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts index 4551fab84c4c6e9f8006c91a260506ff4ac1c268..0f16bde91487e96bd4aa1ebfcab628bd5237bd14 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts @@ -14,13 +14,13 @@ */ import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; import '../../../StackBar.js' import { getTabRunningPercent, querySearchFuncData, queryCpuFreqUsageData, queryCpuFreqFilterId } from '../../../../database/SqlLite.js'; import { Utils } from '../../base/Utils.js'; -import { log } from '../../../../../log/Log.js'; import { resizeObserver } from '../SheetUtils.js'; +import { SliceGroup } from '../../../../bean/StateProcessThread.js'; @element('tabpane-freqdatacut') export class TabPaneFreqDataCut extends BaseElement { @@ -28,7 +28,9 @@ export class TabPaneFreqDataCut extends BaseElement { private threadStatesTblSource: Array = []; private currentSelectionParam: SelectionParam | any; private threadStatesDIV: Element | null | undefined; - private initData: Array = []; + private initData: any = new Map(); + private processArr: any = new Array(); + private threadArr: any = new Array(); set data(threadStatesParam: SelectionParam | any) { if (this.currentSelectionParam === threadStatesParam) { @@ -37,34 +39,58 @@ export class TabPaneFreqDataCut extends BaseElement { this.currentSelectionParam = threadStatesParam; this.threadStatesTblSource = []; this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = true; + this.initData = new Map(); let tableValue: any = this.threadStatesTbl; tableValue.value = []; let divRoot1: any = this.shadowRoot?.querySelector('#dataCutThreadId'); divRoot1.value = ''; let divRoot2: any = this.shadowRoot?.querySelector('#dataCutThreadFunc'); divRoot2.value = ''; + // 查询running状态线程数据 getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => { + // 查询cpu及id信息 queryCpuFreqFilterId().then(r => { + // 以键值对形式将cpu及id进行对应,后续会将频点数据与其对应cpu进行整合 let IdMap = new Map(); let queryId = new Array(); for (let i = 0; i < r.length; i++) { queryId.push(r[i].id); IdMap.set(r[i].id, r[i].cpu); } + // 通过id去查询频点数据 queryCpuFreqUsageData(queryId).then((res) => { if (result != null && result.length > 0) { - log('getTabRunningPercent result size : ' + result.length); let sum = 0; let dealArr = new Array(); for (let i of res) { dealArr.push({ 'startNS': i.startNS + threadStatesParam.recordStartNs, 'dur': i.dur, 'value': i.value, 'cpu': IdMap.get(i.filter_id) }); } - let targetList = new Array(); - let cpuArr = new Array(); - let finalResultArr = new Array(); - finalResultArr.push({ 'thread': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': '100.00', 'state': 'Running', children: new Array() }); + let needDeal = new Map(); + let pidArr = new Array(); + let threadArr = new Array(); + // 整理进程级的数组信息 + let processArr: any = threadStatesParam.processIds.length > 1 ? [...new Set(threadStatesParam.processIds)] : threadStatesParam.processIds; + for (let i of processArr) { + pidArr.push({ 'process': Utils.PROCESS_MAP.get(i) == null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, 'thread': Utils.PROCESS_MAP.get(i) == null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, 'pid': i, 'tid': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + } + // 拷贝给私有属性,以便后续进行数据切割时免除整理进程层级数据 + this.processArr = JSON.parse(JSON.stringify(pidArr)); for (let e of result) { - if (threadStatesParam.processIds.includes(e.pid) && e.state == 'Running') { + if (processArr.includes(e.pid) && e.state == 'Running') { + if (needDeal.get(e.pid + '_' + e.tid) == undefined) { + threadArr.push({ 'process': Utils.PROCESS_MAP.get(e.pid) == null ? 'Process ' + e.pid : Utils.PROCESS_MAP.get(e.pid) + ' ' + e.pid, 'thread': Utils.THREAD_MAP.get(e.tid) + ' ' + e.tid, 'pid': e.pid, 'tid': e.tid, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + needDeal.set(e.pid + '_' + e.tid, new Array()); + } + if ((e.ts < (threadStatesParam.leftNs + threadStatesParam.recordStartNs)) && ((e.ts + e.dur) > (threadStatesParam.leftNs + threadStatesParam.recordStartNs))) { + const ts = e.ts; + e.ts = threadStatesParam.leftNs + threadStatesParam.recordStartNs; + e.dur = ts + e.dur - (threadStatesParam.leftNs + threadStatesParam.recordStartNs); + } + if ((e.ts + e.dur) > (threadStatesParam.rightNs + threadStatesParam.recordStartNs)) { + e.dur = threadStatesParam.rightNs + threadStatesParam.recordStartNs - e.ts; + } + let arr = needDeal.get(e.pid + '_' + e.tid); let process = Utils.PROCESS_MAP.get(e.pid); let thread = Utils.THREAD_MAP.get(e.tid); e.process = process == null || process.length == 0 ? '[NULL]' : process; @@ -72,99 +98,79 @@ export class TabPaneFreqDataCut extends BaseElement { e.stateJX = e.state; e.state = Utils.getEndState(e.stateJX); sum += e.dur; - targetList.push(e); - if (!cpuArr.includes(e.cpu)) { - cpuArr.push(e.cpu); - finalResultArr[0].thread = finalResultArr[0].thread == '' ? e.tid + '_' + e.thread : finalResultArr[0].thread; - finalResultArr[0].children.push({ 'thread': e.tid + '_' + e.thread, 'count': 0, 'cpu': e.cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - } - } - } - // 用来存放数据切割之前的汇总数据 - let resultList = new Array(); - // 通过循环获取每个running状态线程的相关信息,此处或许可以进行算法优化 - const tsMutiple = 1000000000; - for (let i = 0; i < targetList.length; i++) { - for (let j = 0; j < dealArr.length; j++) { - if (targetList[i].cpu == dealArr[j].cpu) { - if (targetList[i].ts > dealArr[j].startNS) { - if (targetList[i].ts < (dealArr[j].startNS + dealArr[j].dur)) { - if (targetList[i].dur < (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * targetList[i].dur) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': targetList[i].dur, 'percent': targetList[i].dur / sum * 100, 'state': 'Running', 'ts': targetList[i].ts / tsMutiple }); - break; - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts), 'percent': (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) / sum * 100, 'state': 'Running', 'ts': targetList[i].ts / tsMutiple }); - } - } - } else { - if ((targetList[i].ts + targetList[i].dur) > dealArr[j].startNS) { - if ((targetList[i].dur + targetList[i].ts - dealArr[j].startNS) < dealArr[j].dur) { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * (targetList[i].dur + targetList[i].ts - dealArr[j].startNS)) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': (targetList[i].dur + targetList[i].ts - dealArr[j].startNS), 'percent': (targetList[i].dur + targetList[i].ts - dealArr[j].startNS) / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS / tsMutiple }); - break; - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': (dealArr[j].value * dealArr[j].dur) / 1000, 'cpu': targetList[i].cpu, 'freq': dealArr[j].value, 'dur': dealArr[j].dur, 'percent': dealArr[j].dur / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS / tsMutiple }); - } - } else { - resultList.push({ 'thread': targetList[i].tid + '_' + targetList[i].thread, 'count': 0, 'cpu': targetList[i].cpu, 'freq': 'unknown', 'dur': targetList[i].dur, 'percent': targetList[i].dur / sum * 100, 'state': 'Running', 'ts': targetList[i].ts / tsMutiple }); - break; - } - } - } + arr.push(e); } } - // 深拷贝,用来进行数据切割操作,避免数据污染 - this.initData = JSON.parse(JSON.stringify(resultList)); - //合并同一线程内,当运行所在cpu和频点相同时,dur及percent进行累加求和,或许可以进行算法优化 - for (let i = 0; i < resultList.length; i++) { - for (let j = i + 1; j < resultList.length; j++) { - if (resultList[i].cpu == resultList[j].cpu && resultList[i].freq == resultList[j].freq) { - resultList[i].dur += resultList[j].dur; - resultList[i].percent += resultList[j].percent; - resultList[i].count += resultList[j].count; - resultList.splice(j, 1); - j--; - } + // 拷贝给私有属性,以便后续进行数据切割时免除整理线程层级数据 + this.threadArr = JSON.parse(JSON.stringify(threadArr)); + // 整理running线程数据、cpu层级信息 + this.mergeFreqData(needDeal, dealArr, sum); + this.threadStatesTbl!.loading = false; + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; + } + }) + }); + }) + } + private threadClick(data: Array) { + let labels = this.threadStatesTbl?.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.threadStatesTbl!.setStatus(data, false); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 1) { + for (let item of data) { + item.status = true; + if (item.children != undefined && item.children.length > 0) { + this.threadStatesTbl!.setStatus(item.children, false); } - resultList[i].percent = Number((resultList[i].percent).toFixed(2)); - resultList[i].ts = (resultList[i].ts * tsMutiple - threadStatesParam.recordStartNs) / tsMutiple; } - finalResultArr[0].children.sort((a: any, b: any) => a.cpu - b.cpu); - // 转成树结构数据进行展示 - for (let i = 0; i < finalResultArr[0].children.length; i++) { - for (let j = 0; j < resultList.length; j++) { - if (finalResultArr[0].children[i].cpu == resultList[j].cpu) { - finalResultArr[0].children[i].children.push(resultList[j]); - finalResultArr[0].children[i].dur += resultList[j].dur; - finalResultArr[0].children[i].percent += resultList[j].percent; - finalResultArr[0].children[i].count += resultList[j].count; - resultList.splice(j, 1); - j--; + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Cycle') && i === 2) { + for (let item of data) { + item.status = true; + for (let value of item.children ? item.children : []) { + value.status = true; + if (value.children != undefined && value.children.length > 0) { + this.threadStatesTbl!.setStatus(value.children, false); } } - finalResultArr[0].children[i].percent = finalResultArr[0].children[i].percent.toFixed(2); - finalResultArr[0].dur += finalResultArr[0].children[i].dur; - finalResultArr[0].count += finalResultArr[0].children[i].count; } - this.threadStatesTblSource = finalResultArr; - this.threadStatesTbl!.recycleDataSource = finalResultArr; - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - this.initData = []; + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('CPU') && i === 3) { + this.threadStatesTbl!.setStatus(data, true); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); } + }); + } + } + let scatterData: any = this.threadStatesTbl?.shadowRoot?.querySelectorAll('.tree-first-body'); + if (scatterData) { + for (let j = 0; j < scatterData.length; j++) { + let scatter = scatterData[j].data; + scatterData[j].addEventListener('click', (e: any) => { + console.log(scatter); }) - }) - - }); + } + } } + initElements(): void { this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-percent'); // 暂时屏蔽列排序功能,后续增加则重写排序方法 this.threadStatesDIV = this.shadowRoot?.querySelector('#dataCut'); this.threadStatesDIV?.children[2].children[0].addEventListener('click', (e) => { + this.threadStatesTbl!.loading = true; 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; this.dataLoopCut(this.threadStatesDIV?.children[0], this.threadStatesDIV?.children[1], this.initData); }) } @@ -201,225 +207,459 @@ export class TabPaneFreqDataCut extends BaseElement { }
- - + +
- - + + - + - + - + - + - + - + - + ` } - dataLoopCut(threadId: any, threadFunc: any, resultList: any) { + sortByColumn(treadStateDetail: any) { + function compare(property: any, treadStatesSort: any, type: any) { + return function (threadStatesLeftData: SelectionData | any, threadStatesRightData: SelectionData | any) { + if (threadStatesLeftData.process == ' ' || threadStatesRightData.process == ' ') { + return 0; + } + if (type === 'number') { + return treadStatesSort === 2 + ? parseFloat(threadStatesRightData[property]) - parseFloat(threadStatesLeftData[property]) + : parseFloat(threadStatesLeftData[property]) - parseFloat(threadStatesRightData[property]); + } else { + if (threadStatesRightData[property] > threadStatesLeftData[property]) { + return treadStatesSort === 2 ? 1 : -1; + } else if (threadStatesRightData[property] == threadStatesLeftData[property]) { + return 0; + } else { + return treadStatesSort === 2 ? -1 : 1; + } + } + }; + } + + if (treadStateDetail.key === 'name' || treadStateDetail.key === 'thread' || treadStateDetail.key === 'state') { + this.threadStatesTblSource.sort(compare(treadStateDetail.key, treadStateDetail.sort, 'string')); + } else { + this.threadStatesTblSource.sort(compare(treadStateDetail.key, treadStateDetail.sort, 'number')); + } + this.threadStatesTbl!.recycleDataSource = this.threadStatesTblSource; + } + // single方式切割数据功能 + dataSingleCut(threadId: any, threadFunc: any, resultList: any) { + threadId.style.border = '1px solid rgb(151,151,151)'; + threadFunc.style.border = '1px solid rgb(151,151,151)'; let threadIdValue = threadId.value.trim(); let threadFuncName = threadFunc.value.trim(); let leftNS = this.currentSelectionParam.leftNs; let rightNS = this.currentSelectionParam.rightNs; let tableValue: any = this.threadStatesTbl; tableValue.value = []; - if (/^[0-9]*$/.test(threadIdValue)) { - querySearchFuncData(threadFuncName, threadIdValue, leftNS, rightNS).then(res => { - let displayArr = JSON.parse(JSON.stringify(resultList)); - let timeDur = this.currentSelectionParam.recordStartNs; - let cutArr = new Array(); - // 根据线程id及方法名获取的数据,处理后用作切割时间依据,时间跨度为整个方法开始时间到末个方法开始时间 - for (let i of res) { - cutArr.push({ 'ts': i.startTime + timeDur }); - } - // 将数据进行切割处理 - let finalArr = new Array(); - let finalResultArr = new Array(); - const tsMutiple = 1000000000; - finalResultArr.push({ 'thread': displayArr[0].thread, 'ts': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - for (let i = 0; i < cutArr.length - 1; i++) { - for (let j = 0; j < displayArr.length; j++) { - displayArr[j].ts = displayArr[j].ts * tsMutiple; - if (displayArr[j].ts >= cutArr[i].ts) { - if ((displayArr[j].ts + displayArr[j].dur) <= cutArr[i + 1].ts) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * displayArr[j].dur) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': displayArr[j].dur, 'percent': displayArr[j].percent, 'state': 'Running', 'ts': (displayArr[j].ts - timeDur) / tsMutiple, 'id': i }); - } else { - if (cutArr[i + 1].ts - displayArr[j].ts > 0) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (cutArr[i + 1].ts - displayArr[j].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': cutArr[i + 1].ts - displayArr[j].ts, 'percent': displayArr[j].percent * ((cutArr[i + 1].ts - displayArr[j].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (displayArr[j].ts - timeDur) / tsMutiple, 'id': i }); - break; - } - } - } else { - if ((displayArr[j].ts + displayArr[j].dur) > cutArr[i + 1].ts) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (cutArr[i + 1].ts - cutArr[i].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': cutArr[i + 1].ts - cutArr[i].ts, 'percent': displayArr[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'id': i }); - } - if ((displayArr[j].ts + displayArr[j].dur) > cutArr[i].ts && (displayArr[j].ts + displayArr[j].dur) < cutArr[i + 1].ts) { - finalArr.push({ 'thread': displayArr[j].thread, 'count': (displayArr[j].freq * (displayArr[j].dur + displayArr[j].ts - cutArr[i].ts)) / 1000, 'cpu': displayArr[j].cpu, 'freq': displayArr[j].freq, 'dur': displayArr[j].dur + displayArr[j].ts - cutArr[i].ts, 'percent': displayArr[j].percent * ((displayArr[j].dur + displayArr[j].ts - cutArr[i].ts) / displayArr[j].dur), 'state': 'Running', 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'id': i }); - } + if (threadIdValue != '' && threadFuncName != '') { + // 根据用户输入的线程ID,方法名去查询数据库,得到对应的方法起始时间,持续时间等数据,以便作为依据进行后续数据切割 + querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then(result => { + if (result != null && result.length > 0) { + let targetMap = new Map(); + // 新创建map对象接收传过来的实参map + resultList.forEach((item: any, key: any) => { + targetMap.set(key, JSON.parse(JSON.stringify(item))); + }) + let timeDur = this.currentSelectionParam.recordStartNs; + // 周期切割依据数据整理 + let dealArr = new Array(); + for (let i of result) { + if (i.startTime + timeDur + i.dur < this.currentSelectionParam.rightNs + timeDur) { + dealArr.push({ 'ts': i.startTime + timeDur, 'dur': i.dur }); } } - finalResultArr[0].children.push({ 'thread': displayArr[0].thread, 'ts': (cutArr[i].ts - timeDur) / tsMutiple, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array(), 'id': i }); - } - - for (let i = 0; i < finalArr.length; i++) { - for (let j = i + 1; j < finalArr.length; j++) { - if (finalArr[i].cpu === finalArr[j].cpu && finalArr[i].freq === finalArr[j].freq && finalArr[i].id === finalArr[j].id) { - finalArr[i].dur += finalArr[j].dur; - finalArr[i].percent += finalArr[j].percent; - finalArr[i].count += finalArr[j].count; - finalArr.splice(j, 1); - j--; + let cycleMap = new Map(); + let totalList = new Map(); + targetMap.forEach((item, key) => { + cycleMap.set(key, new Array()); + totalList.set(key, new Array()); + for (let i = 0; i < dealArr.length; i++) { + let cpuArr = new Array(); + let cpuMap = new Map(); + let resList = new Array(); + // 时间由纳秒转换为秒的倍数 + const multiple = 1000000000; + // 算力倍数值 + const countMutiple = 1000; + cpuMap.set(key, new Array()); + cycleMap.get(key).push({ 'thread': '周期' + (i + 1) + '—' + item[0].thread, 'ts': ((dealArr[i].ts - timeDur) / 1000000).toFixed(3), 'cdur': (dealArr[i].dur / 1000000).toFixed(3), 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + let value = JSON.parse(JSON.stringify(item)); + for (let j = 0; j < value.length; j++) { + value[j].ts = value[j].ts * multiple; + value[j].freq = value[j].freq == 'unknown' ? 0 : value[j].freq; + if (!cpuArr.includes(value[j].cpu)) { + cpuArr.push(value[j].cpu); + cpuMap.get(key).push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': 0, 'cpu': value[j].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + } + if (dealArr[i].ts < value[j].ts) { + if (dealArr[i].ts + dealArr[i].dur > value[j].ts) { + if (dealArr[i].ts + dealArr[i].dur > value[j].ts + value[j].dur) { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * value[j].dur) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].dur, 'percent': value[j].percent, 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * value[j].dur) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].dur, 'percent': value[j].percent, 'state': 'Running', 'id': i }); + } else { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (dealArr[i].ts + dealArr[i].dur - value[j].ts) * value[j].freq / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': dealArr[i].ts + dealArr[i].dur - value[j].ts, 'percent': (dealArr[i].ts + dealArr[i].dur - value[j].ts) / value[j].dur * value[j].percent, 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (dealArr[i].ts + dealArr[i].dur - value[j].ts) * value[j].freq / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': dealArr[i].ts + dealArr[i].dur - value[j].ts, 'percent': (dealArr[i].ts + dealArr[i].dur - value[j].ts) / value[j].dur * value[j].percent, 'state': 'Running', 'id': i }); + break; + } + } + } else { + if (value[j].ts + value[j].dur > dealArr[i].ts) { + if (value[j].ts + value[j].dur > dealArr[i].ts + dealArr[i].dur) { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': dealArr[i].dur * value[j].freq / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': dealArr[i].dur, 'percent': dealArr[i].dur / value[j].dur * value[j].percent, 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': dealArr[i].dur * value[j].freq / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': dealArr[i].dur, 'percent': dealArr[i].dur / value[j].dur * value[j].percent, 'state': 'Running', 'id': i }); + break; + } else { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].ts + value[j].dur - dealArr[i].ts) * value[j].freq / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].ts + value[j].dur - dealArr[i].ts, 'percent': (value[j].ts + value[j].dur - dealArr[i].ts) / value[j].dur * value[j].percent, 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].ts + value[j].dur - dealArr[i].ts) * value[j].freq / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].ts + value[j].dur - dealArr[i].ts, 'percent': (value[j].ts + value[j].dur - dealArr[i].ts) / value[j].dur * value[j].percent, 'state': 'Running', 'id': i }); + } + } + } + } + this.mergeData(resList); + resList.sort((a, b) => b.count - a.count); + cpuMap.get(key).sort((a: any, b: any) => a.cpu - b.cpu); + cpuMap.get(key).forEach((item: any) => { + for (let s = 0; s < resList.length; s++) { + if (item.cpu == resList[s].cpu) { + item.children.push(resList[s]); + item.count += resList[s].count; + item.dur += resList[s].dur; + item.percent += resList[s].percent; + } + } + }); + // 将cpu数据放置到对应周期层级下 + this.mergeCycleData(cycleMap.get(key)[i], cpuMap.get(key)); } - } - finalArr[i].percent = Number((finalArr[i].percent).toFixed(2)); + }); + // 拷贝线程数组,防止数据污染 + let threadArr = JSON.parse(JSON.stringify(this.threadArr)); + // 拷贝进程数组,防止数据污染 + let processArr = JSON.parse(JSON.stringify(this.processArr)); + // 将周期层级防止到线程层级下 + this.mergeThreadData(threadArr, cycleMap); + // 将原始数据放置到对应的线程层级下,周期数据前 + let totalData = this.merge(totalList); + this.mergeTotalData(threadArr, totalData); + // 合并数据到进程层级下 + this.mergePidData(processArr, threadArr); + this.fixedDeal(processArr); + this.threadStatesTblSource = processArr; + this.threadStatesTbl!.recycleDataSource = processArr; + this.threadStatesTbl!.loading = false; + this.threadClick(processArr); + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; } - - let newArr1 = JSON.parse(JSON.stringify(finalResultArr[0])); - let newArr2 = JSON.parse(JSON.stringify(finalArr)); - let finalResult = new Array(this.mergeTree(newArr1, newArr2)); - this.threadStatesTblSource = finalResult[0].children.length > 0 ? finalResult : []; - this.threadStatesTbl!.recycleDataSource = finalResult[0].children.length > 0 ? finalResult : []; }) } else { - alert('请输入正确的线程ID'); + this.threadStatesTbl!.loading = false; + if (threadIdValue == '') { + threadId.style.border = '1px solid rgb(255,0,0)'; + threadId.setAttribute('placeholder', 'Please input thread id'); + } + if (threadFuncName == '') { + threadFunc.style.border = '1px solid rgb(255,0,0)'; + threadFunc.setAttribute('placeholder', 'Please input function name'); + } } } - dataSingleCut(threadId: any, threadFunc: any, resultList: any) { + // Loop方式切割数据功能 + dataLoopCut(threadId: any, threadFunc: any, resultList: any) { + threadId.style.border = '1px solid rgb(151,151,151)'; + threadFunc.style.border = '1px solid rgb(151,151,151)'; let threadIdValue = threadId.value.trim(); let threadFuncName = threadFunc.value.trim(); let leftNS = this.currentSelectionParam.leftNs; let rightNS = this.currentSelectionParam.rightNs; let tableValue: any = this.threadStatesTbl; tableValue.value = []; - if (/^[0-9]*$/.test(threadIdValue)) { - querySearchFuncData(threadFuncName, threadIdValue, leftNS, rightNS).then(result => { - let [...targetList] = JSON.parse(JSON.stringify(resultList)); - let timeDur = this.currentSelectionParam.recordStartNs; - let dealArr = new Array(); - for (let i of result) { - if (i.startTime + timeDur + i.dur < this.currentSelectionParam.rightNs + timeDur) { - dealArr.push({ 'ts': i.startTime + timeDur, 'dur': i.dur }); + if (threadIdValue != '' && threadFuncName != '') { + querySearchFuncData(threadFuncName, Number(threadIdValue), leftNS, rightNS).then(res => { + if (res != null && res.length > 0) { + let targetMap = new Map(); + // 新创建map对象接收传过来的实参map + resultList.forEach((item: any, key: any) => { + targetMap.set(key, JSON.parse(JSON.stringify(item))); + }) + let timeDur = this.currentSelectionParam.recordStartNs; + let cutArr = new Array(); + // 根据线程id及方法名获取的数据,处理后用作切割时间依据,时间跨度为整个方法开始时间到末个方法开始时间 + for (let i of res) { + cutArr[cutArr.length - 1] && (cutArr[cutArr.length - 1].dur = i.startTime ? i.startTime + timeDur - cutArr[cutArr.length - 1].ts : 0); + cutArr.push({ 'ts': i.startTime + timeDur, 'dur': 0 }); + } - } - let finalResultArr = new Array(); - finalResultArr.push({ 'thread': targetList[0].thread, 'ts': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); - let resList = new Array(); - const tsMutiple = 1000000000; - for (let i = 0; i < dealArr.length; i++) { - for (let j = 0; j < targetList.length; j++) { - targetList[j].ts = targetList[j].ts * tsMutiple; - if (dealArr[i].ts < targetList[j].ts) { - if (dealArr[i].ts + dealArr[i].dur > targetList[j].ts) { - if (dealArr[i].ts + dealArr[i].dur > targetList[j].ts + targetList[j].dur) { - resList.push({ 'thread': targetList[i].thread, 'ts': (targetList[j].ts - timeDur) / tsMutiple, 'count': (targetList[j].freq * targetList[j].dur) / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': targetList[j].dur, 'percent': targetList[j].percent, 'state': 'Running', 'id': i }); + let cycleMap = new Map(); + let totalList = new Map(); + targetMap.forEach((item, key) => { + cycleMap.set(key, new Array()); + totalList.set(key, new Array()); + for (let i = 0; i < cutArr.length - 1; i++) { + let cpuArr = new Array(); + let cpuMap = new Map(); + let resList = new Array(); + // 时间由纳秒转换为秒的倍数 + const multiple = 1000000000; + // 算力倍数值 + const countMutiple = 1000; + cpuMap.set(key, new Array()); + cycleMap.get(key).push({ 'thread': '周期' + (i + 1) + '—' + item[0].thread, 'ts': ((cutArr[i].ts - timeDur) / 1000000).toFixed(3), 'cdur': (cutArr[i].dur / 1000000).toFixed(3), 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + let value = JSON.parse(JSON.stringify(item)); + for (let j = 0; j < value.length; j++) { + value[j].ts = value[j].ts * multiple; + value[j].freq = value[j].freq == 'unknown' ? 0 : value[j].freq; + if (!cpuArr.includes(value[j].cpu)) { + cpuArr.push(value[j].cpu); + cpuMap.get(key).push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': 0, 'cpu': value[j].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + } + if (value[j].ts >= cutArr[i].ts) { + if ((value[j].ts + value[j].dur) <= cutArr[i + 1].ts) { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * value[j].dur) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].dur, 'percent': value[j].percent, 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * value[j].dur) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].dur, 'percent': value[j].percent, 'state': 'Running', 'id': i }); + } else { + if (cutArr[i + 1].ts - value[j].ts > 0) { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * (cutArr[i + 1].ts - value[j].ts)) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': cutArr[i + 1].ts - value[j].ts, 'percent': value[j].percent * ((cutArr[i + 1].ts - value[j].ts) / value[j].dur), 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * (cutArr[i + 1].ts - value[j].ts)) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': cutArr[i + 1].ts - value[j].ts, 'percent': value[j].percent * ((cutArr[i + 1].ts - value[j].ts) / value[j].dur), 'state': 'Running', 'id': i }); + break; + } + } } else { - resList.push({ 'thread': targetList[j].thread, 'ts': (targetList[j].ts - timeDur) / tsMutiple, 'count': (dealArr[i].ts + dealArr[i].dur - targetList[j].ts) * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': dealArr[i].ts + dealArr[i].dur - targetList[j].ts, 'percent': (dealArr[i].ts + dealArr[i].dur - targetList[j].ts) / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); + if ((value[j].ts + value[j].dur) > cutArr[i + 1].ts) { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * (cutArr[i + 1].ts - cutArr[i].ts)) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': cutArr[i + 1].ts - cutArr[i].ts, 'percent': value[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / value[j].dur), 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * (cutArr[i + 1].ts - cutArr[i].ts)) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': cutArr[i + 1].ts - cutArr[i].ts, 'percent': value[j].percent * ((cutArr[i + 1].ts - cutArr[i].ts) / value[j].dur), 'state': 'Running', 'id': i }); + } + if ((value[j].ts + value[j].dur) > cutArr[i].ts && (value[j].ts + value[j].dur) < cutArr[i + 1].ts) { + resList.push({ 'thread': '周期' + (i + 1) + '—' + value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * (value[j].dur + value[j].ts - cutArr[i].ts)) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].dur + value[j].ts - cutArr[i].ts, 'percent': value[j].percent * ((value[j].dur + value[j].ts - cutArr[i].ts) / value[j].dur), 'state': 'Running', 'id': i }); + totalList.get(key).push({ 'thread': value[j].thread, 'pid': value[j].pid, 'tid': value[j].tid, 'count': (value[j].freq * (value[j].dur + value[j].ts - cutArr[i].ts)) / countMutiple, 'cpu': value[j].cpu, 'freq': value[j].freq, 'dur': value[j].dur + value[j].ts - cutArr[i].ts, 'percent': value[j].percent * ((value[j].dur + value[j].ts - cutArr[i].ts) / value[j].dur), 'state': 'Running', 'id': i }); + } + } + } + // 合并相同周期内的数据 + this.mergeData(resList); + // 以算力消耗降序排列 + resList.sort((a, b) => b.count - a.count); + // 以cpu升序排列 + cpuMap.get(key).sort((a: any, b: any) => a.cpu - b.cpu); + cpuMap.get(key).forEach((item: any) => { + for (let s = 0; s < resList.length; s++) { + if (item.cpu == resList[s].cpu) { + item.children.push(resList[s]); + item.count += resList[s].count; + item.dur += resList[s].dur; + item.percent += resList[s].percent; + } + } + }); + // 将cpu数据放置到对应周期层级下 + this.mergeCycleData(cycleMap.get(key)[i], cpuMap.get(key)); + } + }); + let threadArr = JSON.parse(JSON.stringify(this.threadArr)); + let processArr = JSON.parse(JSON.stringify(this.processArr)); + this.mergeThreadData(threadArr, cycleMap); + let totalData = this.merge(totalList); + this.mergeTotalData(threadArr, totalData); + this.mergePidData(processArr, threadArr); + this.fixedDeal(processArr); + this.threadStatesTblSource = processArr; + this.threadStatesTbl!.recycleDataSource = processArr; + this.threadStatesTbl!.setStatus(processArr, true); + this.threadStatesTbl!.loading = false; + this.threadClick(processArr); + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; + } + }) + } else { + this.threadStatesTbl!.loading = false; + if (threadIdValue == '') { + threadId.style.border = '1px solid rgb(255,0,0)'; + threadId.setAttribute('placeholder', 'Please input thread id'); + } + if (threadFuncName == '') { + threadFunc.style.border = '1px solid rgb(255,0,0)'; + threadFunc.setAttribute('placeholder', 'Please input function name'); + } + } + } + // 整理出框选区域内的频点数据 + mergeFreqData(needDeal: any, dealArr: any, sum: number) { + needDeal.forEach((value: any, key: any) => { + let resultList = new Array(); + // 时间由纳秒转换为秒的倍数 + const multiple = 1000000000; + // 算力倍数值 + const countMutiple = 1000; + for (let i = 0; i < value.length; i++) { + for (let j = 0; j < dealArr.length; j++) { + if (value[i].cpu == dealArr[j].cpu) { + if (value[i].ts > dealArr[j].startNS) { + if (value[i].ts < (dealArr[j].startNS + dealArr[j].dur)) { + if (value[i].dur < (dealArr[j].startNS + dealArr[j].dur - value[i].ts)) { + resultList.push({ 'thread': value[i].thread, 'pid': value[i].pid, 'tid': value[i].tid, 'count': (dealArr[j].value * value[i].dur) / countMutiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': value[i].dur, 'percent': value[i].dur / sum * 100, 'state': 'Running', 'ts': value[i].ts / multiple }); break; + } else { + resultList.push({ 'thread': value[i].thread, 'pid': value[i].pid, 'tid': value[i].tid, 'count': (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - value[i].ts)) / countMutiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': (dealArr[j].startNS + dealArr[j].dur - value[i].ts), 'percent': (dealArr[j].startNS + dealArr[j].dur - value[i].ts) / sum * 100, 'state': 'Running', 'ts': value[i].ts / multiple }); } } } else { - if (targetList[j].ts + targetList[j].dur > dealArr[i].ts) { - if (targetList[j].ts + targetList[j].dur > dealArr[i].ts + dealArr[i].dur) { - resList.push({ 'thread': targetList[j].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': dealArr[i].dur * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': dealArr[i].dur, 'percent': dealArr[i].dur / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); + if ((value[i].ts + value[i].dur) > dealArr[j].startNS) { + if ((value[i].dur + value[i].ts - dealArr[j].startNS) < dealArr[j].dur) { + resultList.push({ 'thread': value[i].thread, 'pid': value[i].pid, 'tid': value[i].tid, 'count': (dealArr[j].value * (value[i].dur + value[i].ts - dealArr[j].startNS)) / countMutiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': (value[i].dur + value[i].ts - dealArr[j].startNS), 'percent': (value[i].dur + value[i].ts - dealArr[j].startNS) / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS / multiple }); break; } else { - resList.push({ 'thread': targetList[j].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': (targetList[j].ts + targetList[j].dur - dealArr[i].ts) * targetList[j].freq / 1000, 'cpu': targetList[j].cpu, 'freq': targetList[j].freq, 'dur': targetList[j].ts + targetList[j].dur - dealArr[i].ts, 'percent': (targetList[j].ts + targetList[j].dur - dealArr[i].ts) / targetList[j].dur * targetList[j].percent, 'state': 'Running', 'id': i }); + resultList.push({ 'thread': value[i].thread, 'pid': value[i].pid, 'tid': value[i].tid, 'count': (dealArr[j].value * dealArr[j].dur) / countMutiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': dealArr[j].dur, 'percent': dealArr[j].dur / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS / multiple }); } + } else { + resultList.push({ 'thread': value[i].thread, 'pid': value[i].pid, 'tid': value[i].tid, 'count': 0, 'cpu': value[i].cpu, 'freq': 'unknown', 'dur': value[i].dur, 'percent': value[i].dur / sum * 100, 'state': 'Running', 'ts': value[i].ts / multiple }); + break; } } } - finalResultArr[0].children.push({ 'thread': targetList[0].thread, 'ts': (dealArr[i].ts - timeDur) / tsMutiple, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array(), 'id': i }); } - // 合并相同周期内的数据 - for (let i = 0; i < resList.length; i++) { - for (let j = i + 1; j < resList.length; j++) { - if (resList[i].cpu === resList[j].cpu && resList[i].freq === resList[j].freq && resList[i].id === resList[j].id) { - resList[i].dur += resList[j].dur; - resList[i].percent += resList[j].percent; - resList[i].count += resList[j].count; - resList.splice(j, 1); - j--; - } - } - resList[i].percent = Number((resList[i].percent).toFixed(2)); + } + this.initData.set(key, JSON.parse(JSON.stringify(resultList))); + }) + } + // 将cpu层级数据放置到线程分组下 + mergeThreadData(threadArr: any, cpuMap: any) { + for (let i = 0; i < threadArr.length; i++) { + let cpuMapData = cpuMap.get(threadArr[i].pid + '_' + threadArr[i].tid); + for (let j = 0; j < cpuMapData.length; j++) { + threadArr[i].children.push(cpuMapData[j]); + threadArr[i].count += cpuMapData[j].count; + threadArr[i].dur += cpuMapData[j].dur; + threadArr[i].percent += cpuMapData[j].percent; + } + } + } + // 将线程级数据放置到对应的进程分组下 + mergePidData(pidArr: any, threadArr: any) { + for (let i = 0; i < pidArr.length; i++) { + for (let j = 0; j < threadArr.length; j++) { + if (pidArr[i].pid == threadArr[j].pid) { + pidArr[i].children.push(threadArr[j]); + pidArr[i].count += threadArr[j].count; + pidArr[i].dur += threadArr[j].dur; + pidArr[i].percent += threadArr[j].percent; } - - let newArr1 = JSON.parse(JSON.stringify(finalResultArr[0])); - let newArr2 = JSON.parse(JSON.stringify(resList)); - let finalResult = new Array(this.mergeTree(newArr1, newArr2)); - - this.threadStatesTblSource = finalResult[0].children.length > 0 ? finalResult : []; - this.threadStatesTbl!.recycleDataSource = finalResult[0].children.length > 0 ? finalResult : []; - }) - } else { - alert('请输入正确的线程ID'); + } } } - - mergeTree(arr1: any, arr2: any) { - for (let i = 0; i < arr1.children.length; i++) { - // 改成map对象做标记 + // 合并相同周期内的cpu、频点都相同的数据 + mergeData(resList: any) { + // 合并相同周期内的数据 + for (let i = 0; i < resList.length; i++) { + for (let j = i + 1; j < resList.length; j++) { + if (resList[i].cpu === resList[j].cpu && resList[i].freq === resList[j].freq && resList[i].id === resList[j].id) { + resList[i].dur += resList[j].dur; + resList[i].percent += resList[j].percent; + resList[i].count += resList[j].count; + resList.splice(j, 1); + j--; + } + } + } + } + // 将cpu层级数据放置到对应周期分组下 + mergeCycleData(obj: any, arr: any) { + for (let i = 0; i < arr.length; i++) { + if (arr[i].count === 0 && arr[i].dur === 0) { + continue; + } + obj.children.push(arr[i]); + obj.count += arr[i].count; + obj.dur += arr[i].dur; + obj.percent += arr[i].percent; + } + } + // 将total数据存放到线程分组下,周期数据前 + mergeTotalData(threadArr: any, totalData: any) { + for (let i = 0; i < threadArr.length; i++) { + for (let j = 0; j < totalData.length; j++) { + if (threadArr[i].pid == totalData[j].pid && threadArr[i].tid == totalData[j].tid) { + totalData[j].thread = 'TotalData'; + threadArr[i].children.unshift(totalData[j]); + } + } + } + } + // 将百分比做两位小数处理 + fixedDeal(arr: any) { + if (arr == undefined) { + return; + } + for (let i = 0; i < arr.length; i++) { + arr[i].percent = arr[i].percent.toFixed(2); + arr[i].percent = arr[i].percent > 100 ? 100 : arr[i].percent; + this.fixedDeal(arr[i].children); + } + } + // 合并切割后的total数据,并按照cpu分组 + merge(totalList: any) { + let result = new Array(); + totalList.forEach((value: any, key: any) => { + let countNum = result.push({ 'thread': '', 'pid': key.split('_')[0], 'tid': key.split('_')[1], 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); let cpuArr = new Array(); - let flagMap = new Map(); - let flag = 0; - for (let j = 0; j < arr2.length; j++) { - if (arr1.children[i].id == arr2[j].id) { - if (!cpuArr.includes(arr2[j].cpu)) { - flagMap.set(arr2[j].cpu, flag); - cpuArr.push(arr2[j].cpu); - arr1.children[i].children.push({ 'thread': arr2[j].thread, 'count': 0, 'cpu': arr2[j].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', 'ts': '', children: new Array(), 'id': arr2[j].id }); - if (arr1.children[i].children[flag].cpu == arr2[j].cpu && arr1.children[i].children[flag].id == arr2[j].id) { - arr1.children[i].children[flag].children.push(arr2[j]); - arr1.children[i].children[flag].dur += arr2[j].dur; - arr1.children[i].children[flag].percent += arr2[j].percent; - arr1.children[i].children[flag].count += arr2[j].count; - arr1.children[i].percent += arr1.children[i].children[flag].percent; - arr1.children[i].children[flag].percent = Number(arr1.children[i].children[flag].percent.toFixed(2)); - arr1.children[i].dur += arr1.children[i].children[flag].dur; - arr1.children[i].count += arr1.children[i].children[flag].count; - flag++; - arr2.splice(j, 1); - j--; - } - } else { - // 利用map做数据处理 - let count = flagMap.get(arr2[j].cpu); - if (arr1.children[i].children[count].cpu == arr2[j].cpu && arr1.children[i].children[count].id == arr2[j].id) { - arr1.children[i].children[count].children.push(arr2[j]); - arr1.children[i].children[count].dur += arr2[j].dur; - arr1.children[i].children[count].percent += arr2[j].percent; - arr1.children[i].children[count].count += arr2[j].count; - arr1.children[i].percent += arr2[j].percent; - arr1.children[i].children[count].percent = Number(arr2[j].percent.toFixed(2)); - arr1.children[i].dur += arr2[j].dur; - arr1.children[i].count += arr2[j].count; - arr2.splice(j, 1); - j--; - } + let flagArr = new Array(); + for (let i = 0; i < value.length; i++) { + if (!flagArr.includes(value[i].cpu)) { + flagArr.push(value[i].cpu); + let flag = cpuArr.push({ 'thread': value[i].thread, 'pid': value[i].pid, 'tid': value[i].tid, 'count': 0, 'cpu': value[i].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + result[countNum - 1].children.push(cpuArr[flag - 1]); + } + for (let j = i + 1; j < value.length; j++) { + if (value[i].cpu === value[j].cpu && value[i].freq === value[j].freq) { + value[i].dur += value[j].dur; + value[i].percent += value[j].percent; + value[i].count += value[j].count; + value.splice(j, 1); + j--; } - } else { - break; } } - arr1.children[i].children.sort((a: any, b: any) => a.cpu - b.cpu); - arr1.percent += arr1.children[i].percent; - arr1.children[i].percent = Number(arr1.children[i].percent.toFixed(2)); - arr1.dur += arr1.children[i].dur; - arr1.count += arr1.children[i].count; - } - arr1.percent = Number(arr1.percent.toFixed(2)); - return arr1; + result[countNum - 1].children.sort((a: any, b: any) => a.cpu - b.cpu); + for (let i = 0; i < cpuArr.length; i++) { + for (let j = 0; j < value.length; j++) { + if (cpuArr[i].cpu == value[j].cpu) { + cpuArr[i].children.push(value[j]); + cpuArr[i].dur += value[j].dur; + cpuArr[i].count += value[j].count; + cpuArr[i].percent += value[j].percent; + } + } + result[countNum - 1].dur += cpuArr[i].dur; + result[countNum - 1].count += cpuArr[i].count; + result[countNum - 1].percent += cpuArr[i].percent; + } + }); + return result; } } \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts index d0301e1c7caea81794dce3f1668ae2faaa7cc91c..7a4f321b44c5eed59cd79e3f2dad15ab1a7af0b2 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts @@ -14,215 +14,248 @@ */ import { BaseElement, element } from '../../../../../base-ui/BaseElement.js'; -import { LitTable } from '../../../../../base-ui/table/lit-table'; -import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; -import '../../../StackBar.js'; +import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table.js'; +import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection.js'; +import '../../../StackBar.js' import { getTabRunningPercent, queryCpuFreqUsageData, queryCpuFreqFilterId } from '../../../../database/SqlLite.js'; import { Utils } from '../../base/Utils.js'; import { resizeObserver } from '../SheetUtils.js'; +import { SliceGroup } from '../../../../bean/StateProcessThread.js'; @element('tabpane-frequsage') export class TabPaneFreqUsage extends BaseElement { - private threadStatesTbl: LitTable | null | undefined; - private threadStatesTblSource: Array = []; - private currentSelectionParam: Selection | undefined; + private threadStatesTbl: LitTable | null | undefined; + private threadStatesTblSource: Array = []; + private currentSelectionParam: Selection | undefined; - set data(threadStatesParam: SelectionParam | any) { - if (this.currentSelectionParam === threadStatesParam) { - return; + set data(threadStatesParam: SelectionParam | any) { + if (this.currentSelectionParam === threadStatesParam) { + return; + } + this.threadStatesTbl!.loading = true; + this.currentSelectionParam = threadStatesParam; + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + let tableValue: any = this.threadStatesTbl; + tableValue.value = []; + // 查询框选区域内的状态为running的数据 + getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => { + // 查询该trace文件中的cpu核数及id + queryCpuFreqFilterId().then(r => { + // 将查询结果以键值对形式存入Map对象,仪表后续将频点数据与Cpu进行关联 + let IdMap = new Map(); + let queryId = new Array(); + for (let i = 0; i < r.length; i++) { + queryId.push(r[i].id); + IdMap.set(r[i].id, r[i].cpu); + } + // 通过cpu的id去查询总的cpu频点数据 + queryCpuFreqUsageData(queryId).then((res) => { + if (result != null && result.length > 0) { + let sum = 0; + let dealArr = new Array(); + // 将cpu频点数据进行整合 + for (let i of res) { + dealArr.push({ 'startNS': i.startNS + threadStatesParam.recordStartNs, 'dur': i.dur, 'value': i.value, 'cpu': IdMap.get(i.filter_id) }); + } + let needDeal = new Map(); + let cpuMap = new Map(); + let pidArr = new Array(); + let threadArr = new Array(); + // 创建进程级的数组 + let processArr: any = threadStatesParam.processIds.length > 1 ? [...new Set(threadStatesParam.processIds)] : threadStatesParam.processIds; + for (let i of processArr) { + pidArr.push({ 'process': Utils.PROCESS_MAP.get(i) == null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, 'thread': Utils.PROCESS_MAP.get(i) == null ? 'Process ' + i : Utils.PROCESS_MAP.get(i) + ' ' + i, 'pid': i, 'tid': '', 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + } + // 将running线程数据存到map中 + for (let e of result) { + if (processArr.includes(e.pid) && e.state == 'Running') { + if (needDeal.get(e.pid + '_' + e.tid) == undefined) { + threadArr.push({ 'process': Utils.PROCESS_MAP.get(e.pid) == null ? 'Process ' + e.pid : Utils.PROCESS_MAP.get(e.pid) + ' ' + e.pid, 'thread': Utils.THREAD_MAP.get(e.tid) + ' ' + e.tid, 'pid': e.pid, 'tid': e.tid, 'count': 0, 'cpu': '', 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); + needDeal.set(e.pid + '_' + e.tid, new Array()); + } + if((e.ts < (threadStatesParam.leftNs + threadStatesParam.recordStartNs)) && ((e.ts + e.dur) > (threadStatesParam.leftNs + threadStatesParam.recordStartNs))){ + const ts = e.ts; + e.ts = threadStatesParam.leftNs + threadStatesParam.recordStartNs; + e.dur = ts + e.dur - (threadStatesParam.leftNs + threadStatesParam.recordStartNs); + } + if((e.ts + e.dur) > (threadStatesParam.rightNs + threadStatesParam.recordStartNs)){ + e.dur = threadStatesParam.rightNs + threadStatesParam.recordStartNs - e.ts; + } + let arr = needDeal.get(e.pid + '_' + e.tid); + let process = Utils.PROCESS_MAP.get(e.pid); + let thread = Utils.THREAD_MAP.get(e.tid); + e.process = process == null || process.length == 0 ? '[NULL]' : process; + e.thread = thread == null || thread.length == 0 ? '[NULL]' : thread; + e.stateJX = e.state; + e.state = Utils.getEndState(e.stateJX); + sum += e.dur; + arr.push(e); + } + } + // 整理running线程数据、cpu层级信息 + this.mergeFreqData(needDeal, cpuMap, dealArr, sum, threadStatesParam); + // 将频点数据放置到对应cpu层级下 + this.mergeCpuData(cpuMap, needDeal); + // 将cpu层级数据放置到线程分组下 + this.mergeThreadData(threadArr, cpuMap); + // 将线程层级数据放置到进程级分组下 + this.mergePidData(pidArr, threadArr); + // 百分比保留两位小数 + this.fixedDeal(pidArr) + this.threadStatesTblSource = pidArr; + this.threadStatesTbl!.recycleDataSource = pidArr; + this.threadStatesTbl!.loading = false; + this.theadClick(pidArr); + } else { + this.threadStatesTblSource = []; + this.threadStatesTbl!.recycleDataSource = []; + this.threadStatesTbl!.loading = false; + } + }) + }) + + }) } - this.currentSelectionParam = threadStatesParam; - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; - let tableValue: any = this.threadStatesTbl; - tableValue.value = []; - getTabRunningPercent(threadStatesParam.threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then( - (result) => { - queryCpuFreqFilterId().then((r) => { - let IdMap = new Map(); - let queryId = new Array(); - for (let i = 0; i < r.length; i++) { - queryId.push(r[i].id); - IdMap.set(r[i].id, r[i].cpu); - } - queryCpuFreqUsageData(queryId).then((res) => { - if (result != null && result.length > 0) { - let sum = 0; - let dealArr = new Array(); - for (let i of res) { - dealArr.push({ - startNS: i.startNS + threadStatesParam.recordStartNs, - dur: i.dur, - value: i.value, - cpu: IdMap.get(i.filter_id), + + private theadClick(data: Array) { + let labels = this.threadStatesTbl?.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.threadStatesTbl!.setStatus(data, false); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); + } else if (label.includes('Thread') && i === 1) { + for (let item of data) { + 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('CPU') && i === 2) { + this.threadStatesTbl!.setStatus(data, true); + this.threadStatesTbl!.recycleDs = this.threadStatesTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); + } }); - } - let targetList = new Array(); - let cpuArr = new Array(); - let finalResultArr = new Array(); - finalResultArr.push({ - thread: '', - count: 0, - cpu: '', - freq: '', - dur: 0, - percent: '100.00', - state: 'Running', - children: new Array(), - }); - for (let e of result) { - if (threadStatesParam.processIds.includes(e.pid) && e.state == 'Running') { - let process = Utils.PROCESS_MAP.get(e.pid); - let thread = Utils.THREAD_MAP.get(e.tid); - e.process = process == null || process.length == 0 ? '[NULL]' : process; - e.thread = thread == null || thread.length == 0 ? '[NULL]' : thread; - e.stateJX = e.state; - e.state = Utils.getEndState(e.stateJX); - sum += e.dur; - targetList.push(e); - if (!cpuArr.includes(e.cpu)) { - cpuArr.push(e.cpu); - finalResultArr[0].thread = - finalResultArr[0].thread == '' ? e.tid + '_' + e.thread : finalResultArr[0].thread; - finalResultArr[0].children.push({ - thread: e.tid + '_' + e.thread, - count: 0, - cpu: e.cpu, - freq: '', - dur: 0, - percent: 0, - state: 'Running', - children: new Array(), - }); - } + } + } + } + mergeFreqData(needDeal: any, cpuMap: any, dealArr: any, sum: number, threadStatesParam: SelectionParam | any) { + needDeal.forEach((value: any, key: any) => { + let resultList = new Array(); + cpuMap.set(key, new Array()); + let cpuArr = new Array(); + const multiple = 1000; + for (let i = 0; i < value.length; i++) { + if (!cpuArr.includes(value[i].cpu)) { + cpuArr.push(value[i].cpu); + cpuMap.get(key).push({ 'process': Utils.PROCESS_MAP.get(value[i].pid) == null ? 'Process ' + value[i].pid : Utils.PROCESS_MAP.get(value[i].pid) + ' ' + value[i].pid, 'thread': value[i].tid + '_' + Utils.THREAD_MAP.get(value[i].tid), 'pid': value[i].pid, 'tid': value[i].tid, 'count': 0, 'cpu': value[i].cpu, 'freq': '', 'dur': 0, 'percent': 0, 'state': 'Running', children: new Array() }); } - } - let resultList = new Array(); - for (let i = 0; i < targetList.length; i++) { for (let j = 0; j < dealArr.length; j++) { - if (targetList[i].cpu == dealArr[j].cpu) { - if (targetList[i].ts > dealArr[j].startNS) { - if (targetList[i].ts < dealArr[j].startNS + dealArr[j].dur) { - if (targetList[i].dur < dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) { - resultList.push({ - thread: targetList[i].tid + '_' + targetList[i].thread, - count: (dealArr[j].value * targetList[i].dur) / 1000, - cpu: targetList[i].cpu, - freq: dealArr[j].value, - dur: targetList[i].dur, - percent: (targetList[i].dur / sum) * 100, - state: 'Running', - ts: targetList[i].ts, - }); - break; - } else { - resultList.push({ - thread: targetList[i].tid + '_' + targetList[i].thread, - count: (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - targetList[i].ts)) / 1000, - cpu: targetList[i].cpu, - freq: dealArr[j].value, - dur: dealArr[j].startNS + dealArr[j].dur - targetList[i].ts, - percent: ((dealArr[j].startNS + dealArr[j].dur - targetList[i].ts) / sum) * 100, - state: 'Running', - ts: targetList[i].ts, - }); - } - } - } else { - if (targetList[i].ts + targetList[i].dur > dealArr[j].startNS) { - if (targetList[i].dur + targetList[i].ts - dealArr[j].startNS < dealArr[j].dur) { - resultList.push({ - thread: targetList[i].tid + '_' + targetList[i].thread, - count: - (dealArr[j].value * (targetList[i].dur + targetList[i].ts - dealArr[j].startNS)) / 1000, - cpu: targetList[i].cpu, - freq: dealArr[j].value, - dur: targetList[i].dur + targetList[i].ts - dealArr[j].startNS, - percent: ((targetList[i].dur + targetList[i].ts - dealArr[j].startNS) / sum) * 100, - state: 'Running', - ts: dealArr[j].startNS, - }); - break; + if (value[i].cpu == dealArr[j].cpu) { + if (value[i].ts > dealArr[j].startNS) { + if (value[i].ts < (dealArr[j].startNS + dealArr[j].dur)) { + if (value[i].dur < (dealArr[j].startNS + dealArr[j].dur - value[i].ts)) { + resultList.push({ 'thread': value[i].tid + '_' + value[i].thread, 'count': (dealArr[j].value * value[i].dur) / multiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': value[i].dur, 'percent': value[i].dur / sum * 100, 'state': 'Running', 'ts': value[i].ts }); + break; + } else { + resultList.push({ 'thread': value[i].tid + '_' + value[i].thread, 'count': (dealArr[j].value * (dealArr[j].startNS + dealArr[j].dur - value[i].ts)) / multiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': (dealArr[j].startNS + dealArr[j].dur - value[i].ts), 'percent': (dealArr[j].startNS + dealArr[j].dur - value[i].ts) / sum * 100, 'state': 'Running', 'ts': value[i].ts }); + } + } } else { - resultList.push({ - thread: targetList[i].tid + '_' + targetList[i].thread, - count: (dealArr[j].value * dealArr[j].dur) / 1000, - cpu: targetList[i].cpu, - freq: dealArr[j].value, - dur: dealArr[j].dur, - percent: (dealArr[j].dur / sum) * 100, - state: 'Running', - ts: dealArr[j].startNS, - }); + if ((value[i].ts + value[i].dur) > dealArr[j].startNS) { + if ((value[i].dur + value[i].ts - dealArr[j].startNS) < dealArr[j].dur) { + resultList.push({ 'thread': value[i].tid + '_' + value[i].thread, 'count': (dealArr[j].value * (value[i].dur + value[i].ts - dealArr[j].startNS)) / multiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': (value[i].dur + value[i].ts - dealArr[j].startNS), 'percent': (value[i].dur + value[i].ts - dealArr[j].startNS) / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS }); + break; + } else { + resultList.push({ 'thread': value[i].tid + '_' + value[i].thread, 'count': (dealArr[j].value * dealArr[j].dur) / multiple, 'cpu': value[i].cpu, 'freq': dealArr[j].value, 'dur': dealArr[j].dur, 'percent': dealArr[j].dur / sum * 100, 'state': 'Running', 'ts': dealArr[j].startNS }); + } + } else { + resultList.push({ 'thread': value[i].tid + '_' + value[i].thread, 'count': 0, 'cpu': value[i].cpu, 'freq': 'unknown', 'dur': value[i].dur, 'percent': value[i].dur / sum * 100, 'state': 'Running', 'ts': value[i].ts }); + break; + } } - } else { - resultList.push({ - thread: targetList[i].tid + '_' + targetList[i].thread, - count: 0, - cpu: targetList[i].cpu, - freq: 'unknown', - dur: targetList[i].dur, - percent: (targetList[i].dur / sum) * 100, - state: 'Running', - ts: targetList[i].ts, - }); - break; - } } - } } - } - //合并同一线程内,当运行所在cpu和频点相同时,dur及percent进行累加求和,或许可以进行算法优化 - for (let i = 0; i < resultList.length; i++) { + } + //合并同一线程内,当运行所在cpu和频点相同时,dur及percent进行累加求和,或许可以进行算法优化 + for (let i = 0; i < resultList.length; i++) { for (let j = i + 1; j < resultList.length; j++) { - if (resultList[i].cpu == resultList[j].cpu && resultList[i].freq == resultList[j].freq) { - resultList[i].dur += resultList[j].dur; - resultList[i].percent += resultList[j].percent; - resultList[i].count += resultList[j].count; - resultList.splice(j, 1); - j--; - } + if (resultList[i].cpu == resultList[j].cpu && resultList[i].freq == resultList[j].freq) { + resultList[i].dur += resultList[j].dur; + resultList[i].percent += resultList[j].percent; + resultList[i].count += resultList[j].count; + resultList.splice(j, 1); + j--; + } } - resultList[i].percent = Number(resultList[i].percent.toFixed(2)); resultList[i].ts = resultList[i].ts - threadStatesParam.recordStartNs; - } - finalResultArr[0].children.sort((a: any, b: any) => a.cpu - b.cpu); - // 转成树结构数据进行展示 - for (let i = 0; i < finalResultArr[0].children.length; i++) { - for (let j = 0; j < resultList.length; j++) { - if (finalResultArr[0].children[i].cpu == resultList[j].cpu) { - finalResultArr[0].children[i].children.push(resultList[j]); - finalResultArr[0].children[i].dur += resultList[j].dur; - finalResultArr[0].children[i].percent += resultList[j].percent; - finalResultArr[0].children[i].count += resultList[j].count; - resultList.splice(j, 1); - j--; - } + } + resultList.sort((a, b) => b.count - a.count); + cpuMap.get(key).sort((a: any, b: any) => a.cpu - b.cpu); + needDeal.set(key, resultList); + }) + } + mergeCpuData(cpuMap: any, needDeal: any) { + cpuMap.forEach((value: any, key: any) => { + let arr = needDeal.get(key); + for (let i = 0; i < value.length; i++) { + for (let j = 0; j < arr.length; j++) { + if (arr[j].cpu == value[i].cpu) { + value[i].children.push(arr[j]); + value[i].count += arr[j].count; + value[i].dur += arr[j].dur; + value[i].percent += arr[j].percent; + } } - finalResultArr[0].children[i].percent = finalResultArr[0].children[i].percent.toFixed(2); - finalResultArr[0].dur += finalResultArr[0].children[i].dur; - finalResultArr[0].count += finalResultArr[0].children[i].count; - } - this.threadStatesTblSource = finalResultArr; - this.threadStatesTbl!.recycleDataSource = finalResultArr; - } else { - this.threadStatesTblSource = []; - this.threadStatesTbl!.recycleDataSource = []; } - }); }); - } - ); - } - initElements(): void { - this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-percent'); - } - connectedCallback() { - super.connectedCallback(); - resizeObserver(this.parentElement!, this.threadStatesTbl!); - } - initHtml(): string { - return ` + } + mergeThreadData(threadArr: any, cpuMap: any) { + for (let i = 0; i < threadArr.length; i++) { + let cpuMapData = cpuMap.get(threadArr[i].pid + '_' + threadArr[i].tid); + for (let j = 0; j < cpuMapData.length; j++) { + threadArr[i].children.push(cpuMapData[j]); + threadArr[i].count += cpuMapData[j].count; + threadArr[i].dur += cpuMapData[j].dur; + threadArr[i].percent += cpuMapData[j].percent; + } + } + } + mergePidData(pidArr: any, threadArr: any) { + for (let i = 0; i < pidArr.length; i++) { + for (let j = 0; j < threadArr.length; j++) { + if (pidArr[i].pid == threadArr[j].pid) { + pidArr[i].children.push(threadArr[j]); + pidArr[i].count += threadArr[j].count; + pidArr[i].dur += threadArr[j].dur; + pidArr[i].percent += threadArr[j].percent; + } + } + } + } + fixedDeal(arr: any) { + if (arr == undefined) { + return; + } + for (let i = 0; i < arr.length; i++) { + arr[i].percent = arr[i].percent > 100 ? 100 : arr[i].percent; + arr[i].percent = arr[i].percent.toFixed(2); + this.fixedDeal(arr[i].children); + } + } + initElements(): void { + this.threadStatesTbl = this.shadowRoot?.querySelector('#tb-running-percent'); + } + connectedCallback() { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.threadStatesTbl!); + } + initHtml(): string { + return ` - - - + + + @@ -246,6 +279,36 @@ export class TabPaneFreqUsage extends BaseElement { - `; - } -} + ` + } + sortByColumn(treadStateDetail: any) { + function compare(property: any, treadStatesSort: any, type: any) { + return function (threadStatesLeftData: SelectionData | any, threadStatesRightData: SelectionData | any) { + if (threadStatesLeftData.process == ' ' || threadStatesRightData.process == ' ') { + return 0; + } + if (type === 'number') { + return treadStatesSort === 2 + ? parseFloat(threadStatesRightData[property]) - parseFloat(threadStatesLeftData[property]) + : parseFloat(threadStatesLeftData[property]) - parseFloat(threadStatesRightData[property]); + } else { + if (threadStatesRightData[property] > threadStatesLeftData[property]) { + return treadStatesSort === 2 ? 1 : -1; + } else if (threadStatesRightData[property] == threadStatesLeftData[property]) { + return 0; + } else { + return treadStatesSort === 2 ? -1 : 1; + } + } + }; + } + + if (treadStateDetail.key === 'name' || treadStateDetail.key === 'thread' || treadStateDetail.key === 'state') { + this.threadStatesTblSource.sort(compare(treadStateDetail.key, treadStateDetail.sort, 'string')); + } else { + this.threadStatesTblSource.sort(compare(treadStateDetail.key, treadStateDetail.sort, 'number')); + } + this.threadStatesTbl!.recycleDataSource = this.threadStatesTblSource; + } + +} \ No newline at end of file diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts index 9fdde25ff150f50d679751d8ad48fc2509813437..0a28385bff52d5085f3a720fd2c18b841755c52d 100644 --- a/ide/src/trace/database/SqlLite.ts +++ b/ide/src/trace/database/SqlLite.ts @@ -5500,7 +5500,7 @@ export const queryTraceType = (): Promise< export const queryTransferList = (): Promise> => query('queryTransferList', `select id, report_value as cmdStr from perf_report where report_type = 'config_name'`); - export const getTabRunningPercent = (tIds: Array, leftNS: number, rightNS: number): Promise> => +export const getTabRunningPercent = (tIds: Array, leftNS: number, rightNS: number): Promise> => query( 'getTabRunningPercent', ` @@ -5517,11 +5517,10 @@ export const queryTransferList = (): Promise ${rightNS})) order by ts - `, - { $leftNS: leftNS, $rightNS: rightNS } - ); + ` +); -export const querySearchFuncData = (funcName: string, tIds: Array, leftNS: number, rightNS: number): Promise> => +export const querySearchFuncData = (funcName: string, tIds: number, leftNS: number, rightNS: number): Promise> => query( 'querySearchFuncData', ` @@ -5549,7 +5548,7 @@ export const querySearchFuncData = (funcName: string, tIds: Array, leftN left join trace_range r where - c.name = '${funcName}' + c.name like '${funcName}%' and t.tid = ${tIds} and