diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts
index 0c2de71201103dcad3a65ae57316a0621893f4cd..512d7216c2859a3d583a6c126f4462f8f4add97b 100644
--- a/ide/src/trace/SpApplication.ts
+++ b/ide/src/trace/SpApplication.ts
@@ -1521,12 +1521,12 @@ export class SpApplication extends BaseElement {
},
},
{
- title: 'Keyboard shortcuts',
+ title: 'Keyboard Shortcuts',
icon: 'smart-help',
clickHandler: function (item: MenuItem) {
SpStatisticsHttpUtil.addOrdinaryVisitAction({
- event: 'Keyboard shortcuts',
- action: 'Keyboard shortcuts',
+ event: 'Keyboard Shortcuts',
+ action: 'Keyboard Shortcuts',
});
that.search = false;
showContent(SpKeyboard);
@@ -1981,14 +1981,14 @@ export class SpApplication extends BaseElement {
},
},
{
- title: 'Keyboard shortcuts',
+ title: 'Keyboard Shortcuts',
icon: 'smart-help',
clickHandler: function (item: MenuItem) {
that.search = false;
showContent(SpKeyboard);
SpStatisticsHttpUtil.addOrdinaryVisitAction({
- event: 'Keyboard shortcuts',
- action: 'Keyboard shortcuts',
+ event: 'Keyboard Shortcuts',
+ action: 'Keyboard Shortcuts',
});
},
},
diff --git a/ide/src/trace/bean/SearchFuncBean.ts b/ide/src/trace/bean/SearchFuncBean.ts
index 40bfb5baa53801a350efbc909a3b773a0031dc1f..365608b974352babc83661cfbc4353f57a011c35 100644
--- a/ide/src/trace/bean/SearchFuncBean.ts
+++ b/ide/src/trace/bean/SearchFuncBean.ts
@@ -21,6 +21,7 @@ export class SearchFuncBean {
startTime: number | undefined; // 9729867000
tid: number | undefined; //
pid: number | undefined; // 2785
+ endTime: number | undefined; // 9729867000
type: string | undefined;
}
diff --git a/ide/src/trace/component/SpKeyboard.ts b/ide/src/trace/component/SpKeyboard.ts
index dac46503215fc83a53861e3362e26e83d611f3a7..f939b8e47223d322a4d9f37c13a5656f04e015a6 100644
--- a/ide/src/trace/component/SpKeyboard.ts
+++ b/ide/src/trace/component/SpKeyboard.ts
@@ -43,7 +43,7 @@ export class SpKeyboard extends BaseElement {
- SmartPerf help
+ SmartPerf Help
✕
@@ -172,7 +172,7 @@ export class SpKeyboard extends BaseElement {
.body{
width: 50%;
background-color: #fff;
- padding: 30px;
+ padding: 0 30px 30px;
z-index: 9000;
max-height: 600px;
overflow-y: scroll;
@@ -182,10 +182,11 @@ export class SpKeyboard extends BaseElement {
position:absolute;
}
header {
- position: relative;
- width: 100%;
- height: 31px;
- line-height: 31px;
+ position: fixed;
+ width: 50%;
+ height: 50px;
+ line-height: 50px;
+ background-color: #fff;
}
.close-icon{
cursor: pointer;
diff --git a/ide/src/trace/component/SpRecordTrace.ts b/ide/src/trace/component/SpRecordTrace.ts
index f1b3d6a4ea5193d6051a57e2cb3f67c201a9492d..6613671509ba4780c60952a67ea50badfcd6ec19 100644
--- a/ide/src/trace/component/SpRecordTrace.ts
+++ b/ide/src/trace/component/SpRecordTrace.ts
@@ -837,9 +837,12 @@ export class SpRecordTrace extends BaseElement {
SpRecordTrace.supportVersions.forEach((supportVersion) => {
let option = document.createElement('option');
option.className = 'select';
+ option.selected = supportVersion === '4.0+'? true:false;
option.textContent = `OpenHarmony-${supportVersion}`;
option.setAttribute('device-version', supportVersion);
this.deviceVersion!.append(option);
+ SpRecordTrace.selectVersion = '4.0+'
+ this.nativeMemoryHideBySelectVersion();
});
}
diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts
index eeef49272035fbe8f43387d936d41cdb66b167e4..2e8751161688c6daedc54c439199cba62b039433 100644
--- a/ide/src/trace/component/SpSystemTrace.ts
+++ b/ide/src/trace/component/SpSystemTrace.ts
@@ -109,6 +109,8 @@ import { type HiSysEventStruct } from '../database/ui-worker/ProcedureWorkerHiSy
import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon';
import { type SpKeyboard } from '../component/SpKeyboard';
import { drawVSync, enableVSync, resetVSync } from './chart/VSync';
+import { LtpoStruct } from '../database/ui-worker/ProcedureWorkerLTPO';
+import { HitchTimeStruct } from '../database/ui-worker/ProcedureWorkerHitchTime'
function dpr() {
return window.devicePixelRatio || 1;
@@ -2081,6 +2083,12 @@ export class SpSystemTrace extends BaseElement {
(AppStartupStruct.selectStartupStruct.startTs || 0) + (AppStartupStruct.selectStartupStruct.dur || 0),
shiftKey
);
+ }else if (AllAppStartupStruct.selectStartupStruct) {
+ this.slicestime = this.timerShaftEL?.setSlicesMark(
+ AllAppStartupStruct.selectStartupStruct.startTs || 0,
+ (AllAppStartupStruct.selectStartupStruct.startTs || 0) + (AllAppStartupStruct.selectStartupStruct.dur || 0),
+ shiftKey
+ );
} else if (SoStruct.selectSoStruct) {
this.slicestime = this.timerShaftEL?.setSlicesMark(
SoStruct.selectSoStruct.startTs || 0,
@@ -2479,6 +2487,9 @@ export class SpSystemTrace extends BaseElement {
JsCpuProfilerStruct.selectJsCpuProfilerStruct = undefined;
SnapshotStruct.selectSnapshotStruct = undefined;
HiPerfCallChartStruct.selectStruct = undefined;
+ AllAppStartupStruct.selectStartupStruct = undefined;
+ LtpoStruct.selectLtpoStruct = undefined;
+ HitchTimeStruct.selectHitchTimeStruct = undefined;
}
isWASDKeyPress() {
diff --git a/ide/src/trace/component/chart/SpAllAppStartups.ts b/ide/src/trace/component/chart/SpAllAppStartups.ts
index 0046a27e09fe3a7ea5030489bf8f3fb14995fb0f..60141f681779804d84b189f35be11072ca9b527c 100644
--- a/ide/src/trace/component/chart/SpAllAppStartups.ts
+++ b/ide/src/trace/component/chart/SpAllAppStartups.ts
@@ -17,117 +17,121 @@ import { SpSystemTrace } from '../SpSystemTrace';
import { TraceRow } from '../trace/base/TraceRow';
import { renders } from '../../database/ui-worker/ProcedureWorker';
import { CpuFreqStruct } from '../../database/ui-worker/ProcedureWorkerFreq';
-import { queryAppStartupProcessIds, queryProcessStartup, querySingleAppStartupsName } from '../../database/SqlLite';
+import {
+ queryAppStartupProcessIds,
+ queryProcessStartup,
+ querySingleAppStartupsName,
+} from '../../database/SqlLite';
import { FlagsConfig } from '../SpFlags';
import { AllAppStartupStruct, AllAppStartupRender } from '../../database/ui-worker/ProcedureWorkerAllAppStartup';
export class SpAllAppStartupsChart {
- private readonly trace: SpSystemTrace | undefined;
- static APP_STARTUP_PID_ARR: Array = [];
- static jsonRow: TraceRow | undefined;
- static trace: SpSystemTrace;
- static AllAppStartupsNameArr: any[] = [];
- static allAppStartupsAva: number[] = [];
+ private readonly trace: SpSystemTrace | undefined;
+ static APP_STARTUP_PID_ARR: Array = [];
+ static jsonRow: TraceRow | undefined;
+ static trace: SpSystemTrace;
+ static AllAppStartupsNameArr: any[] = [];
+ static allAppStartupsAva: number[] = [];
- constructor(trace: SpSystemTrace) {
- SpAllAppStartupsChart.trace = trace;
- }
-
- async init() {
- SpAllAppStartupsChart.APP_STARTUP_PID_ARR = [];
- let appStartUpPids = await queryAppStartupProcessIds();
- appStartUpPids.forEach((it) => SpAllAppStartupsChart.APP_STARTUP_PID_ARR.push(it.pid));
- SpAllAppStartupsChart.AllAppStartupsNameArr = [];
- SpAllAppStartupsChart.allAppStartupsAva = [];
- for (let i = 0; i < SpAllAppStartupsChart.APP_STARTUP_PID_ARR.length; i++) {
- let tmpSingleApp: any[] = await queryProcessStartup(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!);
- if (tmpSingleApp.length == 8) {
- let avilSingleName = await querySingleAppStartupsName(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!);
- SpAllAppStartupsChart.allAppStartupsAva.push(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]);
- SpAllAppStartupsChart.AllAppStartupsNameArr.push(avilSingleName![0].name);
- }
+ constructor(trace: SpSystemTrace) {
+ SpAllAppStartupsChart.trace = trace;
}
- let loadAppStartup: boolean = FlagsConfig.getFlagsConfigEnableStatus('AppStartup');
- if (loadAppStartup && SpAllAppStartupsChart.allAppStartupsAva.length) await this.initFolder();
- }
-
- async initFolder() {
- let row: TraceRow = TraceRow.skeleton();
- row.setAttribute('hasStartup', 'true');
- row.rowId = `all-app-start-${SpAllAppStartupsChart.APP_STARTUP_PID_ARR![0]}`;
- row.index = 0;
- row.rowType = TraceRow.ROW_TYPE_ALL_APPSTARTUPS;
- row.rowParentId = '';
- row.folder = false;
- row.style.height = '40px';
- row.name = `All App Startups`;
- row.selectChangeHandler = SpAllAppStartupsChart.trace.selectChangeHandler;
- row.favoriteChangeHandler = SpAllAppStartupsChart.trace.favoriteChangeHandler;
- row.supplier = async (): Promise> => {
- let sendRes: AllAppStartupStruct[] | PromiseLike = [];
- for (let i = 0; i < SpAllAppStartupsChart.allAppStartupsAva.length; i++) {
- let tmpResArr = await queryProcessStartup(SpAllAppStartupsChart.allAppStartupsAva[i]);
- let maxStartTs: number | undefined = tmpResArr[0].startTs;
- let minStartTs: number | undefined = tmpResArr[0].startTs;
- let singleDur = tmpResArr[0].dur;
- let endTs: number | undefined = tmpResArr[0].startTs;
- if (tmpResArr.length > 1) {
- for (let j = 0; j < tmpResArr.length; j++) {
- if (Number(tmpResArr[j].startTs) > Number(maxStartTs)) {
- maxStartTs = tmpResArr[j].startTs;
- } else if (Number(tmpResArr[j].startTs) < Number(minStartTs)) {
- minStartTs = tmpResArr[j].startTs;
+ async init() {
+ SpAllAppStartupsChart.APP_STARTUP_PID_ARR = [];
+ let appStartUpPids = await queryAppStartupProcessIds();
+ appStartUpPids.forEach((it) => SpAllAppStartupsChart.APP_STARTUP_PID_ARR.push(it.pid));
+ SpAllAppStartupsChart.AllAppStartupsNameArr = [];
+ SpAllAppStartupsChart.allAppStartupsAva = [];
+ for (let i = 0; i < SpAllAppStartupsChart.APP_STARTUP_PID_ARR.length; i++) {
+ let tmpSingleApp: any[] = await queryProcessStartup(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!);
+ if (tmpSingleApp.length === 8) {
+ let avilSingleName = await querySingleAppStartupsName(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!);
+ SpAllAppStartupsChart.allAppStartupsAva.push(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]);
+ SpAllAppStartupsChart.AllAppStartupsNameArr.push(avilSingleName![0].name);
}
- }
- tmpResArr.forEach((item) => {
- if (item.startTs == maxStartTs) {
- endTs = Number(item.startTs) + Number(item.dur);
- singleDur = Number(endTs) - Number(minStartTs);
+ }
+ let loadAppStartup: boolean = FlagsConfig.getFlagsConfigEnableStatus('AppStartup');
+ if (loadAppStartup && SpAllAppStartupsChart.allAppStartupsAva.length) await this.initFolder();
+ }
+
+ async initFolder() {
+ let row: TraceRow = TraceRow.skeleton();
+ row.setAttribute('hasStartup', 'true');
+ row.rowId = `all-app-start-${SpAllAppStartupsChart.APP_STARTUP_PID_ARR![0]}`;
+ row.index = 0;
+ row.rowType = TraceRow.ROW_TYPE_ALL_APPSTARTUPS;
+ row.rowParentId = '';
+ row.folder = false;
+ row.style.height = '40px';
+ row.name = `All App Startups`;
+ row.addTemplateTypes('AppStartup');
+ row.selectChangeHandler = SpAllAppStartupsChart.trace.selectChangeHandler;
+ row.favoriteChangeHandler = SpAllAppStartupsChart.trace.favoriteChangeHandler;
+ row.supplier = async (): Promise> => {
+ let sendRes: AllAppStartupStruct[] | PromiseLike = [];
+ for (let i = 0; i < SpAllAppStartupsChart.allAppStartupsAva.length; i++) {
+ let tmpResArr = await queryProcessStartup(SpAllAppStartupsChart.allAppStartupsAva[i]);
+ let maxStartTs: number | undefined = tmpResArr[0].startTs;
+ let minStartTs: number | undefined = tmpResArr[0].startTs;
+ let singleDur = tmpResArr[0].dur;
+ let endTs: number | undefined = tmpResArr[0].startTs;
+ if (tmpResArr.length > 1) {
+ for (let j = 0; j < tmpResArr.length; j++) {
+ if (Number(tmpResArr[j].startTs) > Number(maxStartTs)) {
+ maxStartTs = tmpResArr[j].startTs;
+ } else if (Number(tmpResArr[j].startTs) < Number(minStartTs)) {
+ minStartTs = tmpResArr[j].startTs;
+ }
+ }
+ tmpResArr.forEach((item) => {
+ if (item.startTs === maxStartTs) {
+ endTs = Number(item.startTs) + Number(item.dur);
+ singleDur = Number(endTs) - Number(minStartTs);
+ }
+ })
+ } else if (tmpResArr.length === 1) {
+ minStartTs = tmpResArr[0].startTs;
+ singleDur = tmpResArr[0].dur;
+ }
+ sendRes.push(
+ {
+ dur: singleDur,
+ value: undefined,
+ startTs: minStartTs,
+ pid: SpAllAppStartupsChart.allAppStartupsAva[i],
+ process: undefined,
+ itid: undefined,
+ endItid: undefined,
+ tid: SpAllAppStartupsChart.allAppStartupsAva[i],
+ startName: undefined,
+ stepName: SpAllAppStartupsChart.AllAppStartupsNameArr[i],
+ translateY: undefined,
+ frame: undefined,
+ isHover: false
+ }
+ )
}
- });
- } else if (tmpResArr.length === 1) {
- minStartTs = tmpResArr[0].startTs;
- singleDur = tmpResArr[0].dur;
+ return sendRes
}
- sendRes.push({
- dur: singleDur,
- value: undefined,
- startTs: minStartTs,
- pid: SpAllAppStartupsChart.allAppStartupsAva[i],
- process: undefined,
- itid: undefined,
- endItid: undefined,
- tid: SpAllAppStartupsChart.allAppStartupsAva[i],
- startName: undefined,
- stepName: SpAllAppStartupsChart.AllAppStartupsNameArr[i],
- translateY: undefined,
- frame: undefined,
- isHover: false,
- });
- }
- return sendRes;
- };
- row.onThreadHandler = (useCache): void => {
- let context: CanvasRenderingContext2D;
- if (row.currentContext) {
- context = row.currentContext;
- } else {
- context = row.collect
- ? SpAllAppStartupsChart.trace.canvasFavoritePanelCtx!
- : SpAllAppStartupsChart.trace.canvasPanelCtx!;
- }
- row.canvasSave(context);
- (renders['all-app-start-up'] as AllAppStartupRender).renderMainThread(
- {
- appStartupContext: context,
- useCache: useCache,
- type: `app-startup ${row.rowId}`,
- },
- row
- );
- row.canvasRestore(context);
- };
- SpAllAppStartupsChart.trace.rowsEL?.appendChild(row);
- }
-}
+ row.onThreadHandler = (useCache): void => {
+ let context: CanvasRenderingContext2D;
+ if (row.currentContext) {
+ context = row.currentContext;
+ } else {
+ context = row.collect ? SpAllAppStartupsChart.trace.canvasFavoritePanelCtx! : SpAllAppStartupsChart.trace.canvasPanelCtx!;
+ }
+ row.canvasSave(context);
+ (renders['all-app-start-up'] as AllAppStartupRender).renderMainThread(
+ {
+ appStartupContext: context,
+ useCache: useCache,
+ type: `app-startup ${row.rowId}`,
+ },
+ row
+ );
+ row.canvasRestore(context);
+ };
+ SpAllAppStartupsChart.trace.rowsEL?.appendChild(row);
+ }
+}
\ No newline at end of file
diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts
index 480f6d8867d8495390f78a50b57d7259fef86a12..da7713477aaff6a087a31559920f89cf18bf2a90 100644
--- a/ide/src/trace/component/chart/SpChartManager.ts
+++ b/ide/src/trace/component/chart/SpChartManager.ts
@@ -51,6 +51,7 @@ import { SpLogChart } from './SpLogChart';
import { SpHiSysEventChart } from './SpHiSysEventChart';
import { SpAllAppStartupsChart } from './SpAllAppStartups';
import { SpSegmentationChart } from './SpSegmentationChart';
+import { SpLtpoChart } from './SpLTPO';
export class SpChartManager {
static APP_STARTUP_PID_ARR: Array = [];
@@ -71,6 +72,7 @@ export class SpChartManager {
private clockChart: SpClockChart;
private irqChart: SpIrqChart;
private spAllAppStartupsChart!: SpAllAppStartupsChart;
+ private SpLtpoChart!: SpLtpoChart;
frameTimeChart: SpFrameTimeChart;
public arkTsChart: SpArkTsChart;
private logChart: SpLogChart;
@@ -98,6 +100,7 @@ export class SpChartManager {
this.logChart = new SpLogChart(trace);
this.spHiSysEvent = new SpHiSysEventChart(trace);
this.spAllAppStartupsChart = new SpAllAppStartupsChart(trace);
+ this.SpLtpoChart = new SpLtpoChart(trace)
this.spSegmentationChart = new SpSegmentationChart(trace);
}
@@ -173,9 +176,10 @@ export class SpChartManager {
progress('ark ts', 90);
await this.arkTsChart.initFolder();
info('initData ark ts initialized');
+ await this.spAllAppStartupsChart.init();
+ await this.SpLtpoChart.init();
await this.frameTimeChart.init();
info('initData frameTimeLine initialized');
- await this.spAllAppStartupsChart.init();
progress('process', 92);
await this.process.initAsyncFuncData();
await this.process.initDeliverInputEvent();
diff --git a/ide/src/trace/component/chart/SpLTPO.ts b/ide/src/trace/component/chart/SpLTPO.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dbe7c6bfa16a06a1e2d8050929affab808a53c52
--- /dev/null
+++ b/ide/src/trace/component/chart/SpLTPO.ts
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.翻译
+ */
+
+import { SpSystemTrace } from '../SpSystemTrace';
+import { TraceRow } from '../trace/base/TraceRow';
+import { renders } from '../../database/ui-worker/ProcedureWorker';
+import { CpuFreqStruct } from '../../database/ui-worker/ProcedureWorkerFreq';
+import {
+ queryPresentInfo,
+ queryFanceNameList,
+ queryFpsNameList
+} from '../../database/SqlLite';
+import { LtpoRender, LtpoStruct } from '../../database/ui-worker/ProcedureWorkerLTPO'
+import { HitchTimeStruct, hitchTimeRender } from '../../database/ui-worker/ProcedureWorkerHitchTime';
+
+export class SpLtpoChart {
+ private readonly trace: SpSystemTrace | undefined;
+ static APP_STARTUP_PID_ARR: Array = [];
+ static jsonRow: TraceRow | undefined;
+ static trace: SpSystemTrace;
+ static presentArr: Array = [];
+ static fanceNameList: Array = [];
+ static fpsnameList: Array = [];
+ static ltpoDataArr: Array = [];
+ static sendLTPODataArr: Array = [];
+ static sendHitchDataArr: Array = [];
+ constructor(trace: SpSystemTrace) {
+ SpLtpoChart.trace = trace;
+ }
+
+ async init() {
+ SpLtpoChart.ltpoDataArr = [];
+ SpLtpoChart.fanceNameList = await queryFanceNameList();
+ SpLtpoChart.fpsnameList = await queryFpsNameList();
+ SpLtpoChart.fanceNameList.map((item) => {
+ let cutFanceNameArr = item.name!.split(" ");
+ item.fanceId = Number(cutFanceNameArr[cutFanceNameArr.length - 1]);
+ })
+ SpLtpoChart.fpsnameList.map((item) => {
+ let cutFpsNameArr = item.name!.split(",")[0].split(":");
+ item.fps = Number(cutFpsNameArr[cutFpsNameArr.length - 1]);
+ })
+ if (SpLtpoChart.fanceNameList!.length && SpLtpoChart.fpsnameList.length === SpLtpoChart.fanceNameList.length) {
+ for (let i = 0; i < SpLtpoChart.fanceNameList.length; i++) {
+ let tmpFps = SpLtpoChart.fpsnameList[i]!.fps ? Number(SpLtpoChart.fpsnameList[i]!.fps) : 60;
+ this.pushLtpoData(
+ SpLtpoChart.ltpoDataArr,
+ Number(SpLtpoChart.fanceNameList[i]!.fanceId!),
+ tmpFps,
+ 0, 0, 0, 0
+ );
+ }
+ } else {
+ return;
+ }
+ if (SpLtpoChart.fanceNameList && SpLtpoChart.fanceNameList.length) {
+ await this.initFolder();
+ await this.initHitchTime();
+ }
+ }
+ pushLtpoData(
+ lptoArr: any[] | undefined,
+ fanceId: Number,
+ fps: Number,
+ startTs: Number,
+ dur: Number,
+ nextStartTs: Number,
+ nextDur: number
+ ): void {
+ lptoArr?.push(
+ {
+ fanceId: fanceId,
+ fps: fps,
+ startTs: startTs,
+ dur: dur,
+ nextStartTs: nextStartTs,
+ nextDur: nextDur
+ }
+ );
+ }
+ sendDataHandle(presentArr: LtpoStruct[], ltpoDataArr: LtpoStruct[]): Array {
+ let sendDataArr: LtpoStruct[] = [];
+ if (presentArr!.length && presentArr!.length === ltpoDataArr!.length) {
+ for (let i = 0; i < presentArr!.length; i++) {
+ ltpoDataArr[i].startTs = Number(presentArr[i].ts) - (window as any).recordStartNS;
+ ltpoDataArr[i].dur = presentArr[i].dur;
+ ltpoDataArr[i].nextStartTs = presentArr[i + 1] ? Number(presentArr[i + 1].ts) - (window as any).recordStartNS : '';
+ ltpoDataArr[i].nextDur = presentArr[i + 1] ? presentArr[i + 1].dur : 0;
+ }
+ } else {
+ return sendDataArr;
+ }
+ for (let i = 0; i < ltpoDataArr.length; i++) {
+ if (ltpoDataArr[i].fanceId !== -1 && ltpoDataArr[i].nextDur) {
+ let sendStartTs: number | undefined = 0;
+ let sendDur: number | undefined = 0;
+ sendStartTs = Number(ltpoDataArr[i].startTs) + Number(ltpoDataArr[i].dur);
+ sendDur = Number(ltpoDataArr[i].nextStartTs) + Number(ltpoDataArr[i].nextDur) - sendStartTs;
+ let tmpDur = (Math.ceil(sendDur / 100000)) / 10;
+ if (tmpDur < 170) {
+ sendDataArr.push(
+ {
+ dur: sendDur,
+ value: 0,
+ startTs: sendStartTs,
+ pid: ltpoDataArr[i].fanceId,
+ itid: ltpoDataArr[i].fanceId,
+ name: undefined,
+ presentFance: ltpoDataArr[i].fanceId,
+ ts: undefined,
+ fanceId: ltpoDataArr[i].fanceId,
+ fps: ltpoDataArr[i].fps,
+ nextStartTs: ltpoDataArr[i].nextStartTs,
+ nextDur: ltpoDataArr[i].nextDur,
+ translateY: undefined,
+ frame: undefined,
+ isHover: false
+ }
+ );
+ }
+ }
+ }
+ return sendDataArr;
+ }
+ async initFolder() {
+ SpLtpoChart.presentArr = [];
+ let row: TraceRow = TraceRow.skeleton();
+ row.rowId = SpLtpoChart.fanceNameList!.length ? `LTPO ${SpLtpoChart.fanceNameList[0].fanceId}` : '';
+ row.rowParentId = '';
+ row.rowType = TraceRow.ROW_TYPE_LTPO;
+ row.folder = false;
+ row.style.height = '40px';
+ row.name = `Lost Frames`;
+ row.favoriteChangeHandler = SpLtpoChart.trace.favoriteChangeHandler;
+ row.selectChangeHandler = SpLtpoChart.trace.selectChangeHandler;
+ row.supplier = async (): Promise> => {
+ SpLtpoChart.presentArr = await queryPresentInfo();
+ SpLtpoChart.presentArr.map((item) => {
+ let cutPresentArr = item.name!.split(" ");
+ item.presentFance = Number(cutPresentArr[cutPresentArr.length - 1]);
+ })
+ SpLtpoChart.sendLTPODataArr = this.sendDataHandle(SpLtpoChart.presentArr, SpLtpoChart.ltpoDataArr);
+ for (let i = 0; i < SpLtpoChart.sendLTPODataArr.length; i++) {
+ let tmpDur = SpLtpoChart.sendLTPODataArr[i].dur! / 1000000;
+ SpLtpoChart.sendLTPODataArr[i].value = (Math.round(tmpDur * Number(SpLtpoChart.sendLTPODataArr[i].fps) / 1000 - 1)) < 1 ? 0 : Math.round(tmpDur * Number(SpLtpoChart.sendLTPODataArr[i].fps) / 1000 - 1);
+ }
+ return SpLtpoChart.sendLTPODataArr;
+ }
+ row.focusHandler = (ev) => {
+ SpLtpoChart.trace?.displayTip(
+ row!,
+ LtpoStruct.hoverLtpoStruct,
+ `${(LtpoStruct.hoverLtpoStruct?.value!)}`
+ )
+ };
+ row.onThreadHandler = (useCache): void => {
+ let context: CanvasRenderingContext2D;
+ if (row.currentContext) {
+ context = row.currentContext;
+ } else {
+ context = row.collect ? SpLtpoChart.trace.canvasFavoritePanelCtx! : SpLtpoChart.trace.canvasPanelCtx!;
+ }
+ row.canvasSave(context);
+ (renders['ltpo-present'] as LtpoRender).renderMainThread(
+ {
+ appStartupContext: context,
+ useCache: useCache,
+ type: `ltpo-present ${row.rowId}`,
+ },
+ row
+ );
+ row.canvasRestore(context);
+ };
+ SpLtpoChart.trace.rowsEL?.appendChild(row);
+ }
+ async initHitchTime() {
+ SpLtpoChart.presentArr = [];
+ let row: TraceRow = TraceRow.skeleton();
+ row.rowId = SpLtpoChart.fanceNameList!.length ? `hitch-time ${SpLtpoChart.fanceNameList[0].fanceId}` : '';
+ row.rowParentId = '';
+ row.rowType = TraceRow.ROW_TYPE_HITCH_TIME;
+ row.folder = false;
+ row.style.height = '40px';
+ row.name = `Hitch Time`;
+ row.favoriteChangeHandler = SpLtpoChart.trace.favoriteChangeHandler;
+ row.selectChangeHandler = SpLtpoChart.trace.selectChangeHandler;
+ row.supplier = async (): Promise> => {
+ SpLtpoChart.presentArr = await queryPresentInfo();
+ SpLtpoChart.presentArr.map((item) => {
+ let cutPresentArr = item.name!.split(" ");
+ item.presentFance = Number(cutPresentArr[cutPresentArr.length - 1]);
+ })
+ SpLtpoChart.sendHitchDataArr = this.sendDataHandle(SpLtpoChart.presentArr, SpLtpoChart.ltpoDataArr);
+ for (let i = 0; i < SpLtpoChart.sendHitchDataArr.length; i++) {
+ let tmpVale = Number((Math.ceil(((SpLtpoChart.sendHitchDataArr[i].dur! / 1000000) - (1000 / SpLtpoChart.sendHitchDataArr[i].fps!)) * 10)) / 10);
+ SpLtpoChart.sendHitchDataArr[i].value = tmpVale! < 0 ? 0 : tmpVale;
+ }
+ return SpLtpoChart.sendHitchDataArr;
+ }
+ row.focusHandler = (ev) => {
+ SpLtpoChart.trace?.displayTip(
+ row!,
+ HitchTimeStruct.hoverHitchTimeStruct,
+ `${(HitchTimeStruct.hoverHitchTimeStruct?.value!)}`
+ )
+ };
+ row.onThreadHandler = (useCache): void => {
+ let context: CanvasRenderingContext2D;
+ if (row.currentContext) {
+ context = row.currentContext;
+ } else {
+ context = row.collect ? SpLtpoChart.trace.canvasFavoritePanelCtx! : SpLtpoChart.trace.canvasPanelCtx!;
+ }
+ row.canvasSave(context);
+ (renders['hitch'] as hitchTimeRender).renderMainThread(
+ {
+ appStartupContext: context,
+ useCache: useCache,
+ type: `hitch ${row.rowId}`,
+ },
+ row
+ );
+ row.canvasRestore(context);
+ };
+ SpLtpoChart.trace.rowsEL?.appendChild(row);
+ }
+}
diff --git a/ide/src/trace/component/trace/base/RangeSelect.ts b/ide/src/trace/component/trace/base/RangeSelect.ts
index a052cd6c645fe05af38bad3917047056857eb631..306068f105b556131c3859a494517473d9704072 100644
--- a/ide/src/trace/component/trace/base/RangeSelect.ts
+++ b/ide/src/trace/component/trace/base/RangeSelect.ts
@@ -19,7 +19,8 @@ import { ns2x, TimerShaftElement } from '../TimerShaftElement';
import { info } from '../../../../log/Log';
import './Extension';
import { SpSystemTrace } from '../../SpSystemTrace';
-import { querySearchRowFuncData } from '../../../database/SqlLite';
+import { fuzzyQueryFuncRowData, queryFuncRowData } from '../../../database/SqlLite';
+import { SpLtpoChart } from '../../chart/SpLTPO';
export class RangeSelect {
private rowsEL: HTMLDivElement | undefined | null;
@@ -80,35 +81,106 @@ export class RangeSelect {
if (this.selectHandler) {
this.selectHandler(this.rangeTraceRow || [], !this.isHover);
}
- //如果只框选了一条泳道,查询H:RSMainThread::DoComposition数据
- let docompositionData: Array = [];
- if (this.rangeTraceRow) {
- this.rangeTraceRow.forEach((row) => {
- row.docompositionList = [];
- });
- docompositionData = [];
+ //查询H:RSMainThread::DoComposition数据
+ if (this.rangeTraceRow?.length) {
+ let judgeRowName: boolean = this.checkProcessName(this.rangeTraceRow, 'render_service');
if (
- this.rangeTraceRow.length === 1 &&
- this.rangeTraceRow[0]?.getAttribute('row-type') === 'func' &&
- this.rangeTraceRow[0]?.getAttribute('name')?.startsWith('render_service')
+ // 如果框选的第一行和最后一行的父节点名称都以render_service开头
+ this.rangeTraceRow[0]!.parentRowEl?.getAttribute('name')?.startsWith('render_service') &&
+ this.rangeTraceRow[this.rangeTraceRow.length - 1].parentRowEl?.getAttribute('name')?.startsWith('render_service')
) {
- querySearchRowFuncData(
- 'H:RSMainThread::DoComposition',
- Number(this.rangeTraceRow[0]?.getAttribute('row-id')),
- TraceRow.rangeSelectObject!.startNS!,
- TraceRow.rangeSelectObject!.endNS!
- ).then((res) => {
- res.forEach((item) => {
- docompositionData.push(item.startTime!);
- });
- this.rangeTraceRow![0].docompositionList = docompositionData;
- });
+ this.handleFrameRateData(this.rangeTraceRow!, 'render_service', 'H:RSMainThread::DoComposition');
+ this.handleFrameRateData(this.rangeTraceRow!, 'RSHardwareThrea', 'H:Repaint');
+ this.handleFrameRateData(this.rangeTraceRow!, 'present', 'H:Waiting for present Fence');
+ } else if (judgeRowName) {
+ this.handleFrameRateData(this.rangeTraceRow[0].childrenList, 'render_service', 'H:RSMainThread::DoComposition');
+ this.handleFrameRateData(this.rangeTraceRow[0].childrenList, 'RSHardwareThrea', 'H:Repaint');
+ this.handleFrameRateData(this.rangeTraceRow[0].childrenList, 'present', 'H:Waiting for present Fence');
}
}
}
this.isMouseDown = false;
}
+// 检查框选进程是否为render-service
+checkProcessName(selectRangeRow: Array>, processName: string) {
+ let judgeName: boolean = false;
+ for (const item of selectRangeRow) {
+ if (
+ item.childrenList.length &&
+ item.getAttribute('name')?.startsWith(processName)
+ ) {
+ judgeName = true;
+ break;
+ }
+ }
+ return judgeName
+}
+
+// 根据框选行和方法名查询数据
+handleFrameRateData(rowList: Array>, rowName: string, funcName: string): void {
+ let dataList: Array = [];
+ for (let i = 0; i < rowList.length; i++) {
+ if (rowList[i].getAttribute('row-type') === 'func') {
+ // console.log('funcName', funcName);
+ if (rowList[i]?.getAttribute('name')?.startsWith(rowName)) {
+ queryFuncRowData(
+ funcName,
+ Number(rowList[i]?.getAttribute('row-id')),
+ TraceRow.rangeSelectObject!.startNS!,
+ TraceRow.rangeSelectObject!.endNS!,
+ ).then((res) => {
+ if (res.length >= 2) {
+ res.forEach((item) => {
+ dataList.push(item.startTime!)
+ });
+ rowList[i].frameRateList = dataList;
+ }
+ });
+ }
+ if (rowName === 'present' && rowList[i]?.getAttribute('name')?.startsWith(rowName)) {
+ this.handlePresentData(rowList[i], funcName)
+ }
+ if (dataList.length) {
+ break;
+ }
+ }
+ }
+}
+
+// 处理框选时present线程的数据
+handlePresentData(currentRow: TraceRow, funcName: string): void {
+ let dataList: Array = [];
+ fuzzyQueryFuncRowData(
+ funcName,
+ Number(currentRow?.getAttribute('row-id')),
+ TraceRow.rangeSelectObject!.startNS!,
+ TraceRow.rangeSelectObject!.endNS!,
+ ).then((res) => {
+ if (res.length >= 2) {
+ res.forEach((item) => {
+ dataList.push(item.endTime!)
+ });
+ currentRow.frameRateList = dataList;
+ if (currentRow.frameRateList.length >= 2) {
+ let hitchTimeList: Array = []
+ for (let i = 0; i < SpLtpoChart.sendHitchDataArr.length; i++) {
+ if (SpLtpoChart.sendHitchDataArr[i].startTs! >= dataList[0]
+ &&
+ SpLtpoChart.sendHitchDataArr[i].startTs! < dataList[dataList.length - 1]) {
+ hitchTimeList.push(SpLtpoChart.sendHitchDataArr[i].value!)
+ }
+ if (SpLtpoChart.sendHitchDataArr[i].startTs! >= dataList[dataList.length - 1]) {
+ break;
+ }
+ }
+ let sum: number = hitchTimeList.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
+ let hitchRate: number = (sum / ((TraceRow.rangeSelectObject!.endNS! - TraceRow.rangeSelectObject!.startNS!) / 1000000))
+ currentRow.hitchRateData = hitchRate
+ }
+ }
+ });
+}
isDrag(): boolean {
return this.startPageX != this.endPageX;
}
@@ -256,9 +328,17 @@ export class RangeSelect {
}
});
if (this.rangeTraceRow && this.rangeTraceRow.length) {
- this.rangeTraceRow!.forEach((row) => {
- row.docompositionList = [];
- });
+ if (this.rangeTraceRow[0].parentRowEl) {
+ for (let i = 0; i < this.rangeTraceRow[0].parentRowEl.childrenList.length; i++) {
+ this.rangeTraceRow[0].parentRowEl.childrenList[i].frameRateList = [];
+ this.rangeTraceRow[0].parentRowEl.childrenList[i].hitchRateData = null;
+ }
+ } else {
+ for (let j = 0; j < this.rangeTraceRow[0].childrenList.length; j++) {
+ this.rangeTraceRow[0].childrenList[j].frameRateList = [];
+ this.rangeTraceRow[0].childrenList[j].hitchRateData = null;
+ }
+ }
}
this.timerShaftEL!.sportRuler!.isRangeSelect = this.rangeTraceRow?.length > 0;
this.timerShaftEL!.sportRuler!.draw();
diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts
index c1ba67b7cc06e945f1024e407f0f393043dbb9a1..b1bb2f61fce3328cf4d5870be8868d9c612f4ba0 100644
--- a/ide/src/trace/component/trace/base/TraceRow.ts
+++ b/ide/src/trace/component/trace/base/TraceRow.ts
@@ -182,12 +182,15 @@ export class TraceRow extends HTMLElement {
childrenList: Array> = [];
parentRowEl: TraceRow | undefined;
_rowSettingList: Array | null | undefined;
- _docompositionList: Array | undefined;
+ _frameRateList: Array | undefined;
+ _hitchRateData: number | undefined | null
focusHandler?: (ev: MouseEvent) => void | undefined;
findHoverStruct?: () => void | undefined;
public funcMaxHeight: number = 0;
currentContext: CanvasRenderingContext2D | undefined | null;
+ static ROW_TYPE_HITCH_TIME: string | null | undefined;
+ static ROW_TYPE_LTPO: string | null | undefined;
constructor(
args: {
@@ -197,12 +200,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;
@@ -245,12 +248,21 @@ export class TraceRow extends HTMLElement {
'row-setting-popover-direction',
];
}
- get docompositionList(): Array | undefined {
- return this._docompositionList;
+
+ get frameRateList(): Array | undefined {
+ return this._frameRateList;
+ }
+
+ set frameRateList(value: Array | undefined) {
+ this._frameRateList = value;
+ }
+
+ get hitchRateData(): number | undefined | null {
+ return this._hitchRateData;
}
- set docompositionList(value: Array | undefined) {
- this._docompositionList = value;
+ set hitchRateData(value: number | undefined | null) {
+ this._hitchRateData = value;
}
get funcExpand(): boolean {
diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts b/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts
index 4a8db661cec919264f2484a58c140f4494aa777a..7882c2335bff8bc15599d617ead4889cad4a0709 100644
--- a/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts
+++ b/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts
@@ -75,6 +75,10 @@ export class TabPaneThreadUsage extends BaseElement {
if (result != null && result.length > 0) {
log('getTabThreadStates result size : ' + result.length);
let filterArr = result.filter((it) => threadUsageParam.processIds.includes(it.pid));
+ let totalDurtion = 0;
+ filterArr.forEach((item) => {
+ totalDurtion = totalDurtion + item.wallDuration;
+ })
let map: Map = new Map();
for (let resultEl of filterArr) {
if (threadUsageParam.processIds.includes(resultEl.pid)) {
@@ -83,7 +87,7 @@ export class TabPaneThreadUsage extends BaseElement {
map.get(resultEl.tid)[`cpu${resultEl.cpu}TimeStr`] = getProbablyTime(resultEl.wallDuration || 0);
map.get(resultEl.tid)[`cpu${resultEl.cpu}Ratio`] = (
(100.0 * (resultEl.wallDuration || 0)) /
- (threadUsageParam.rightNs - threadUsageParam.leftNs)
+ (totalDurtion)
).toFixed(2);
map.get(resultEl.tid)[`wallDuration`] =
map.get(resultEl.tid)[`wallDuration`] + (resultEl.wallDuration || 0);
@@ -108,7 +112,7 @@ export class TabPaneThreadUsage extends BaseElement {
threadStatesStruct[`cpu${resultEl.cpu}TimeStr`] = getProbablyTime(resultEl.wallDuration || 0);
threadStatesStruct[`cpu${resultEl.cpu}Ratio`] = (
(100.0 * (resultEl.wallDuration || 0)) /
- (threadUsageParam.rightNs - threadUsageParam.leftNs)
+ (totalDurtion)
).toFixed(2);
map.set(resultEl.tid, threadStatesStruct);
}
diff --git a/ide/src/trace/database/SqlLite.ts b/ide/src/trace/database/SqlLite.ts
index a3e9e84e209fffe5ffc9526658fe0e8689e664d2..9a4e7268fb18d17292f9abc523cf527d289eb1fc 100644
--- a/ide/src/trace/database/SqlLite.ts
+++ b/ide/src/trace/database/SqlLite.ts
@@ -85,6 +85,7 @@ import { HiSysEventStruct } from './ui-worker/ProcedureWorkerHiSysEvent';
import { KeyPathStruct } from '../bean/KeyPathStruct';
import { FuncNameCycle, BinderItem } from '../bean/BinderProcessThread';
import { GpuCountBean, SearchGpuFuncBean } from '../bean/GpufreqBean';
+import { LtpoStruct } from './ui-worker/ProcedureWorkerLTPO';
class DataWorkerThread {
taskMap: any = {};
@@ -1545,6 +1546,94 @@ export const querySingleAppStartupsName = (pid: number): Promise> =>
where pid=$pid`,
{ $pid: pid }
);
+ export const queryPresentInfo =(): Promise > =>
+ query(
+ 'queryPresentInfo',
+ `SELECT ts,dur,name FROM "callstack" WHERE callid in (SELECT id FROM "thread" WHERE name LIKE('Present%'))
+ AND name LIKE('H:Waiting for Present Fence%')`
+ )
+
+ export const queryFanceNameList = ():Promise> =>
+ query(
+ 'queryFanceNameList',
+ `SELECT ts,dur,name FROM "callstack" WHERE callid in (SELECT id FROM "thread" WHERE name LIKE('RSHardwareThrea%'))
+ AND name LIKE('H:Present Fence%')`
+ )
+
+ export const queryFpsNameList = ():Promise> =>
+ query(
+ 'queryFpsNameList',
+ `SELECT name FROM "callstack" WHERE callid in (SELECT id FROM "thread" WHERE name LIKE('RSHardwareThrea%'))
+ AND name LIKE('%Layers rate%')`
+ )
+ export const queryFuncRowData = (
+ funcName: string,
+ tIds: number,
+ leftNS: number,
+ rightNS: number
+ ): Promise> =>
+ query(
+ 'queryFuncRowData',
+ `
+ select
+ c.name as funName,
+ c.ts - r.start_ts as startTime
+ from
+ callstack c
+ left join
+ thread t
+ on
+ c.callid = t.id
+ left join
+ process p
+ on
+ t.ipid = p.id
+ left join
+ trace_range r
+ where
+ c.name like '${funcName}'
+ and
+ t.tid = ${tIds}
+ and
+ not ((startTime < ${leftNS}) or (startTime > ${rightNS}));
+ `,
+ { $search: funcName }
+ );
+
+ export const fuzzyQueryFuncRowData = (
+ funcName: string,
+ tIds: number,
+ leftNS: number,
+ rightNS: number
+ ): Promise> =>
+ query(
+ 'fuzzyQueryFuncRowData',
+ `
+ select
+ c.name as funName,
+ c.ts - r.start_ts as startTime,
+ c.ts - r.start_ts + c.dur as endTime
+ from
+ callstack c
+ left join
+ thread t
+ on
+ c.callid = t.id
+ left join
+ process p
+ on
+ t.ipid = p.id
+ left join
+ trace_range r
+ where
+ c.name like '%${funcName}%'
+ and
+ t.tid = ${tIds}
+ and
+ not ((endTime < ${leftNS}) or (endTime > ${rightNS}));
+ `,
+ { $search: funcName }
+ );
export const queryProcessSoMaxDepth = (): Promise> =>
query(
diff --git a/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/ide/src/trace/database/ui-worker/ProcedureWorker.ts
index 5382eb22358e87ae7ef7b03fc64c0c100f17c3ce..5218c4276c91416c6d278e15dfc9deee04e19de0 100644
--- a/ide/src/trace/database/ui-worker/ProcedureWorker.ts
+++ b/ide/src/trace/database/ui-worker/ProcedureWorker.ts
@@ -61,6 +61,8 @@ import { HiSysEventRender } from './ProcedureWorkerHiSysEvent';
import { AllAppStartupRender } from './ProcedureWorkerAllAppStartup';
import { FreqExtendRender } from './ProcedureWorkerFreqExtend';
import { BinderRender } from './procedureWorkerBinder';
+import { hitchTimeRender } from './ProcedureWorkerHitchTime';
+import { LtpoRender } from './ProcedureWorkerLTPO';
let dataList: any = {};
let dataList2: any = {};
@@ -81,6 +83,8 @@ export let renders: any = {
process: new ProcessRender(),
'app-start-up': new AppStartupRender(),
'all-app-start-up': new AllAppStartupRender(),
+ 'ltpo-present': new LtpoRender(),
+ 'hitch': new hitchTimeRender(),
'app-so-init': new SoRender(),
heap: new HeapRender(),
'heap-timeline': new HeapTimelineRender(),
diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts
index 7b804d5bcc3297c54f19597819f1e22ae28fd3d5..cf8a86783ce7800e4d8867aef531088606a1ecee 100644
--- a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts
+++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts
@@ -48,10 +48,10 @@ export class RequestMessage {
totalNS: any;
slicesTime:
| {
- startTime: number | null;
- endTime: number | null;
- color: string | null;
- }
+ startTime: number | null;
+ endTime: number | null;
+ color: string | null;
+ }
| undefined;
range: any;
scale: any;
@@ -64,9 +64,9 @@ export class RequestMessage {
id: any;
postMessage:
| {
- (message: any, targetOrigin: string, transfer?: Transferable[]): void;
- (message: any, options?: WindowPostMessageOptions): void;
- }
+ (message: any, targetOrigin: string, transfer?: Transferable[]): void;
+ (message: any, options?: WindowPostMessageOptions): void;
+ }
| undefined;
}
@@ -99,8 +99,8 @@ export function ns2Timestamp(ns: number): string {
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second
.toString()
.padStart(2, '0')}:${millisecond.toString().padStart(3, '0')}:${microsecond
- .toString()
- .padStart(3, '0')}:${nanosecond.toString().padStart(3, '0')}`;
+ .toString()
+ .padStart(3, '0')}:${nanosecond.toString().padStart(3, '0')}`;
}
const offsetX = 5;
@@ -539,10 +539,10 @@ export function drawFlagLine(
frame: any,
slicesTime:
| {
- startTime: number | null | undefined;
- endTime: number | null | undefined;
- color: string | null | undefined;
- }
+ startTime: number | null | undefined;
+ endTime: number | null | undefined;
+ color: string | null | undefined;
+ }
| undefined
) {
if (commonCtx) {
@@ -746,104 +746,122 @@ export function drawSelectionRange(context: any, params: TraceRow) {
}
// 绘制方法H:RSMainThread::DoComposition平均帧率的箭头指示线条
- if (params._docompositionList?.length) {
- const rateList: Array = [...new Set(params.docompositionList)];
- if (rateList.length >= 2) {
- // 计算平均帧率
- let cutres: number = rateList[rateList.length - 1]! - rateList[0]!;
- let avgFrameRate: string = (((rateList.length - 1) / cutres) * 1000000000).toFixed(1) + 'fps';
-
- let avgRateStartX = Math.floor(
- ns2x(
- rateList[0]!,
- TraceRow.range?.startNS ?? 0,
- TraceRow.range?.endNS ?? 0,
- TraceRow.range?.totalNS ?? 0,
- params.frame
- )
- );
- let avgRateEndX = Math.floor(
- ns2x(
- rateList[rateList.length - 1]!,
- TraceRow.range?.startNS ?? 0,
- TraceRow.range?.endNS ?? 0,
- TraceRow.range?.totalNS ?? 0,
- params.frame
- )
- );
- const textWidth = context.measureText(avgFrameRate).width;
- const textHeight = 25;
- const padding = 5;
- let textX =
- Math.floor(
- ns2x(
- (rateList[0]! + rateList[rateList.length - 1]!) / 2,
- TraceRow.range?.startNS ?? 0,
- TraceRow.range?.endNS ?? 0,
- TraceRow.range?.totalNS ?? 0,
- params.frame
- )
- ) -
- textWidth / 2;
- const textY = params.frame.y + 25;
-
- //左移到边界,不画线和文字
- if (avgRateStartX <= 0) {
- avgRateStartX = -100;
- }
- if (avgRateEndX <= 0) {
- avgRateEndX = -100;
- }
- if (textX <= 0) {
- textX = -100;
- }
- //右移到边界,不画线和文字
- if (textX + textWidth / 2 >= params.frame.width) {
- textX = params.frame.width + 100;
- }
- if (avgRateStartX >= params.frame.width) {
- avgRateStartX = params.frame.width + 100;
- }
- if (avgRateEndX >= params.frame.width) {
- avgRateEndX = params.frame.width + 100;
- }
- // 绘制文字背景矩形
- context.fillStyle = 'red';
- context.fillRect(
- textX - padding,
- textY - textHeight + padding,
- textWidth + padding * 2,
- textHeight - padding * 2
- );
+ if (params.frameRateList && params.frameRateList.length) {
+ changeFrameRatePoint(params.frameRateList, context, params);
+ };
+ }
+}
- context.lineWidth = 2;
- context.strokeStyle = 'yellow';
- context.beginPath();
- context.moveTo(avgRateStartX, textY);
- context.lineTo(avgRateEndX, textY);
- context.stroke();
-
- const arrowSize = 5.5;
- const arrowHead = (x: number, y: number, direction: 'left' | 'right') => {
- context.beginPath();
- const headX = x + (direction === 'left' ? arrowSize : -arrowSize);
- const headY = y - arrowSize / 2;
- context.moveTo(x, y);
- context.lineTo(headX, headY);
- context.lineTo(headX, y + arrowSize);
- context.closePath();
-
- context.fillStyle = 'yellow';
- context.fill();
- };
- arrowHead(avgRateStartX, textY - 1, 'left');
- arrowHead(avgRateEndX, textY - 1, 'right');
-
- context.fillStyle = 'white';
- context.fillText(avgFrameRate, textX, textY - 8);
- }
- }
+// 转换起始点坐标
+function changeFrameRatePoint(arrList: Array, ctx: any, selectParams: TraceRow): void {
+ const rateList: Array = [...new Set(arrList)];
+ let avgRateStartX = Math.floor(
+ ns2x(
+ rateList[0]!,
+ TraceRow.range?.startNS ?? 0,
+ TraceRow.range?.endNS ?? 0,
+ TraceRow.range?.totalNS ?? 0,
+ selectParams.frame
+ )
+ );// 起始坐标
+
+ let avgRateEndX = Math.floor(
+ ns2x(
+ rateList[rateList.length - 1]!,
+ TraceRow.range?.startNS ?? 0,
+ TraceRow.range?.endNS ?? 0,
+ TraceRow.range?.totalNS ?? 0,
+ selectParams.frame
+ )
+ );// 结束坐标
+
+ drawavgFrameRate(rateList, ctx, selectParams, avgRateStartX, avgRateEndX); // 绘制
+}
+
+// 计算平均帧率
+function calculateAvgRate(arr: Array) {
+ let cutres: number = (arr[arr.length - 1]! - arr[0]!); // 结束时间-开始时间
+ let avgRate: string = ((arr.length - 1) / cutres * 1000000000).toFixed(1); // 帧数/时间差 * 1000000000 四舍五入保留一位小数
+ return avgRate;
+}
+
+// 绘制平均帧率箭头指示线条
+function drawavgFrameRate(arrList: Array, ctx: any, selectParams: TraceRow, startX: number, endX: number): void {
+ // 获取平均帧率
+ let avgFrameRate: string = calculateAvgRate(arrList) + 'fps';
+ if (selectParams.hitchRateData !== null && selectParams.hitchRateData !== undefined) {
+ let hitchRate: string = (Number(selectParams.hitchRateData) * 100).toFixed(2) + '%';
+ avgFrameRate = 'RS:' + ' ' + calculateAvgRate(arrList) + 'fps' + ' ' + ',' + ' ' + 'HitchRate:' + ' ' + hitchRate;
+ } else {
+ avgFrameRate = 'RS:' + ' ' + calculateAvgRate(arrList) + 'fps';
+ }
+
+ const textWidth = ctx.measureText(avgFrameRate).width; // 测量文本的宽度
+ const textHeight = 25; //文本的高度
+ const padding = 5; //内边距
+ let textX = Math.floor(ns2x(
+ (arrList[0]! + arrList[arrList.length - 1]!) / 2,
+ TraceRow.range?.startNS ?? 0,
+ TraceRow.range?.endNS ?? 0,
+ TraceRow.range?.totalNS ?? 0,
+ selectParams.frame
+ )) - textWidth / 2; //根据帧率范围的中间值计算文本的起始x坐标
+ const textY = selectParams.frame.y + 10;
+
+ //左移到边界,不画线和文字
+ if (startX <= 0) {
+ startX = -100;
+ }
+ if (endX <= 0) {
+ endX = -100;
+ }
+ if (textX <= 0) {
+ textX = -100;
+ }
+ //右移到边界,不画线和文字
+ if (textX + textWidth / 2 >= selectParams.frame.width) {
+ textX = selectParams.frame.width + 100;
}
+ if (startX >= selectParams.frame.width) {
+ startX = selectParams.frame.width + 100;
+ }
+ if (endX >= selectParams.frame.width) {
+ endX = selectParams.frame.width + 100;
+ }
+
+ // 设置横线的宽度、颜色并绘制
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = 'yellow';
+
+ ctx.beginPath();
+ ctx.moveTo(startX, textY);
+ ctx.lineTo(endX, textY);
+ ctx.stroke();
+
+ // 定义箭头的大小和绘制箭头的函数
+ const arrowSize = 5.5;
+ const arrowHead = (x: number, y: number, direction: 'left' | 'right') => {
+ ctx.beginPath();
+ const headX = x + (direction === 'left' ? arrowSize : -arrowSize);
+ const headY = y - arrowSize / 2;
+ ctx.moveTo(x, y);
+ ctx.lineTo(headX, headY);
+ ctx.lineTo(headX, y + arrowSize);
+ ctx.closePath();
+
+ ctx.fillStyle = 'yellow';
+ ctx.fill();
+ };
+ arrowHead(startX, textY - 1, 'left');
+ arrowHead(endX, textY - 1, 'right');
+
+ // 绘制文字背景矩形
+ ctx.fillStyle = 'red';
+ ctx.fillRect(textX - padding, textY - textHeight / 2 + padding, textWidth + padding * 2, textHeight - padding * 2);
+
+ // 绘制文字
+ ctx.fillStyle = 'white';
+ ctx.fillText(avgFrameRate, textX, textY + 4);
}
export function drawWakeUp(
@@ -1210,7 +1228,7 @@ export function drawLoading(
frame: any,
left: number,
right: number
-) {}
+) { }
export function drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect, data: any) {
if (data.textMetricsWidth === undefined) {
diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerHitchTime.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerHitchTime.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f5195c2e057977840e1844fca893497d0929a6e
--- /dev/null
+++ b/ide/src/trace/database/ui-worker/ProcedureWorkerHitchTime.ts
@@ -0,0 +1,112 @@
+/*
+ * 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 { BaseStruct, dataFilterHandler } from './ProcedureWorkerCommon';
+import { TraceRow } from '../../component/trace/base/TraceRow';
+
+export class hitchTimeRender {
+ renderMainThread(
+ req: {
+ appStartupContext: CanvasRenderingContext2D;
+ useCache: boolean;
+ type: string;
+ },
+ ltpoRow: TraceRow
+ ): void {
+ let list = ltpoRow.dataList;
+ HitchTimeStruct.maxVal = 0;
+ for (let i = 0; i < list.length; i++) {
+ if (Number(list[i].value) > HitchTimeStruct.maxVal) {
+ HitchTimeStruct.maxVal = Number(list[i].value)
+ };
+ }
+ let filter = ltpoRow.dataListCache;
+ dataFilterHandler(list, filter, {
+ startKey: 'startTs',
+ durKey: 'dur',
+ startNS: TraceRow.range?.startNS ?? 0,
+ endNS: TraceRow.range?.endNS ?? 0,
+ totalNS: TraceRow.range?.totalNS ?? 0,
+ frame: ltpoRow.frame,
+ paddingTop: 5,
+ useCache: req.useCache || !(TraceRow.range?.refresh ?? false),
+ });
+ req.appStartupContext.globalAlpha = 0.6;
+ let find = false;
+ let offset = 3;
+ for (let re of filter) {
+ if (ltpoRow.isHover) {
+ if (
+ re.frame &&
+ ltpoRow.hoverX >= re.frame.x - offset &&
+ ltpoRow.hoverX <= re.frame.x + re.frame.width + offset
+ ) {
+ HitchTimeStruct.hoverHitchTimeStruct = re;
+ find = true;
+ }
+ }
+ if (!ltpoRow.isHover) HitchTimeStruct.hoverHitchTimeStruct = undefined
+ if (!find && ltpoRow.isHover) {
+ HitchTimeStruct.hoverHitchTimeStruct = undefined;
+ }
+ req.appStartupContext.beginPath()
+ HitchTimeStruct.draw(req.appStartupContext, re);
+ req.appStartupContext.closePath()
+ }
+ }
+}
+
+
+export class HitchTimeStruct extends BaseStruct {
+ static hoverHitchTimeStruct: HitchTimeStruct | undefined;
+ static selectHitchTimeStruct: HitchTimeStruct | undefined;
+ static maxVal: number = 0;
+ dur: number | undefined;
+ name: string | undefined;
+ presentFance: number | undefined;
+ ts: number | undefined;
+ fanceId: number | undefined;
+ fps: number | undefined;
+ startTs: number | undefined;
+ nextStartTs: string | number | undefined;
+ nextDur: number | undefined;
+ value: number | undefined;
+ pid: number | undefined;
+ itid: number | undefined;
+
+ static draw(ctx: CanvasRenderingContext2D, data: HitchTimeStruct): void {
+ if (data.frame) {
+ ctx.fillStyle = '#9933FA';
+ if (data === HitchTimeStruct.hoverHitchTimeStruct || data === HitchTimeStruct.selectHitchTimeStruct) {
+ let drawHeight: number = Math.floor(
+ ((Number(data.value) || 0) * (data.frame.height || 0) * 1.0) / HitchTimeStruct.maxVal!
+ );
+ drawHeight = drawHeight < 1 ? 1 : drawHeight
+ ctx.globalAlpha = 1.0;
+ ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, data.frame.width, drawHeight);
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = ' #0000FF';
+ ctx.strokeRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, data.frame.width, drawHeight)
+ } else {
+ ctx.globalAlpha = 0.6;
+ let drawHeight: number = Math.floor(((Number(data.value) || 0) * (data.frame.height || 0)) / HitchTimeStruct.maxVal!);
+ drawHeight = drawHeight < 1 ? 1 : drawHeight
+ ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, data.frame.width, drawHeight)
+ }
+
+ }
+ }
+
+}
diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerLTPO.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerLTPO.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb986a5cf391107a984e1a2aa31a56949d2dca89
--- /dev/null
+++ b/ide/src/trace/database/ui-worker/ProcedureWorkerLTPO.ts
@@ -0,0 +1,110 @@
+/*
+ * 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 { BaseStruct, dataFilterHandler } from './ProcedureWorkerCommon';
+import { TraceRow } from '../../component/trace/base/TraceRow';
+
+export class LtpoRender {
+ renderMainThread(
+ req: {
+ appStartupContext: CanvasRenderingContext2D;
+ useCache: boolean;
+ type: string;
+ },
+ ltpoRow: TraceRow
+ ): void {
+ let list = ltpoRow.dataList;
+ LtpoStruct.maxVal = 0;
+ for (let i = 0; i < list.length; i++) {
+ if (Number(list[i].value) > LtpoStruct.maxVal) LtpoStruct.maxVal = Number(list[i].value);
+ }
+ let filter = ltpoRow.dataListCache;
+ dataFilterHandler(list, filter, {
+ startKey: 'startTs',
+ durKey: 'dur',
+ startNS: TraceRow.range?.startNS ?? 0,
+ endNS: TraceRow.range?.endNS ?? 0,
+ totalNS: TraceRow.range?.totalNS ?? 0,
+ frame: ltpoRow.frame,
+ paddingTop: 5,
+ useCache: req.useCache || !(TraceRow.range?.refresh ?? false),
+ });
+ req.appStartupContext.globalAlpha = 0.6;
+ let find = false;
+ let offset = 3;
+ for (let re of filter) {
+ if (ltpoRow.isHover) {
+ if (
+ re.frame &&
+ ltpoRow.hoverX >= re.frame.x - offset &&
+ ltpoRow.hoverX <= re.frame.x + re.frame.width + offset
+ ) {
+ LtpoStruct.hoverLtpoStruct = re;
+ find = true;
+ }
+ }
+ if(!ltpoRow.isHover) LtpoStruct.hoverLtpoStruct = undefined
+ if (!find && ltpoRow.isHover) {
+ LtpoStruct.hoverLtpoStruct = undefined;
+ }
+ req.appStartupContext.beginPath()
+ LtpoStruct.draw(req.appStartupContext, re);
+ req.appStartupContext.closePath()
+ }
+ }
+}
+
+
+export class LtpoStruct extends BaseStruct {
+ static hoverLtpoStruct: LtpoStruct | undefined;
+ static selectLtpoStruct: LtpoStruct | undefined;
+ static maxVal: number | undefined;
+ dur: number | undefined;
+ name: string | undefined;
+ presentFance: number | undefined;
+ ts: number | undefined;
+ fanceId: number | undefined;
+ fps: number | undefined;
+ startTs: number | undefined;
+ nextStartTs: string | number | undefined;
+ nextDur: number | undefined;
+ value: number | undefined ;
+ pid: number | undefined;
+ itid: number | undefined;
+
+ static draw(ctx: CanvasRenderingContext2D, data: LtpoStruct): void {
+ if (data.frame) {
+ ctx.fillStyle = '#9933FA';
+ if (data === LtpoStruct.hoverLtpoStruct || data === LtpoStruct.selectLtpoStruct) {
+ let drawHeight: number = Math.floor(
+ ((Number(data.value) || 0) * (data.frame.height || 0) * 1.0) / LtpoStruct.maxVal!
+ );
+ drawHeight = drawHeight < 1 ? 1 : drawHeight
+ ctx.globalAlpha = 1.0;
+ ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, data.frame.width, drawHeight);
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = ' #0000FF';
+ ctx.strokeRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, data.frame.width, drawHeight)
+ } else {
+ ctx.globalAlpha = 0.6;
+ let drawHeight: number = Math.floor(((Number(data.value) || 0) * (data.frame.height || 0)) / LtpoStruct.maxVal!);
+ drawHeight = drawHeight < 1 ? 1 : drawHeight
+ ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, data.frame.width, drawHeight)
+ }
+
+ }
+ }
+
+}