From 99c6e1298476f01e49a1fb2c9e89d330ccb63c38 Mon Sep 17 00:00:00 2001 From: liufei Date: Thu, 14 Dec 2023 17:06:03 +0800 Subject: [PATCH 1/5] =?UTF-8?q?helpdocument=E6=B7=BB=E5=8A=A0=E6=94=B6?= =?UTF-8?q?=E8=B5=B7=E5=9B=BE=E6=A0=87=E5=B9=B6=E4=BF=AE=E6=94=B9=E8=BE=B9?= =?UTF-8?q?=E8=B7=9D=EF=BC=8Chiperf=20callchart=E9=BB=98=E8=AE=A4=E6=94=B6?= =?UTF-8?q?=E8=B5=B7=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=9B=9B=E6=9D=A1=E6=B3=B3?= =?UTF-8?q?=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liufei --- ide/src/base-ui/menu/LitMainMenu.ts | 17 ++++- ide/src/base-ui/menu/LitMainMenuGroup.ts | 41 ++++++++--- ide/src/trace/SpApplication.ts | 7 ++ ide/src/trace/component/SpHelp.ts | 10 +++ .../trace/component/chart/SpChartManager.ts | 7 +- ide/src/trace/component/chart/SpHiPerf.ts | 25 +++---- .../trace/component/trace/base/TraceRow.ts | 72 +++++++++++++++---- .../database/ui-worker/ProcedureWorker.ts | 4 ++ ide/webpack.config.js | 59 +++++++++------ 9 files changed, 182 insertions(+), 60 deletions(-) diff --git a/ide/src/base-ui/menu/LitMainMenu.ts b/ide/src/base-ui/menu/LitMainMenu.ts index 8a6f3760b..9f287b122 100644 --- a/ide/src/base-ui/menu/LitMainMenu.ts +++ b/ide/src/base-ui/menu/LitMainMenu.ts @@ -44,7 +44,12 @@ export class LitMainMenu extends BaseElement { value?.forEach((it) => { let group = new LitMainMenuGroup(); group.setAttribute('title', it.title || ''); - group.setAttribute('describe', it.describe || ''); + if (it.describe !== '') { + group.setAttribute('describe', it.describe || ''); + } else { + group.removeAttribute('describe'); + } + group.setAttribute('icon', it.icon || ''); if (it.collapsed) { group.setAttribute('collapsed', ''); } else { @@ -57,7 +62,12 @@ export class LitMainMenu extends BaseElement { if (item.children && item.children.length > 0) { let secondGroup = new LitMainMenuGroup(); secondGroup.setAttribute('title', item.title || ''); - secondGroup.setAttribute('describe', item.describe || ''); + if (item.describe !== '') { + secondGroup.setAttribute('describe', item.describe || ''); + } else { + secondGroup.removeAttribute('describe'); + } + secondGroup.setAttribute('icon', item.icon || ''); if (item.second) { secondGroup.setAttribute('second', ''); } else { @@ -72,7 +82,7 @@ export class LitMainMenu extends BaseElement { item.children?.forEach((v: any) => { let th = new LitMainMenuItem(); th.setAttribute('icon', v.icon || ''); - th.setAttribute('title', v.title || '');if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') === 'dark') { + th.setAttribute('title', v.title || ''); if (this.getAttribute('main_menu') === '1' && window.localStorage.getItem('Theme') === 'dark') { groupName.style.color = 'white'; groupDescribe.style.color = 'white'; th!.style.color = 'white'; @@ -245,6 +255,7 @@ export interface MenuGroup { second: boolean; collapsed: boolean; children: any; + icon: string; } export interface MenuItem { diff --git a/ide/src/base-ui/menu/LitMainMenuGroup.ts b/ide/src/base-ui/menu/LitMainMenuGroup.ts index b9d0fbedf..869978b09 100644 --- a/ide/src/base-ui/menu/LitMainMenuGroup.ts +++ b/ide/src/base-ui/menu/LitMainMenuGroup.ts @@ -21,9 +21,10 @@ export class LitMainMenuGroup extends BaseElement { private groupNameEl: HTMLElement | null | undefined; private groupDescEl: HTMLElement | null | undefined; private group: HTMLElement | null | undefined; + private iconEl: HTMLElement | null | undefined; static get observedAttributes() { - return ['title', 'describe', 'collapsed', 'nocollapse', 'radius', 'second']; + return ['title', 'describe', 'collapsed', 'nocollapse', 'radius', 'second', 'icon']; } get second() { @@ -67,8 +68,9 @@ export class LitMainMenuGroup extends BaseElement { } initElements(): void { - this.groupNameEl = this.shadowRoot?.querySelector('.group-name'); + this.groupNameEl = this.shadowRoot?.querySelector('.group-title'); this.groupDescEl = this.shadowRoot?.querySelector('.group-describe'); + this.iconEl = this.shadowRoot?.querySelector('.icon'); this.group = this.shadowRoot?.querySelector('#group'); this.group!.addEventListener('click', (e) => { if (this.nocollapsed) { @@ -104,6 +106,7 @@ export class LitMainMenuGroup extends BaseElement { :host(:not([collapsed])) .group-describe{ height: 0; visibility: hidden; + padding:0; } :host([collapsed]):hover){ background-color: #FFFFFF; @@ -128,25 +131,38 @@ export class LitMainMenuGroup extends BaseElement { :host([collapsed]) ::slotted(lit-main-menu-group){ display:none; } + :host(:not([describe])) .group-describe{ + display:none; + } + :host([describe]) .group-describe{ + padding: 4px 24px 0 24px; + color: #999 !important; + font-size: 1rem; + } + :host([describe]) .group-name{ + margin-top: 10px; + } .group-name{ + display:flex; font-size: 14px; font-family: Helvetica; color: #000; - padding: 20px 24px 0px 24px; + padding: 15px 24px 5px 10px; line-height: 16px; font-weight: 400; text-align: left; } - .group-describe{ - color: #000; - font-size: 0.6rem; - padding: 4px 24px 20px 24px; + :host([collapsed]) .icon{ + transform: rotateZ(-90deg); } -
-
-
-
+
+
+ + +
+
+
`; } @@ -159,6 +175,9 @@ export class LitMainMenuGroup extends BaseElement { case 'describe': if (this.groupDescEl) this.groupDescEl.textContent = newValue; break; + case 'icon': + if (this.iconEl) this.iconEl.setAttribute('name', newValue); + break; } } } diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index 5b760f70c..00af9a153 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -1064,6 +1064,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Current Trace', second: false, + icon:'', describe: 'Actions on the current trace', children: getTraceOptionMenus(showFileName, fileSize, fileName, true, dbName), }); @@ -1411,6 +1412,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Convert trace', second: false, + icon:'', describe: 'Convert to other formats', children: pushConvertTrace(fileName), }); @@ -1420,6 +1422,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Support', second: false, + icon:'', describe: 'Support', children: [ { @@ -1467,6 +1470,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Current Trace', second: false, + icon:'', describe: 'Actions on the current trace', children: getTraceOptionMenus(showFileName, fileSize, fileName, false), }); @@ -1763,6 +1767,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Current Trace', second: false, + icon:'', describe: 'Actions on the current trace', children: getTraceOptionMenus(showFileName, fileSize, fileName, false), }); @@ -1789,6 +1794,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Navigation', second: false, + icon:'', describe: 'Open or record a new trace', children: [ { @@ -1848,6 +1854,7 @@ export class SpApplication extends BaseElement { collapsed: false, title: 'Support', second: false, + icon:'', describe: 'Support', children: [ { diff --git a/ide/src/trace/component/SpHelp.ts b/ide/src/trace/component/SpHelp.ts index 4af9598ea..1ee902efa 100644 --- a/ide/src/trace/component/SpHelp.ts +++ b/ide/src/trace/component/SpHelp.ts @@ -55,6 +55,7 @@ export class SpHelp extends BaseElement { collapsed: false, title: 'QuickStart', second: false, + icon:'caret-down', describe: '', children: [ { @@ -62,6 +63,7 @@ export class SpHelp extends BaseElement { title: '抓取和导入', describe: '', second: true, + icon:'caret-down', children: [ { title: '设备端抓取trace说明', @@ -108,6 +110,7 @@ export class SpHelp extends BaseElement { collapsed: false, title: '内存', describe: '', + icon:'caret-down', second: true, children: [ { @@ -170,6 +173,7 @@ export class SpHelp extends BaseElement { title: 'Native栈', describe: '', second: true, + icon:'caret-down', children: [ { title: 'HiPerf的抓取和展示说明', @@ -191,6 +195,7 @@ export class SpHelp extends BaseElement { title: 'TS栈', describe: '', second: true, + icon:'caret-down', children: [ { title: 'Cpuprofiler抓取和展示说明', @@ -212,6 +217,7 @@ export class SpHelp extends BaseElement { title: '分析模板', describe: '', second: true, + icon:'caret-down', children: [ { title: 'Frame timeline抓取和展示说明', @@ -285,6 +291,7 @@ export class SpHelp extends BaseElement { title: '文件', describe: '', second: true, + icon:'caret-down', children: [ { title: 'FileSystem抓取和展示说明', @@ -319,6 +326,7 @@ export class SpHelp extends BaseElement { title: '其他', describe: '', second: true, + icon:'caret-down', children: [ { title: 'Sql分析和Metrics说明', @@ -449,6 +457,7 @@ export class SpHelp extends BaseElement { title: 'TraceStreamer', second: false, describe: '', + icon:'caret-down', children: [ { title: 'TraceStreamer数据库说明', @@ -524,6 +533,7 @@ export class SpHelp extends BaseElement { title: 'SmartPerf', second: false, describe: '', + icon:'caret-down', children: [ { title: 'SmartPerf 编译指导', diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index 248f13166..50dcaa253 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -50,7 +50,8 @@ import { FlagsConfig } from '../SpFlags'; import { SpLogChart } from './SpLogChart'; import { SpHiSysEventChart } from './SpHiSysEventChart'; import { SpAllAppStartupsChart } from './SpAllAppStartups'; -import {setVSyncData} from './VSync'; +import { setVSyncData } from './VSync'; +import { SpSegmentationChart } from './SpSegmentationChart'; export class SpChartManager { static APP_STARTUP_PID_ARR: Array = []; @@ -75,6 +76,7 @@ export class SpChartManager { public arkTsChart: SpArkTsChart; private logChart: SpLogChart; private spHiSysEvent: SpHiSysEventChart; + private spSegmentationChart: SpSegmentationChart; constructor(trace: SpSystemTrace) { this.trace = trace; @@ -97,6 +99,7 @@ export class SpChartManager { this.logChart = new SpLogChart(trace); this.spHiSysEvent = new SpHiSysEventChart(trace); this.spAllAppStartupsChart = new SpAllAppStartupsChart(trace); + this.spSegmentationChart = new SpSegmentationChart(trace); } async init(progress: Function) { @@ -141,6 +144,8 @@ export class SpChartManager { progress('Irq init', 84); await this.irqChart.init(); info('Cpu Freq Data initialized'); + progress('SpSegmentationChart inin', 84.5); + await this.spSegmentationChart.init(); await this.virtualMemChart.init(); progress('fps', 85); await this.fps.init(); diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index 439975f86..c0ee12942 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -209,6 +209,7 @@ export class SpHiPerf { perfCallCutRow.folder = false; perfCallCutRow.drawType = -2; perfCallCutRow.name = 'CallChart [cpu0]'; + perfCallCutRow.funcExpand = false; perfCallCutRow.setAttribute('children', ''); perfCallCutRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; perfCallCutRow.selectChangeHandler = this.trace.selectChangeHandler; @@ -228,7 +229,7 @@ export class SpHiPerf { `Name: ${callName}
Lib: - ${perfDataQuery.getLibName(hoverStruct!.fileId,hoverStruct!.symbolId)}
+ ${perfDataQuery.getLibName(hoverStruct!.fileId, hoverStruct!.symbolId)}
Self Time: ${Utils.getProbablyTime(selfDur || 0)}
Duration: @@ -274,16 +275,16 @@ export class SpHiPerf { row.rowSetting = 'enable'; row.rowSettingList = [ ...cpuData.reverse().map((it: any): { - key: string; - title: string; - checked?: boolean - } => { - return { - key: `${it.cpu_id}-c`, - checked: it.cpu_id === 0, - title: `cpu${it.cpu_id}`, - }; - } + key: string; + title: string; + checked?: boolean + } => { + return { + key: `${it.cpu_id}-c`, + checked: it.cpu_id === 0, + title: `cpu${it.cpu_id}`, + }; + } ), ...Array.from(pt.values()) ]; @@ -569,7 +570,7 @@ export class SpHiPerf { row.isComplete = false; } - resetAllChartData() : void { + resetAllChartData(): void { this.rowList?.forEach(row => this.resetChartData(row)); } diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 55a759360..f82449d83 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -44,6 +44,11 @@ let dragDirection: string = ''; @element('trace-row') export class TraceRow extends HTMLElement { + static ROW_TYPE_SPSEGNENTATION = 'spsegmentation'; + static ROW_TYPE_CPU_COMPUTILITY = 'cpu-computility'; + static ROW_TYPE_GPU_COMPUTILITY = 'gpu-computility'; + static ROW_TYPE_BINDER_COUNT = 'binder-count'; + static ROW_TYPE_SCHED_SWITCH = 'sched-switch'; static ROW_TYPE_CPU = 'cpu-data'; static ROW_TYPE_CPU_STATE = 'cpu-state'; static ROW_TYPE_CPU_FREQ = 'cpu-freq'; @@ -143,6 +148,7 @@ export class TraceRow extends HTMLElement { public collectEL: LitIcon | null | undefined; public onThreadHandler: ((useCache: boolean, buf: ArrayBuffer | undefined | null) => void) | undefined | null; public onRowSettingChangeHandler: ((keys: Array, nodes: Array) => void) | undefined | null; + public onRowCheckFileChangeHandler: ((file: string | ArrayBuffer | null) => void) | undefined | null; public supplier: (() => Promise>) | undefined | null; public favoriteChangeHandler: ((fav: TraceRow) => void) | undefined | null; public selectChangeHandler: ((traceRow: TraceRow) => void) | undefined | null; @@ -161,6 +167,8 @@ export class TraceRow extends HTMLElement { private nameEL: HTMLLabelElement | null | undefined; private rowSettingTree: LitTree | null | undefined; private rowSettingPop: LitPopover | null | undefined; + private fileEL: any; + private rowCheckFilePop: LitPopover | null | undefined; private _rangeSelect: boolean = false; private _drawType: number = 0; private folderIconEL: LitIcon | null | undefined; @@ -188,12 +196,12 @@ export class TraceRow extends HTMLElement { isOffScreen: boolean; skeleton?: boolean; } = { - canvasNumber: 1, - alpha: false, - contextId: '2d', - isOffScreen: true, - skeleton: false, - } + canvasNumber: 1, + alpha: false, + contextId: '2d', + isOffScreen: true, + skeleton: false, + } ) { super(); this.args = args; @@ -251,13 +259,13 @@ export class TraceRow extends HTMLElement { set funcExpand(b: boolean) { this.setAttribute('func-expand', b ? 'true' : 'false'); } - get sticky():boolean{ + get sticky(): boolean { return this.hasAttribute('sticky'); } - set sticky(fixed:boolean){ + set sticky(fixed: boolean) { if (fixed) { this.setAttribute('sticky', ''); - }else{ + } else { this.removeAttribute('sticky'); } } @@ -708,7 +716,7 @@ export class TraceRow extends HTMLElement { this.checkType = '-1'; } - addRowSettingPop(): void{ + addRowSettingPop(): void { this.rowSettingPop = document.createElement('lit-popover') as LitPopover; this.rowSettingPop.innerHTML = `
@@ -737,7 +745,39 @@ export class TraceRow extends HTMLElement { this.describeEl?.appendChild(this.rowSettingPop); } - getRowSettingKeys() : Array { + addRowCheckFilePop(): void { + this.rowCheckFilePop = document.createElement('litpopover') as LitPopover; + this.rowCheckFilePop.innerHTML = `
+
+ + `; + this.rowCheckFilePop.id = 'rowCheckFile'; + this.rowCheckFilePop.className = 'popover checkFile'; + this.rowCheckFilePop.setAttribute('trigger', 'click'); + this.rowCheckFilePop?.addEventListener('mouseenter', (e) => { + window.publish(window.SmartEvent.UI.HoverNull, undefined); + }); + this.fileEL = this.rowCheckFilePop.querySelector('#jsoninput'); + this.rowCheckFilePop.onclick = (): void => { + this.fileEL.click(); + this.fileEL.addEventListener('change', (e: any) => { + let file = e.target.files[0]; + if (file.type === 'application/json') { + let file_reader = new FileReader(); + file_reader.readAsText(file, 'UTF-8'); + file_reader.onload = () => { + let fc = file_reader.result; + this.onRowCheckFileChangeHandler?.(fc) + }; + } else { + return + } + }, false) + } + this.describeEl?.appendChild(this.rowCheckFilePop); + } + + getRowSettingKeys(): Array { if (this.rowSetting === 'enable') { return this.rowSettingTree!.getCheckdKeys(); } @@ -756,7 +796,7 @@ export class TraceRow extends HTMLElement { } } - enableCollapseChart() : void { + enableCollapseChart(): void { this._enableCollapseChart = true; this.nameEL!.onclick = () => { if (this.funcExpand) { @@ -1440,7 +1480,13 @@ export class TraceRow extends HTMLElement { } :host([row-setting='enable']:not([check-type='-1'])) .collect{ margin-right: 5px; - } + } + :host([row-setting='checkFile']) #rowCheckFile{ + display:flex; + } + :host([row-setting='checkFile']) #myfolder{ + color:#4b5766; + }
diff --git a/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/ide/src/trace/database/ui-worker/ProcedureWorker.ts index df8360f91..23504dd78 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorker.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorker.ts @@ -59,6 +59,8 @@ import { LogRender } from './ProcedureWorkerLog'; import { HiPerfCallChartRender } from './ProcedureWorkerHiPerfCallChart'; import { HiSysEventRender } from './ProcedureWorkerHiSysEvent'; import { AllAppStartupRender } from './ProcedureWorkerAllAppStartup'; +import { FreqExtendRender } from './ProcedureWorkerFreqExtend'; +import { BinderRender } from './procedureWorkerBinder'; let dataList: any = {}; let dataList2: any = {}; @@ -115,6 +117,8 @@ export let renders: any = { snapshot: new SnapshotRender(), logs: new LogRender(), hiSysEvent: new HiSysEventRender(), + 'freq-extend': new FreqExtendRender(), + 'binder' : new BinderRender(), }; function match(type: string, req: RequestMessage): void { diff --git a/ide/webpack.config.js b/ide/webpack.config.js index 38d6d8ad7..8ecc16731 100644 --- a/ide/webpack.config.js +++ b/ide/webpack.config.js @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - // Generated using webpack-cli https://github.com/webpack/webpack-cli const path = require('path'); @@ -26,16 +25,6 @@ const childProcess = require('child_process'); const { exec } = require('child_process'); const fs = require('fs'); - -function directoryExists(path) { - try { - fs.accessSync(path); - return true; - } catch (error) { - return false; - } -} - function runCommand(command) { return new Promise((resolve, reject) => { exec(command, (error, stdout, stderr) => { @@ -48,6 +37,42 @@ function runCommand(command) { }); } +function cpFile(sourcePath, targetPath) { + fs.readdir(sourcePath, (err, files) => { + if (err) { + console.error('无法读取目录', err); + return; + } + files.forEach((file) => { + const source = `${sourcePath}/${file}`; + const target = `${targetPath}/${file}`; + fs.copyFile(source, target, (err) => { + if (err) { + console.error('无法复制文件', err); + return; + } + }); + }); + }); +} + +function clearDirectory(directoryPath) { + const isDirectoryExists = fs.existsSync(directoryPath); + + if (!isDirectoryExists) { + fs.mkdirSync(directoryPath); + } else { + fs.readdirSync(directoryPath).forEach((file) => { + const filePath = path.join(directoryPath, file); + if (fs.lstatSync(filePath).isDirectory()) { + return; + } else { + fs.unlinkSync(filePath); // 删除文件 + } + }); + } +} + const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : 'style-loader'; //compile server ((flag) => { @@ -57,15 +82,9 @@ const stylesHandler = isProduction ? MiniCssExtractPlugin.loader : 'style-loader console.log('start compile server'); let outPath = path.normalize(path.join(__dirname, '/', 'dist')); let serverSrc = path.normalize(path.join(__dirname, '/server/main.go')); - if (!directoryExists(outPath)) { - runCommand(`mkdir ${outPath}`); - } else { - runCommand(`rm -rf ${outPath}/* `).then((result) => { - - }); - } - runCommand(`cp ./bin/* dist/`); - + let binPath = path.normalize(path.join(__dirname, '/', 'bin')); + clearDirectory(outPath); + cpFile(binPath, outPath); let rs; if (os.type() === 'Windows_NT') { rs = childProcess.spawnSync('go', ['build', '-o', outPath, serverSrc], { -- Gitee From fab1608c19d73ef8b224b372abaef73a3024ff38 Mon Sep 17 00:00:00 2001 From: liufei Date: Thu, 14 Dec 2023 18:27:13 +0800 Subject: [PATCH 2/5] =?UTF-8?q?helpdocument=E6=B7=BB=E5=8A=A0=E6=8A=98?= =?UTF-8?q?=E5=8F=A0=E6=A0=87=E5=BF=97=E5=B9=B6=E8=B0=83=E6=95=B4=E9=97=B4?= =?UTF-8?q?=E8=B7=9D=EF=BC=8Chiperf=20callchart=E9=BB=98=E8=AE=A4=E6=8A=98?= =?UTF-8?q?=E5=8F=A0=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=9B=9B=E6=9D=A1=E6=B3=B3?= =?UTF-8?q?=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liufei --- .../trace/component/chart/SpChartManager.ts | 6 +- .../component/chart/SpSegmentationChart.ts | 491 ++++++++++++++++++ .../ui-worker/ProcedureWorkerFreqExtend.ts | 117 +++++ .../ui-worker/procedureWorkerBinder.ts | 105 ++++ 4 files changed, 716 insertions(+), 3 deletions(-) create mode 100644 ide/src/trace/component/chart/SpSegmentationChart.ts create mode 100644 ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts create mode 100644 ide/src/trace/database/ui-worker/procedureWorkerBinder.ts diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index 50dcaa253..d1d824022 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -76,7 +76,7 @@ export class SpChartManager { public arkTsChart: SpArkTsChart; private logChart: SpLogChart; private spHiSysEvent: SpHiSysEventChart; - private spSegmentationChart: SpSegmentationChart; + private SpSegmentationChart: SpSegmentationChart; constructor(trace: SpSystemTrace) { this.trace = trace; @@ -99,7 +99,7 @@ export class SpChartManager { this.logChart = new SpLogChart(trace); this.spHiSysEvent = new SpHiSysEventChart(trace); this.spAllAppStartupsChart = new SpAllAppStartupsChart(trace); - this.spSegmentationChart = new SpSegmentationChart(trace); + this.SpSegmentationChart = new SpSegmentationChart(trace); } async init(progress: Function) { @@ -145,7 +145,7 @@ export class SpChartManager { await this.irqChart.init(); info('Cpu Freq Data initialized'); progress('SpSegmentationChart inin', 84.5); - await this.spSegmentationChart.init(); + await this.SpSegmentationChart.init(); await this.virtualMemChart.init(); progress('fps', 85); await this.fps.init(); diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts new file mode 100644 index 000000000..a3fd22397 --- /dev/null +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -0,0 +1,491 @@ +/* + * 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 { ColorUtils } from '../trace/base/ColorUtils'; +import { TraceRow } from '../trace/base/TraceRow'; +import { renders } from '../../database/ui-worker/ProcedureWorker'; +import { EmptyRender } from '../../database/ui-worker/ProcedureWorkerCPU'; +import { FreqExtendRender, CpuFreqExtendStruct } from '../../database/ui-worker/ProcedureWorkerFreqExtend'; +import { BinderRender, BinderStruct } from '../../database/ui-worker/procedureWorkerBinder'; +import { queryIrqList } from '../../database/SqlLite'; +import { BaseStruct } from '../../bean/BaseStruct'; + +export class SpSegmentationChart { + static trace: SpSystemTrace; + static jsonRow: TraceRow | undefined; + static GpuRow: TraceRow | undefined; + static binderRow: TraceRow | undefined; + static schedRow: TraceRow | undefined; + static freqInfoMapData = new Map>(); + private rowFolder!: TraceRow; + static chartData: Array = [];; + // 数据切割联动 + static setChartData(type: string, data: Array) { + let currentMaxValue: number = 0; + if (type === 'CPU-FREQ') { + setCpuData(data, currentMaxValue, type); + } + else if (type === 'GPU-FREQ') { + setGpuData(data, currentMaxValue, type) + } else { + setSchedData(data, currentMaxValue, type) + } + SpSegmentationChart.trace.refreshCanvas(true) + } + + // binder联动调用 + static setBinderChartData(type: string, data: Array>) { + BinderStruct.maxHeight = 0; + let binderList: Array = []; + let chartData: Array = []; + setBinderData(data, binderList); + chartData = binderList.map((v: BinderDataStruct) => { + return { + cpu: v.name === 'binder transaction' ? + 0 : v.name === 'binder transaction async' ? + 1 : v.name === 'binder reply' ? + 2 : 3, + startNS: v.startNS, + dur: v.dur, + name: `${v.name}`, + value: v.count, + depth: v.depth, + cycle: v.idx, + idx: v.idx, + count: v.count, + } + }) + SpSegmentationChart.binderRow!.dataList = []; + SpSegmentationChart.binderRow!.dataListCache = []; + SpSegmentationChart.binderRow!.isComplete = false; + SpSegmentationChart.binderRow!.style.height = `${BinderStruct.maxHeight > 2 ? BinderStruct.maxHeight * 20 + 20 : 40}px`; + // @ts-ignore + SpSegmentationChart.binderRow!.supplier = (): Promise> => + new Promise>((resolve) => resolve(chartData)); + } + + // 悬浮联动 + static tabHover(type: String, tableIsHover: boolean = false, cycle: number = -1) { + CpuFreqExtendStruct.isTabHover = tableIsHover; + if (type === 'CPU-FREQ' || type === 'GPU-FREQ' || type === 'SCHED-SWITCH') { + if (tableIsHover) { + SpSegmentationChart.jsonRow!.isHover = false; + SpSegmentationChart.GpuRow!.isHover = false; + CpuFreqExtendStruct.cycle = cycle; + } else { + CpuFreqExtendStruct.cycle = -1 + CpuFreqExtendStruct.hoverCpuFreqStruct = undefined; + } + } else if (type === 'BINDER') { + if (tableIsHover) { + BinderStruct.hoverCycle = cycle; + } else { + BinderStruct.hoverCycle = -1; + } + } + SpSegmentationChart.trace.refreshCanvas(true, 'flagChange') + } + + constructor(trace: SpSystemTrace) { + SpSegmentationChart.trace = trace; + } + + async init() { + let irqList = await queryIrqList(); + if (irqList.length == 0) { + return; + } + else { + await this.initFolder(); + await this.initCpuFreq(); + await this.initGpuTrace(); + await this.initSchedTrace(); + await this.initBinderTrace(); + } + } + + async initFolder() { + let row = TraceRow.skeleton(); + row.setAttribute('disabled-check', ''); + row.rowId = `unkown`; + row.index = 0; + row.rowType = TraceRow.ROW_TYPE_SPSEGNENTATION; + row.rowParentId = ''; + row.folder = true; + row.style.height = '40px'; + row.name = `Segmentation`; + row.supplier = () => new Promise>((resolve) => resolve([])); + row.onThreadHandler = (useCache) => { + row.canvasSave(SpSegmentationChart.trace.canvasPanelCtx!); + if (row.expansion) { + SpSegmentationChart.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); + } else { + (renders['empty'] as EmptyRender).renderMainThread( + { + context: SpSegmentationChart.trace.canvasPanelCtx, + useCache: useCache, + type: ``, + }, + row, + ); + } + row.canvasRestore(SpSegmentationChart.trace.canvasPanelCtx!); + }; + this.rowFolder = row; + SpSegmentationChart.trace.rowsEL?.appendChild(row); + + } + + async initCpuFreq() { + // json文件泳道 + SpSegmentationChart.jsonRow = TraceRow.skeleton(); + SpSegmentationChart.jsonRow.rowId = `json0`; + SpSegmentationChart.jsonRow.rowType = TraceRow.ROW_TYPE_CPU_COMPUTILITY; + SpSegmentationChart.jsonRow.rowParentId = ''; + SpSegmentationChart.jsonRow.style.height = '40px'; + SpSegmentationChart.jsonRow.name = `Cpu Computility`; + SpSegmentationChart.jsonRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; + SpSegmentationChart.jsonRow.addRowCheckFilePop(); + SpSegmentationChart.jsonRow.rowSetting = 'checkFile'; + // 拿到了用户传递的数据 + SpSegmentationChart.jsonRow.onRowCheckFileChangeHandler = (e: string | ArrayBuffer | null) => { + // @ts-ignore + let chartData = JSON.parse(e); + let mapData = new Map(); + // @ts-ignore + chartData.map((v) => { + for (let key in v.freqInfo) { + mapData.set(Number(key), Number(v.freqInfo[key])) + } + SpSegmentationChart.freqInfoMapData.set(v.cpuId, mapData) + mapData = new Map() + }) + } + SpSegmentationChart.jsonRow.focusHandler = (ev) => { + SpSegmentationChart.trace?.displayTip( + SpSegmentationChart.jsonRow!, + CpuFreqExtendStruct.hoverCpuFreqStruct, + `${CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value!}` + ); + }; + SpSegmentationChart.jsonRow.findHoverStruct = () => { + CpuFreqExtendStruct.hoverCpuFreqStruct = SpSegmentationChart.jsonRow!.getHoverStruct(); + }; + // @ts-ignore + SpSegmentationChart.jsonRow.supplier = (): Promise> => + new Promise>((resolve) => resolve([])); + SpSegmentationChart.jsonRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (SpSegmentationChart.jsonRow!.currentContext) { + context = SpSegmentationChart.jsonRow!.currentContext; + } else { + context = SpSegmentationChart.jsonRow!.collect ? SpSegmentationChart.trace.canvasFavoritePanelCtx! : SpSegmentationChart.trace.canvasPanelCtx!; + } + SpSegmentationChart.jsonRow!.canvasSave(context); + (renders['freq-extend'] as FreqExtendRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `json0`, + }, + SpSegmentationChart.jsonRow! + ); + SpSegmentationChart.jsonRow!.canvasRestore(context); + }; + SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.jsonRow); + this.rowFolder!.addChildTraceRow(SpSegmentationChart.jsonRow); + } + + async initGpuTrace() { + SpSegmentationChart.GpuRow = TraceRow.skeleton(); + SpSegmentationChart.GpuRow.rowId = `gpurow`; + SpSegmentationChart.GpuRow.rowType = TraceRow.ROW_TYPE_GPU_COMPUTILITY; + SpSegmentationChart.GpuRow.rowParentId = ''; + SpSegmentationChart.GpuRow.style.height = '40px'; + SpSegmentationChart.GpuRow.name = `Gpu Computility`; + SpSegmentationChart.GpuRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; + SpSegmentationChart.GpuRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; + // @ts-ignore + SpSegmentationChart.GpuRow.supplier = (): Promise> => + new Promise>((resolve) => resolve([])); + SpSegmentationChart.GpuRow.focusHandler = (ev) => { + SpSegmentationChart.trace?.displayTip( + SpSegmentationChart.GpuRow!, + CpuFreqExtendStruct.hoverCpuFreqStruct, + `${CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value!} Hz·ms` + ); + }; + SpSegmentationChart.GpuRow.findHoverStruct = () => { + CpuFreqExtendStruct.hoverCpuFreqStruct = SpSegmentationChart.GpuRow!.getHoverStruct(); + }; + SpSegmentationChart.GpuRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (SpSegmentationChart.GpuRow!.currentContext) { + context = SpSegmentationChart.GpuRow!.currentContext; + } else { + context = SpSegmentationChart.GpuRow!.collect ? SpSegmentationChart.trace.canvasFavoritePanelCtx! : SpSegmentationChart.trace.canvasPanelCtx!; + } + SpSegmentationChart.GpuRow!.canvasSave(context); + (renders['freq-extend'] as FreqExtendRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `json1`, + }, + SpSegmentationChart.GpuRow! + ); + SpSegmentationChart.GpuRow!.canvasRestore(context); + }; + SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.GpuRow); + this.rowFolder!.addChildTraceRow(SpSegmentationChart.GpuRow); + } + + async initSchedTrace() { + SpSegmentationChart.schedRow = TraceRow.skeleton(); + SpSegmentationChart.schedRow.rowId = `sched_switch Count`; + SpSegmentationChart.schedRow.rowType = TraceRow.ROW_TYPE_SCHED_SWITCH; + SpSegmentationChart.schedRow.rowParentId = ''; + SpSegmentationChart.schedRow.style.height = '40px'; + SpSegmentationChart.schedRow.name = `Sched_switch Count`; + SpSegmentationChart.schedRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; + SpSegmentationChart.schedRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; + SpSegmentationChart.schedRow.focusHandler = (ev) => { + SpSegmentationChart.trace?.displayTip( + SpSegmentationChart.schedRow!, + CpuFreqExtendStruct.hoverCpuFreqStruct, + `${ColorUtils.formatNumberComma(CpuFreqExtendStruct.hoverCpuFreqStruct?.value!)} Hz·ms` + ); + }; + SpSegmentationChart.schedRow.findHoverStruct = () => { + CpuFreqExtendStruct.hoverCpuFreqStruct = SpSegmentationChart.schedRow!.getHoverStruct(); + }; + // @ts-ignore + SpSegmentationChart.schedRow.supplier = (): Promise> => + new Promise>((resolve) => resolve([])); + SpSegmentationChart.schedRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (SpSegmentationChart.schedRow!.currentContext) { + context = SpSegmentationChart.schedRow!.currentContext; + } else { + context = SpSegmentationChart.schedRow!.collect ? SpSegmentationChart.trace.canvasFavoritePanelCtx! : SpSegmentationChart.trace.canvasPanelCtx!; + } + SpSegmentationChart.schedRow!.canvasSave(context); + (renders['freq-extend'] as FreqExtendRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `json0`, + }, + SpSegmentationChart.schedRow! + ); + SpSegmentationChart.schedRow!.canvasRestore(context); + }; + SpSegmentationChart.trace.rowsEL?.appendChild(SpSegmentationChart.schedRow); + this.rowFolder!.addChildTraceRow(SpSegmentationChart.schedRow); + } + + async initBinderTrace() { + SpSegmentationChart.binderRow = TraceRow.skeleton(); + SpSegmentationChart.binderRow.rowId = `binderrow`; + SpSegmentationChart.binderRow.rowType = TraceRow.ROW_TYPE_BINDER_COUNT; + SpSegmentationChart.binderRow.rowParentId = ''; + SpSegmentationChart.binderRow.name = `Binder Count`; + SpSegmentationChart.binderRow.style.height = '40px'; + SpSegmentationChart.binderRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; + SpSegmentationChart.binderRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; + SpSegmentationChart.binderRow.findHoverStruct = () => { + BinderStruct.hoverCpuFreqStruct = SpSegmentationChart.binderRow!.dataListCache.find((v: any) => { + 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) { + return v + } + } + }) + }; + SpSegmentationChart.binderRow.supplier = (): Promise> => + new Promise>((resolve) => resolve([])); + SpSegmentationChart.binderRow.onThreadHandler = (useCache) => { + let context: CanvasRenderingContext2D; + if (SpSegmentationChart.binderRow!.currentContext) { + context = SpSegmentationChart.binderRow!.currentContext; + } else { + context = SpSegmentationChart.binderRow!.collect ? SpSegmentationChart.trace.canvasFavoritePanelCtx! : SpSegmentationChart.trace.canvasPanelCtx!; + } + SpSegmentationChart.binderRow!.canvasSave(context); + (renders['binder'] as BinderRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `binder`, + }, + SpSegmentationChart.binderRow! + ); + SpSegmentationChart.binderRow!.canvasRestore(context); + }; + SpSegmentationChart.binderRow.focusHandler = (ev) => { + 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); + } + +} + +class FreqChartDataStruct { + cpu?: number = 0; + dur: number = 0; + value: number = 0; + startNS: number = 0; + cycle: number = 0; + freq?: number = 0; + type?: string = ''; + count?: number = 0; +} + +class BinderDataStruct { + name: string = ''; + count: number = 0; + dur: number = 0; + startNS: number = 0; + idx: number = -1; + depth?: number = 0; +} + +function setCpuData(data: Array, currentMaxValue: number, type: string) { + let chartData = data.map((v: FreqChartDataStruct) => { + if (v.value > currentMaxValue) { + currentMaxValue = v.value + } + return { + cpu: 0, + dur: v.dur, + value: v.value ? v.value : v.count ? v.count : 0, + startNS: v.startNS, + cycle: v.cycle, + type + } + }) + CpuFreqExtendStruct.maxValue = currentMaxValue; + SpSegmentationChart.jsonRow!.dataList = []; + SpSegmentationChart.jsonRow!.dataListCache = []; + SpSegmentationChart.jsonRow!.isComplete = false; + // @ts-ignore + SpSegmentationChart.jsonRow!.supplier = (): Promise> => + new Promise>((resolve) => resolve(chartData)); +} + +function setGpuData(data: Array, currentMaxValue: number, type: string) { + let chartData = data.map((v: FreqChartDataStruct) => { + let _count = Number(v.count) + if (_count > currentMaxValue) { + currentMaxValue = _count + } + return { + cpu: 7, + dur: v.dur ? Number(v.dur * 1000000) : 0, + value: Number(v.count), + startNS: Number(v.startNS), + cycle: Number(v.cycle), + type + } + }) + CpuFreqExtendStruct.maxValue = currentMaxValue; + SpSegmentationChart.GpuRow!.dataList = []; + SpSegmentationChart.GpuRow!.dataListCache = []; + SpSegmentationChart.GpuRow!.isComplete = false; + // @ts-ignore + SpSegmentationChart.GpuRow!.supplier = (): Promise> => + new Promise>((resolve) => resolve(chartData)); +} + +function setSchedData(data: Array, currentMaxValue: number, type: string) { + let chartData = data.map((v: any) => { + if (v.count > currentMaxValue) { + currentMaxValue = v.count + } + return { + cpu: 5, + dur: Number(v.duration) * 1000000, + value: v.count, + startNS: Number(v.cycleStartTime) * 1000000, + cycle: v.cycle, + type + } + }) + CpuFreqExtendStruct.maxValue = currentMaxValue; + SpSegmentationChart.schedRow!.dataList = []; + SpSegmentationChart.schedRow!.dataListCache = []; + SpSegmentationChart.schedRow!.isComplete = false; + SpSegmentationChart.schedRow!.supplier = (): Promise> => + new Promise>((resolve) => resolve(chartData)); +} + +function setBinderData(data: Array>, binderList: Array) { + data.map((v: Array) => { + let listCount = 0 + v.map((t: BinderDataStruct) => { + listCount += t.count; + if (t.name === 'binder transaction') { + t.depth = t.count; + } + if (t.name === 'binder transaction async') { + t.depth = t.count + ((v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction'; + }).length > 0) ? (v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction'; + })[0].count) : 0); + } + if (t.name === 'binder reply') { + t.depth = t.count + ((v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction'; + }).length > 0) ? (v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction'; + })[0].count) : 0) + ((v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction async'; + }).length > 0) ? (v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction async'; + })[0].count) : 0); + } + if (t.name === 'binder async rcv') { + t.depth = t.count + ((v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction'; + }).length > 0) ? (v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction'; + })[0].count) : 0) + ((v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction async'; + }).length > 0) ? (v.filter((i: BinderDataStruct) => { + return i.name === 'binder transaction async'; + })[0].count) : 0) + ((v.filter((i: BinderDataStruct) => { + return i.name === 'binder reply'; + }).length > 0) ? (v.filter((i: BinderDataStruct) => { + return i.name === 'binder reply'; + })[0].count) : 0); + } + binderList.push(t); + }); + BinderStruct.maxHeight = BinderStruct.maxHeight > listCount ? BinderStruct.maxHeight : JSON.parse(JSON.stringify(listCount)); + listCount = 0; + }) +} \ No newline at end of file diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts new file mode 100644 index 000000000..871fd6966 --- /dev/null +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts @@ -0,0 +1,117 @@ +/* + * 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 { ColorUtils } from '../../component/trace/base/ColorUtils'; +import { BaseStruct, dataFilterHandler, isFrameContainPoint, Render, RequestMessage } from './ProcedureWorkerCommon'; +import { TraceRow } from '../../component/trace/base/TraceRow'; + +export class FreqExtendRender extends Render { + renderMainThread( + freqReq: { + context: CanvasRenderingContext2D; + useCache: boolean; + type: string; + }, + row: TraceRow + ) { + let freqList = row.dataList; + let freqFilter = row.dataListCache; + dataFilterHandler(freqList, freqFilter, { + startKey: 'startNS', + durKey: 'dur', + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: freqReq.useCache || !(TraceRow.range?.refresh ?? false), + }); + + if (row.isHover) { + CpuFreqExtendStruct.cycle = -1; + CpuFreqExtendStruct.isTabHover = false; + } + freqReq.context.beginPath(); + for (let re of freqFilter) { + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + CpuFreqExtendStruct.hoverCpuFreqStruct = re; + } + if (!row.isHover && !CpuFreqExtendStruct.isTabHover) CpuFreqExtendStruct.hoverCpuFreqStruct = undefined; + CpuFreqExtendStruct.draw(freqReq.context, re); + } + freqReq.context.closePath(); + } +} + +export class CpuFreqExtendStruct extends BaseStruct { + static maxValue: number = 0; + static cycle: number = -1; + static isTabHover: boolean = false; + static hoverCpuFreqStruct: CpuFreqExtendStruct | undefined; + freq: number = 0; + static selectCpuFreqStruct: CpuFreqExtendStruct | undefined; + cpu: number | undefined; + value: number = 0; + startNS: number | undefined; + dur: number | undefined; //自补充,数据库没有返回 + cycle: number | undefined; + type: string | undefined; + count:number = 0; + + static draw(freqContext: CanvasRenderingContext2D, data: CpuFreqExtendStruct) { + if (data.frame) { + let width = data.frame.width || 0; + let index = data.cpu || 0; + index += 2; + let color = ColorUtils.colorForTid(index) + freqContext.fillStyle = color; + freqContext.strokeStyle = color; + if (data === CpuFreqExtendStruct.hoverCpuFreqStruct + || data === CpuFreqExtendStruct.selectCpuFreqStruct + || data === CpuFreqExtendStruct.selectCpuFreqStruct + || (data.cycle === CpuFreqExtendStruct.cycle + && CpuFreqExtendStruct.cycle !== -1)) { + freqContext.fillStyle = '#ff0000'; + freqContext.strokeStyle = '#ff0000'; + freqContext.lineWidth = 3; + freqContext.globalAlpha = 0.6; + if (data.type === 'SCHED-SWITCH' || data.type === 'GPU-FREQ') { + freqContext.globalAlpha = 1; + freqContext.fillStyle = color; + freqContext.strokeStyle = color; + } + let drawHeight: number = Math.floor( + ((data.value || 0) * (data.frame.height || 0) * 1.0) / CpuFreqExtendStruct.maxValue + ); + if (drawHeight < 1) { + drawHeight = 1; + } + freqContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); + freqContext.globalAlpha = 0.8; + freqContext.strokeRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); + } else { + freqContext.globalAlpha = 0.6; + freqContext.lineWidth = 1; + let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0)) / CpuFreqExtendStruct.maxValue); + if (drawHeight < 1) { + drawHeight = 1; + } + freqContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); + } + } + freqContext.globalAlpha = 1.0; + freqContext.lineWidth = 1; + } +} diff --git a/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts b/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts new file mode 100644 index 000000000..a36bda5e0 --- /dev/null +++ b/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts @@ -0,0 +1,105 @@ +/* + * 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 { ColorUtils } from '../../component/trace/base/ColorUtils'; +import { BaseStruct, dataFilterHandler, isFrameContainPoint, Render, RequestMessage } from './ProcedureWorkerCommon'; +import { TraceRow } from '../../component/trace/base/TraceRow'; +import { drawString, Rect } from './ProcedureWorkerCommon'; + +export class BinderRender extends Render { + renderMainThread( + freqReq: { + context: CanvasRenderingContext2D; + useCache: boolean; + type: string; + }, + row: TraceRow + ) { + let freqList = row.dataList; + let freqFilter = row.dataListCache; + dataFilterHandler(freqList, freqFilter, { + startKey: 'startNS', + durKey: 'dur', + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 5, + useCache: freqReq.useCache || !(TraceRow.range?.refresh ?? false), + }); + freqReq.context.beginPath(); + for (let re of freqFilter) { + if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { + BinderStruct.hoverCpuFreqStruct = re; + } + if (!row.isHover) { + BinderStruct.hoverCpuFreqStruct = undefined; + } + BinderStruct.draw(freqReq.context, re); + } + freqReq.context.closePath(); + } +} +export class BinderStruct extends BaseStruct { + static hoverCpuFreqStruct: BinderStruct | undefined; + static selectCpuFreqStruct: BinderStruct | undefined; + static maxHeight: number = 0; + static hoverCycle: number = -1; + cpu: number | undefined; + value: number = 0; + cycle: number = 0; + startNS: number | undefined; + dur: number | undefined; //自补充,数据库没有返回 + name: string | undefined; + depth: number = 0; + static draw(freqContext: CanvasRenderingContext2D, data: BinderStruct) { + if (data.frame) { + let index = data.cpu || 0; + let color = ''; + if (data.name === 'binder transaction') { + color = '#e86b6a'; + } + if (data.name === 'binder transaction async') { + color = '#36baa4'; + } + if (data.name === 'binder reply') { + color = '#8770d3'; + } + if (data.name === 'binder async rcv') { + color = '#0cbdd4'; + } + freqContext.fillStyle = color + if (data === BinderStruct.hoverCpuFreqStruct || data === BinderStruct.selectCpuFreqStruct || data.cycle === BinderStruct.hoverCycle) { + freqContext.globalAlpha = 1; + freqContext.lineWidth = 1; + freqContext.fillRect(data.frame.x, BinderStruct.maxHeight * 20 - data.depth * 20 + 20, data.frame.width, data.value * 20); + } else { + freqContext.globalAlpha = 0.6; + freqContext.lineWidth = 1; + freqContext.fillRect(data.frame.x, BinderStruct.maxHeight * 20 - data.depth * 20 + 20, data.frame.width, data.value * 20); + } + if (data.frame.width > 8) { + freqContext.lineWidth = 1; + freqContext.fillStyle = ColorUtils.funcTextColor( + ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', 0, ColorUtils.FUNC_COLOR.length)] + ); + freqContext.textBaseline = 'middle'; + drawString(freqContext, `${data.name || ''}`, 6, new Rect(data.frame.x, BinderStruct.maxHeight * 20 - data.depth * 20 + 20, data.frame.width, data.value * 20), data); + } + freqContext.globalAlpha = 1.0; + freqContext.lineWidth = 1; + } + } +} \ No newline at end of file -- Gitee From e7793feaf686932841da04063c80c7b9e2643391 Mon Sep 17 00:00:00 2001 From: liufei Date: Thu, 14 Dec 2023 18:50:54 +0800 Subject: [PATCH 3/5] =?UTF-8?q?helpdocument=E6=8A=98=E5=8F=A0=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=EF=BC=8Chiperfcallchart=E9=BB=98=E8=AE=A4=E6=94=B6?= =?UTF-8?q?=E8=B5=B7=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=9B=9B=E6=9D=A1=E6=B3=B3?= =?UTF-8?q?=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liufei --- ide/src/trace/component/chart/SpSegmentationChart.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index a3fd22397..c2baf08f7 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -33,7 +33,7 @@ export class SpSegmentationChart { private rowFolder!: TraceRow; static chartData: Array = [];; // 数据切割联动 - static setChartData(type: string, data: Array) { + static setChartData(type: string, data: Array): void { let currentMaxValue: number = 0; if (type === 'CPU-FREQ') { setCpuData(data, currentMaxValue, type); @@ -47,7 +47,7 @@ export class SpSegmentationChart { } // binder联动调用 - static setBinderChartData(type: string, data: Array>) { + static setBinderChartData(type: string, data: Array>): void { BinderStruct.maxHeight = 0; let binderList: Array = []; let chartData: Array = []; @@ -78,7 +78,7 @@ export class SpSegmentationChart { } // 悬浮联动 - static tabHover(type: String, tableIsHover: boolean = false, cycle: number = -1) { + 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 (tableIsHover) { @@ -396,7 +396,7 @@ function setCpuData(data: Array, currentMaxValue: number, t new Promise>((resolve) => resolve(chartData)); } -function setGpuData(data: Array, currentMaxValue: number, type: string) { +function setGpuData(data: Array, currentMaxValue: number, type: string): void { let chartData = data.map((v: FreqChartDataStruct) => { let _count = Number(v.count) if (_count > currentMaxValue) { @@ -420,7 +420,7 @@ function setGpuData(data: Array, currentMaxValue: number, t new Promise>((resolve) => resolve(chartData)); } -function setSchedData(data: Array, currentMaxValue: number, type: string) { +function setSchedData(data: Array, currentMaxValue: number, type: string): void { let chartData = data.map((v: any) => { if (v.count > currentMaxValue) { currentMaxValue = v.count @@ -442,7 +442,7 @@ function setSchedData(data: Array, currentMaxValue: number, new Promise>((resolve) => resolve(chartData)); } -function setBinderData(data: Array>, binderList: Array) { +function setBinderData(data: Array>, binderList: Array): void { data.map((v: Array) => { let listCount = 0 v.map((t: BinderDataStruct) => { -- Gitee From 9253817c73e81e07940a092940ddc1906410c356 Mon Sep 17 00:00:00 2001 From: liufei Date: Fri, 15 Dec 2023 09:37:21 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liufei --- .../trace/component/chart/SpSegmentationChart.ts | 14 +++++++------- .../database/ui-worker/procedureWorkerBinder.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index c2baf08f7..13aee0ba5 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -225,7 +225,7 @@ export class SpSegmentationChart { SpSegmentationChart.trace?.displayTip( SpSegmentationChart.GpuRow!, CpuFreqExtendStruct.hoverCpuFreqStruct, - `${CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value!} Hz·ms` + `${CpuFreqExtendStruct.hoverCpuFreqStruct === undefined ? 0 : CpuFreqExtendStruct.hoverCpuFreqStruct.value!}` ); }; SpSegmentationChart.GpuRow.findHoverStruct = () => { @@ -266,7 +266,7 @@ export class SpSegmentationChart { SpSegmentationChart.trace?.displayTip( SpSegmentationChart.schedRow!, CpuFreqExtendStruct.hoverCpuFreqStruct, - `${ColorUtils.formatNumberComma(CpuFreqExtendStruct.hoverCpuFreqStruct?.value!)} Hz·ms` + `${CpuFreqExtendStruct.hoverCpuFreqStruct?.value!}` ); }; SpSegmentationChart.schedRow.findHoverStruct = () => { @@ -313,7 +313,7 @@ export class SpSegmentationChart { && 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) { - return v + return v; } } }) @@ -376,7 +376,7 @@ class BinderDataStruct { function setCpuData(data: Array, currentMaxValue: number, type: string) { let chartData = data.map((v: FreqChartDataStruct) => { if (v.value > currentMaxValue) { - currentMaxValue = v.value + currentMaxValue = v.value; } return { cpu: 0, @@ -400,7 +400,7 @@ function setGpuData(data: Array, currentMaxValue: number, t let chartData = data.map((v: FreqChartDataStruct) => { let _count = Number(v.count) if (_count > currentMaxValue) { - currentMaxValue = _count + currentMaxValue = _count; } return { cpu: 7, @@ -423,7 +423,7 @@ function setGpuData(data: Array, currentMaxValue: number, t function setSchedData(data: Array, currentMaxValue: number, type: string): void { let chartData = data.map((v: any) => { if (v.count > currentMaxValue) { - currentMaxValue = v.count + currentMaxValue = v.count; } return { cpu: 5, @@ -444,7 +444,7 @@ function setSchedData(data: Array, currentMaxValue: number, function setBinderData(data: Array>, binderList: Array): void { data.map((v: Array) => { - let listCount = 0 + let listCount = 0; v.map((t: BinderDataStruct) => { listCount += t.count; if (t.name === 'binder transaction') { diff --git a/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts b/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts index a36bda5e0..8996d8ead 100644 --- a/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts +++ b/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts @@ -80,7 +80,7 @@ export class BinderStruct extends BaseStruct { if (data.name === 'binder async rcv') { color = '#0cbdd4'; } - freqContext.fillStyle = color + freqContext.fillStyle = color; if (data === BinderStruct.hoverCpuFreqStruct || data === BinderStruct.selectCpuFreqStruct || data.cycle === BinderStruct.hoverCycle) { freqContext.globalAlpha = 1; freqContext.lineWidth = 1; -- Gitee From 6d4e9be3b465967018d6d85dc2e4778545bb442b Mon Sep 17 00:00:00 2001 From: liufei Date: Fri, 15 Dec 2023 14:21:41 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=86=8D=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: liufei --- .../trace/component/chart/SpSegmentationChart.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index 13aee0ba5..96266e967 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -307,10 +307,10 @@ export class SpSegmentationChart { SpSegmentationChart.binderRow.favoriteChangeHandler = SpSegmentationChart.trace.favoriteChangeHandler; SpSegmentationChart.binderRow.selectChangeHandler = SpSegmentationChart.trace.selectChangeHandler; SpSegmentationChart.binderRow.findHoverStruct = () => { - BinderStruct.hoverCpuFreqStruct = SpSegmentationChart.binderRow!.dataListCache.find((v: any) => { + 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 + 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) { return v; @@ -356,12 +356,14 @@ export class SpSegmentationChart { class FreqChartDataStruct { cpu?: number = 0; dur: number = 0; + duration?: number = 0; value: number = 0; startNS: number = 0; cycle: number = 0; freq?: number = 0; type?: string = ''; count?: number = 0; + cycleStartTime?: number = 0; } class BinderDataStruct { @@ -420,9 +422,9 @@ function setGpuData(data: Array, currentMaxValue: number, t new Promise>((resolve) => resolve(chartData)); } -function setSchedData(data: Array, currentMaxValue: number, type: string): void { - let chartData = data.map((v: any) => { - if (v.count > currentMaxValue) { +function setSchedData(data: Array, currentMaxValue: number | undefined, type: string): void { + let chartData = data.map((v: FreqChartDataStruct) => { + if (v.count && v.count > currentMaxValue!) { currentMaxValue = v.count; } return { -- Gitee