* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BaseElement, element } from '../../base-ui/BaseElement';
import './trace/TimerShaftElement';
import './trace/base/TraceRow';
import { threadPool, threadPool2 } from '../database/SqlLite';
import { TraceRow } from './trace/base/TraceRow';
import { TimerShaftElement } from './trace/TimerShaftElement';
import './trace/base/TraceSheet';
import { TraceSheet } from './trace/base/TraceSheet';
import { RangeSelect } from './trace/base/RangeSelect';
import { SelectionParam } from '../bean/BoxSelection';
import { procedurePool } from '../database/Procedure';
import { SpApplication } from '../SpApplication';
import { Flag } from './trace/timer-shaft/Flag';
import { SlicesTime, SportRuler } from './trace/timer-shaft/SportRuler';
import { SpHiPerf } from './chart/SpHiPerf';
import { SearchSdkBean } from '../bean/SearchFuncBean';
import { info } from '../../log/Log';
import {
drawFlagLineSegment,
drawLines,
drawLinkLines,
drawLogsLineSegment,
drawWakeUp,
drawWakeUpList,
LineType,
ns2x,
ns2xByTimeShaft,
PairPoint,
Rect,
prioClickHandlerFun,
drawThreadCurve,
} from '../database/ui-worker/ProcedureWorkerCommon';
import { SpChartManager } from './chart/SpChartManager';
import { CpuStruct, WakeupBean } from '../database/ui-worker/cpu/ProcedureWorkerCPU';
import { ProcessStruct } from '../database/ui-worker/ProcedureWorkerProcess';
import { CpuFreqStruct } from '../database/ui-worker/ProcedureWorkerFreq';
import { CpuFreqLimitsStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread';
import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc';
import { CpuStateStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuState';
import { HiPerfCpuStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2';
import { HiPerfProcessStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2';
import { HiPerfThreadStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2';
import { HiPerfEventStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent';
import { HiPerfReportStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport';
import { FpsStruct } from '../database/ui-worker/ProcedureWorkerFPS';
import { CpuAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerCpuAbility';
import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerDiskIoAbility';
import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility';
import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility';
import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock';
import { DmaFenceStruct } from '../database/ui-worker/ProcedureWorkerDmaFence';
import { Utils } from './trace/base/Utils';
import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq';
import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank';
import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent';
import { HeapStruct } from '../database/ui-worker/ProcedureWorkerHeap';
import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
import { HeapSnapshotStruct } from '../database/ui-worker/ProcedureWorkerHeapSnapshot';
import { HeapDataInterface } from '../../js-heap/HeapDataInterface';
import { LitTabs } from '../../base-ui/tabs/lit-tabs';
import { TraceRowConfig } from './trace/base/TraceRowConfig';
import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection';
import { SpChartList } from './trace/SpChartList';
import './trace/SpChartList';
import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup';
import { AllAppStartupStruct } from '../database/ui-worker/ProcedureWorkerAllAppStartup';
import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit';
import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic';
import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation';
import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing';
import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler';
import { FileInfo } from '../../js-heap/model/UiStruct';
import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot';
import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample';
import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample';
import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag';
import { LitTabpane } from '../../base-ui/tabs/lit-tabpane';
import { HiPerfCallChartStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCallChart';
import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon';
import { searchCpuDataSender } from '../database/data-trafic/CpuDataSender';
import { resetVSync } from './chart/VSync';
import { QueryEnum } from '../database/data-trafic/utils/QueryEnum';
import { SpSystemTraceHtml } from './SpSystemTrace.html';
import { querySceneSearchFunc, querySearchFunc } from '../database/sql/Func.sql';
import { IOStruct } from '../database/ui-worker/ProcedureWorkerIO';
import { queryCpuKeyPathData } from '../database/sql/Cpu.sql';
import { LtpoStruct } from '../database/ui-worker/ProcedureWorkerLTPO';
import { HitchTimeStruct } from '../database/ui-worker/ProcedureWorkerHitchTime';
import { ProcessMemStruct } from '../database/ui-worker/ProcedureWorkerMem';
import {
spSystemTraceInit,
spSystemTraceInitElement,
spSystemTraceInitPointToEvent,
spSystemTraceParentRowSticky,
spSystemTraceShowStruct,
} from './SpSystemTrace.init';
import {
spSystemTraceDrawDistributedLine,
spSystemTraceDrawFuncLine,
spSystemTraceDrawJankLine,
spSystemTraceDrawTaskPollLine,
spSystemTraceDrawThreadLine,
} from './SpSystemTrace.line';
import spSystemTraceOnClickHandler, {
spSystemTraceDocumentOnClick,
spSystemTraceDocumentOnKeyDown,
spSystemTraceDocumentOnKeyPress,
spSystemTraceDocumentOnKeyUp,
spSystemTraceDocumentOnMouseDown,
spSystemTraceDocumentOnMouseMove,
spSystemTraceDocumentOnMouseOut,
spSystemTraceDocumentOnMouseUp,
spSystemTraceDocumentOnMouseMoveMouseDown,
} from './SpSystemTrace.event';
import { SampleStruct } from '../database/ui-worker/ProcedureWorkerBpftrace';
import { readTraceFileBuffer } from '../SpApplicationPublicFunc';
import { PerfToolStruct } from '../database/ui-worker/ProcedureWorkerPerfTool';
import { BaseStruct } from '../bean/BaseStruct';
import { GpuCounterStruct } from '../database/ui-worker/ProcedureWorkerGpuCounter';
import { SpProcessChart } from './chart/SpProcessChart';
import { LitSearch } from './trace/search/Search';
import { LitTable } from '../../base-ui/table/lit-table';
import { HangStruct } from '../database/ui-worker/ProcedureWorkerHang';
import { SpAiAnalysisPage } from './SpAiAnalysisPage';
import { XpowerAppDetailStruct } from '../database/ui-worker/ProcedureWorkerXpowerAppDetail';
import { XpowerStatisticStruct } from '../database/ui-worker/ProcedureWorkerXpowerStatistic';
import { XpowerWifiStruct } from '../database/ui-worker/ProcedureWorkerXpowerWifi';
import { XpowerThreadInfoStruct } from '../database/ui-worker/ProcedureWorkerXpowerThreadInfo';
import { XpowerGpuFreqStruct } from '../database/ui-worker/ProcedureWorkerXpowerGpuFreq';
import { LitProgressBar } from '../../base-ui/progress-bar/LitProgressBar';
import { SnapShotStruct } from '../database/ui-worker/ProcedureWorkerSnaps';
import { ThreadSysCallStruct } from '../database/ui-worker/ProcedureWorkerThreadSysCall';
import { TabPaneFreqByCpu } from './trace/sheet/cpu/TanpaneFreqByCpu';
import { TabPaneSchedTaskByCpu } from './trace/sheet/cpu/TabPaneSchedTaskByCpu';
function dpr(): number {
return window.devicePixelRatio || 1;
}
export class CurrentSlicesTime {
startTime: number | undefined;
endTime: number | undefined;
}
type HTMLDivElementAlias = HTMLDivElement | undefined | null;
type FlagAlias = Flag | undefined | null;
type SlicesTimeAlias = SlicesTime | undefined | null;
@element('sp-system-trace')
export class SpSystemTrace extends BaseElement {
mouseCurrentPosition = 0;
offsetMouse = 0;
static isMouseLeftDown = false;
static scrollViewWidth = 0;
static isCanvasOffScreen = true;
static DATA_DICT: Map<number, string> = new Map<number, string>();
static DATA_TASK_POOL_CALLSTACK: Map<number, { id: number; ts: number; dur: number; name: string }> = new Map<
number,
{ id: number; ts: number; dur: number; name: string }
>();
static SDK_CONFIG_MAP: unknown;
static sliceRangeMark: unknown;
static wakeupList: Array<WakeupBean> = [];
static keyPathList: Array<CpuStruct> = [];
static keyboardFlar: Boolean = true;
static jsProfilerMap: Map<number, unknown> = new Map<number, unknown>();
times: Set<number> = new Set<number>();
currentSlicesTime: CurrentSlicesTime = new CurrentSlicesTime();
intersectionObserver: IntersectionObserver | undefined;
tipEL: HTMLDivElementAlias;
rowsEL: HTMLDivElementAlias;
rowsPaneEL: HTMLDivElementAlias;
stateRowsId: Array<object> = [];
spacerEL: HTMLDivElementAlias;
visibleRows: Array<TraceRow<unknown>> = [];
invisibleRows: Array<TraceRow<unknown>> = [];
collectRows: Array<TraceRow<unknown>> = [];
currentRow: TraceRow<unknown> | undefined | null;
copyCurrentRow: TraceRow<unknown> | undefined | null;
keyboardEnable = true;
mouseEventEnable = true;
currentRowType = '';
observerScrollHeightEnable: boolean = false;
observerScrollHeightCallback: Function | undefined;
favoriteChartListEL: SpChartList | undefined | null;
observer = new ResizeObserver((entries) => {
if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) {
this.observerScrollHeightCallback();
}
});
static btnTimer: unknown = null;
isMousePointInSheet = false;
hoverFlag: FlagAlias;
selectFlag: FlagAlias;
slicestime: SlicesTimeAlias;
public timerShaftEL: TimerShaftElement | null | undefined;
public traceSheetEL: TraceSheet | undefined | null;
public rangeSelect!: RangeSelect;
chartManager: SpChartManager | undefined | null;
loadTraceCompleted: boolean = false;
rangeTraceRow: Array<TraceRow<unknown>> | undefined = [];
canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined;
canvasPanel: HTMLCanvasElement | null | undefined;
canvasPanelCtx: CanvasRenderingContext2D | undefined | null;
linkNodes: PairPoint[][] = [];
public currentClickRow: HTMLDivElement | undefined | null;
private litTabs: LitTabs | undefined | null;
eventMap: unknown = {};
isSelectClick: boolean = false;
selectionParam: SelectionParam | undefined;
snapshotFiles: FileInfo | null | undefined;
tabCpuFreq: TabPaneFrequencySample | undefined | null;
tabSchedTaskByCpu: TabPaneSchedTaskByCpu | undefined | null;
tabFreqByCpu: TabPaneFreqByCpu | undefined | null;
tabCpuState: TabPaneCounterSample | undefined | null;
collapseAll: boolean = false;
currentCollectGroup: string = '1';
private _list: Array<SlicesTime> = [];
static isHiddenMenu: boolean = false;
expandRowList: Array<TraceRow<unknown>> = [];
_slicesList: Array<SlicesTime> = [];
_flagList: Array<unknown> = [];
static currentStartTime: number = 0;
static retargetIndex: number = 0;
prevScrollY: number = 0;
wakeupListTbl: LitTable | undefined | null;
_checkclick: boolean = false;
docomList: Array<number> = [];
repaintMap: Map<string,unknown> = new Map<string,unknown>();
presentMap: Map<string,unknown> = new Map<string,unknown>();
static isAiAsk: boolean = false;
collectEl1: HTMLDivElement | undefined | null;
collectEl2: HTMLDivElement | undefined | null;
groupTitle1: HTMLDivElement | undefined | null;
groupTitle2: HTMLDivElement | undefined | null;
isInSheet: boolean = false;
set snapshotFile(data: FileInfo) {
this.snapshotFiles = data;
}
set slicesList(list: Array<SlicesTime>) {
this._slicesList = list;
}
set flagList(list: Array<unknown>) {
this._flagList = list;
}
get checkclick(): boolean {
return this._checkclick;
}
set checkclick(value: boolean) {
if (value) {
this._checkclick = true;
} else {
this._checkclick = false;
}
}
throttle(fn: Function, t: number, ev?: unknown): Function {
let timerId: unknown = null;
return (): void => {
if (!timerId) {
timerId = setTimeout(function (): void {
if (ev) {
fn(ev);
} else {
fn();
}
timerId = null;
}, t);
this.times.add(timerId);
}
};
}
debounce(fn: Function, ms: number, ev?: unknown): Function {
let timerId: undefined | number;
return (): void => {
if (timerId) {
window.clearTimeout(timerId);
} else {
timerId = window.setTimeout((): void => {
if (ev) {
fn(ev);
} else {
fn();
}
timerId = undefined;
}, ms);
this.times.add(timerId);
}
};
}
addPointPair(startPoint: PairPoint, endPoint: PairPoint, lineType?: string): void {
if (startPoint !== null && startPoint.rowEL !== null && endPoint !== null && endPoint.rowEL !== null) {
const LinkNodes: PairPoint[][] = [];
LinkNodes.push([startPoint, endPoint]);
startPoint.sourceOffsetY = startPoint.offsetY;
endPoint.sourceOffsetY = endPoint.offsetY;
startPoint.offsetY = startPoint.rowEL.funcExpand ? startPoint.sourceOffsetY : startPoint.rowEL._frame!.height;
endPoint.offsetY = endPoint.rowEL.funcExpand ? endPoint.sourceOffsetY : endPoint.rowEL._frame!.height;
this.handleCollectFunc(LinkNodes);
startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY;
endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY;
startPoint.backrowEL = startPoint.rowEL;
endPoint.backrowEL = endPoint.rowEL;
startPoint.sourcebackrowEL = startPoint.rowEL;
endPoint.sourcebackrowEL = endPoint.rowEL;
if (!lineType) {
this.linkNodes.push([startPoint, endPoint]);
} else {
if (startPoint.rangeTime) {
this.linkNodes.push([startPoint, endPoint]);
}
}
this.refreshCanvas(true);
}
}
clearPointPair(): void {
this.linkNodes.length = 0;
}
removeLinkLinesByBusinessType(...businessTypes: string[]): void {
this.linkNodes = this.linkNodes.filter((pointPair) => {
if (businessTypes.indexOf('distributed') >= 0) {
FuncStruct.selectLineFuncStruct = [];
}
return businessTypes.indexOf(pointPair[0].business) <= -1;
});
}
hiddenLinkLinesByBusinessType(...businessTypes: string[]): void {
this.linkNodes.map((value) => {
if (businessTypes.indexOf(value[0].business) !== -1) {
value[0].hidden = true;
value[1].hidden = true;
}
});
}
showLinkLinesByBusinessType(...businessTypes: string[]): void {
this.linkNodes.map((value) => {
if (businessTypes.indexOf(value[0].business) !== -1) {
value[0].hidden = false;
value[1].hidden = false;
}
});
}
initElements(): void {
spSystemTraceInitElement(this);
}
clearTriangle(flagList: Array<Flag>): void {
this.timerShaftEL!.sportRuler!.times = [];
for (let i = 0; i < flagList.length; i++) {
if (flagList[i].type === 'triangle') {
flagList.splice(i, 1);
this.timerShaftELFlagChange(this.hoverFlag, null);
i--;
}
}
}
pushPidToSelection(selection: SelectionParam, id: string, originalId?: string | Array<string>): void {
let add = (it: string): void => {
let pid = parseInt(it ? it : id);
if (!isNaN(pid!)) {
if (!selection.processIds.includes(pid!)) {
selection.processIds.push(pid!);
}
}
};
if (Array.isArray(originalId)) {
originalId.forEach(item => {
add(item);
});
} else {
add(originalId!);
}
}
getCollectRows(condition: (row: TraceRow<unknown>) => boolean): Array<TraceRow<unknown>> {
return this.favoriteChartListEL!.getCollectRows(condition);
}
createPointEvent(it: TraceRow<unknown>): unknown {
let event = this.eventMap[`${it.rowType}`];
if (event) {
return event;
} else {
if (it.rowType === TraceRow.ROW_TYPE_HEAP) {
event = it.name;
} else if (it.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) {
event = 'HiPerf Cpu';
if (it.rowId === 'HiPerf-cpu-merge') {
event = 'HiPerf';
}
} else if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) {
event = this.handleFileSystemType(it, event);
} else if (it.rowType === TraceRow.ROW_TYPE_STATE_ENERGY) {
event = it.name;
} else if (it.rowType === TraceRow.ROW_TYPE_VM_TRACKER) {
if (it.rowParentId === '') {
event = 'VM Tracker';
} else {
event = it.name;
}
} else if (it.rowType === TraceRow.ROW_TYPE_JANK) {
if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') {
event = 'FrameTimeLine';
} else if (it.hasAttribute('frame_type')) {
event = `${it.getAttribute('frame_type')}`;
}
} else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
event = 'DeliverInputEvent';
if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
event = 'DeliverInputEvent Func';
}
} else if (it.rowType === TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH) {
event = 'TouchEventDispatch';
if (it.rowParentId === TraceRow.ROW_TYPE_TOUCH_EVENT_DISPATCH) {
event = 'TouchEventDispatch Func';
}
} else {
event = it.name;
}
return event;
}
}
private handleFileSystemType(it: TraceRow<unknown>, event: unknown): void {
if (it.rowId === 'FileSystemLogicalWrite') {
event = 'FileSystem Logical Write';
} else if (it.rowId === 'FileSystemLogicalRead') {
event = 'FileSystem Logical Read';
} else if (it.rowId === 'FileSystemVirtualMemory') {
event = 'Page Fault Trace';
} else if (it.rowId!.startsWith('FileSystemDiskIOLatency')) {
event = 'Disk I/O Latency';
if (it.rowId!.startsWith('FileSystemDiskIOLatency-')) {
event = 'Bio Process';
}
}
return event;
}
refreshFavoriteCanvas(): void {
this.favoriteChartListEL!.refreshFavoriteCanvas();
}
expansionAllParentRow(currentRow: TraceRow<unknown>): void {
let parentRow = this.rowsEL!.querySelector<TraceRow<unknown>>(
`trace-row[row-id='${currentRow.rowParentId}'][folder][scene]`
);
if (parentRow) {
parentRow.expansion = true;
if (this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)) {
this.expansionAllParentRow(parentRow);
}
}
}
canvasPanelConfig(): void {
this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`;
this.canvasPanel!.width = this.canvasPanel!.offsetWidth * dpr();
this.canvasPanel!.height = this.canvasPanel!.offsetHeight * dpr();
this.canvasPanelCtx!.scale(dpr(), dpr());
}
getScrollWidth(): number {
let overflowDiv = document.createElement('div');
overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;';
let totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth;
overflowDiv.style.overflowY = 'scroll';
let scrollDiv = overflowDiv.clientWidth;
document.body.removeChild(overflowDiv);
return totalScrollDiv - scrollDiv;
}
getShowTab(): Array<string> {
let tabpane = this.traceSheetEL!.shadowRoot!.querySelectorAll('lit-tabpane') as NodeListOf<LitTabpane>;
let showTab: Array<string> = [];
for (let pane of tabpane) {
if (pane.getAttribute('hidden') === 'false') {
showTab.push(pane.getAttribute('id') || '');
}
}
return showTab;
}
timerShaftELFlagClickHandler = (flag: FlagAlias): void => {
if (flag) {
setTimeout(() => {
if (TraceRow.rangeSelectObject) {
let showTab = this.getShowTab();
this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag', ...showTab).setCurrentFlag(flag);
} else {
this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flag);
}
}, 100);
}
};
timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias): void => {
this.hoverFlag = hoverFlag;
this.selectFlag = selectFlag;
this.refreshCanvas(true, 'flagChange');
};
timerShaftELRangeClick = (sliceTime: SlicesTimeAlias): void => {
if (sliceTime) {
setTimeout(() => {
if (TraceRow.rangeSelectObject) {
let showTab = this.getShowTab();
this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current', ...showTab).setCurrentSlicesTime(sliceTime);
} else {
this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(sliceTime);
}
}, 0);
}
};
timerShaftELRangeChange = (e: unknown): void => {
TraceRow.range = e;
if (TraceRow.rangeSelectObject) {
TraceRow.rangeSelectObject!.startX = Math.floor(
ns2x(
TraceRow.rangeSelectObject!.startNS!,
TraceRow.range?.startNS!,
TraceRow.range?.endNS!,
TraceRow.range?.totalNS!,
this.timerShaftEL!.sportRuler!.frame
)
);
TraceRow.rangeSelectObject!.endX = Math.floor(
ns2x(
TraceRow.rangeSelectObject!.endNS!,
TraceRow.range?.startNS!,
TraceRow.range?.endNS!,
TraceRow.range?.totalNS!,
this.timerShaftEL!.sportRuler!.frame
)
);
}
if (!TraceRow.rangeSelectObject) {
SpAiAnalysisPage.selectChangeListener(TraceRow.range?.startNS!, TraceRow.range?.endNS!);
}
this.linkNodes.forEach((it) => {
it[0].x = ns2xByTimeShaft(it[0].ns, this.timerShaftEL!);
it[1].x = ns2xByTimeShaft(it[1].ns, this.timerShaftEL!);
});
this.invisibleRows.forEach((it) => (it.needRefresh = true));
this.visibleRows.forEach((it) => (it.needRefresh = true));
this.refreshCanvas(false, 'rangeChange');
};
isSlectStruct(): unknown {
return CpuStruct.selectCpuStruct ||
CpuStruct.wakeupBean ||
CpuFreqStruct.selectCpuFreqStruct ||
ThreadStruct.selectThreadStruct ||
ThreadStruct.isClickPrio ||
FuncStruct.selectFuncStruct ||
SpHiPerf.selectCpuStruct ||
CpuStateStruct.selectStateStruct ||
CpuFreqLimitsStruct.selectCpuFreqLimitsStruct ||
ClockStruct.selectClockStruct ||
IrqStruct.selectIrqStruct ||
JankStruct.selectJankStruct ||
HeapStruct.selectHeapStruct ||
AppStartupStruct.selectStartupStruct ||
SoStruct.selectSoStruct ||
HeapSnapshotStruct.selectSnapshotStruct ||
FrameSpacingStruct.selectFrameSpacingStruct ||
FrameAnimationStruct.selectFrameAnimationStruct ||
FrameDynamicStruct.selectFrameDynamicStruct ||
JsCpuProfilerStruct.selectJsCpuProfilerStruct ||
SnapshotStruct.selectSnapshotStruct ||
HiPerfCallChartStruct.selectStruct ||
AllAppStartupStruct.selectStartupStruct ||
LtpoStruct.selectLtpoStruct ||
HitchTimeStruct.selectHitchTimeStruct ||
SampleStruct.selectSampleStruct ||
PerfToolStruct.selectPerfToolStruct ||
GpuCounterStruct.selectGpuCounterStruct ||
DmaFenceStruct.selectDmaFenceStruct ||
XpowerThreadInfoStruct.selectXpowerStruct ||
XpowerGpuFreqStruct.selectXpowerStruct ||
SnapShotStruct.selectSnapShotStruct ||
IOStruct.selectIOStruct;
}
top: number = 0;
handler: number = -1;
rowsElOnScroll = (e: unknown): void => {
this.rangeSelect.isMouseDown = false;
const currentScrollY = e.target.scrollTop;
const deltaY = currentScrollY - this.prevScrollY;
this.handleCollectFunc(this.linkNodes);
this.hoverStructNull();
if (this.scrollTimer) {
clearTimeout(this.scrollTimer);
}
this.scrollTimer = setTimeout(() => {
TraceRow.range!.refresh = true;
requestAnimationFrame(() => this.refreshCanvas(false));
}, 200);
spSystemTraceParentRowSticky(this, deltaY);
this.prevScrollY = currentScrollY;
};
handleCollectFunc(linkNodes: PairPoint[][]): void {
let margin = this.timerShaftEL?._checkExpand ? this.timerShaftEL!._usageFoldHeight! - 195 : 0 - 195;
linkNodes.forEach((itln) => {
if (itln[0].rowEL.collect) {
if (itln[1].rowEL.collect) {
if (itln[0].rowEL.collectGroup === itln[1].rowEL.collectGroup && itln[1].rowEL.collectGroup === '1') {
if (this.favoriteChartListEL?.collect1Expand) {
itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top + margin;
itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top + margin;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].sourceOffsetY! : itln[0].rowEL._frame!.height - 5;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].sourceOffsetY! : itln[1].rowEL._frame!.height - 5;
} else {
itln[0].rowEL.translateY = this.groupTitle1!.getBoundingClientRect().top + margin;
itln[1].rowEL.translateY = this.groupTitle1!.getBoundingClientRect().top + margin;
itln[0].offsetY = this.groupTitle1!.offsetHeight / 2;
itln[1].offsetY = this.groupTitle1!.offsetHeight / 2;
}
} else if (itln[0].rowEL.collectGroup === itln[1].rowEL.collectGroup && itln[1].rowEL.collectGroup === '2') {
if (this.favoriteChartListEL?.collect2Expand) {
itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top + margin;
itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top + margin;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].sourceOffsetY! : itln[0].rowEL._frame!.height - 5;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].sourceOffsetY! : itln[1].rowEL._frame!.height - 5;
} else {
itln[0].rowEL.translateY = this.groupTitle2!.getBoundingClientRect().top + margin;
itln[1].rowEL.translateY = this.groupTitle2!.getBoundingClientRect().top + margin;
itln[0].offsetY = this.groupTitle2!.offsetHeight / 2;
itln[1].offsetY = this.groupTitle2!.offsetHeight / 2;
}
} else if (itln[0].rowEL.collectGroup === '1' && itln[1].rowEL.collectGroup === '2') {
if (this.favoriteChartListEL?.collect1Expand) {
itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top + margin;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].sourceOffsetY! : itln[0].rowEL._frame!.height - 5;
} else {
itln[0].rowEL.translateY = this.groupTitle1!.getBoundingClientRect().top + margin;
itln[0].offsetY = this.groupTitle1!.offsetHeight / 2;
}
if (this.favoriteChartListEL?.collect2Expand) {
itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top + margin;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].sourceOffsetY! : itln[1].rowEL._frame!.height - 5;
} else {
itln[1].rowEL.translateY = this.groupTitle2!.getBoundingClientRect().top + margin;
itln[1].offsetY = this.groupTitle2!.offsetHeight / 2;
}
} else if (itln[0].rowEL.collectGroup === '2' && itln[1].rowEL.collectGroup === '1') {
if (this.favoriteChartListEL?.collect1Expand) {
itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top + margin;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].sourceOffsetY! : itln[1].rowEL._frame!.height - 5;
} else {
itln[1].rowEL.translateY = this.groupTitle1!.getBoundingClientRect().top + margin;
itln[1].offsetY = this.groupTitle1!.offsetHeight / 2;
}
if (this.favoriteChartListEL?.collect2Expand) {
itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top + margin;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].sourceOffsetY! : itln[0].rowEL._frame!.height - 5;
} else {
itln[0].rowEL.translateY = this.groupTitle2!.getBoundingClientRect().top + margin;
itln[0].offsetY = this.groupTitle2!.offsetHeight / 2;
}
}
} else {
itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].offsetY! : itln[1].rowEL._frame!.height - 5;
if (itln[0].rowEL.collectGroup === '1') {
if (this.favoriteChartListEL?.collect1Expand) {
itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top + margin;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].sourceOffsetY! : itln[0].rowEL._frame!.height - 5;
} else {
itln[0].rowEL.translateY = this.groupTitle1!.getBoundingClientRect().top + margin;
itln[0].offsetY = this.groupTitle1!.offsetHeight / 2;
}
} else {
if (this.favoriteChartListEL?.collect2Expand) {
itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top + margin;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].sourceOffsetY! : itln[0].rowEL._frame!.height - 5;
} else {
itln[0].rowEL.translateY = this.groupTitle2!.getBoundingClientRect().top + margin;
itln[0].offsetY = this.groupTitle2!.offsetHeight / 2;
}
}
}
} else {
itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
itln[0].offsetY = itln[0].rowEL.funcExpand ? itln[0].offsetY! : itln[0].rowEL._frame!.height - 5;
if (itln[1].rowEL.collect) {
if (itln[1].rowEL.collectGroup === '1') {
if (this.favoriteChartListEL?.collect1Expand) {
itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top + margin;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].sourceOffsetY! : itln[1].rowEL._frame!.height - 5;
} else {
itln[1].rowEL.translateY = this.groupTitle1!.getBoundingClientRect().top + margin;
itln[1].offsetY = this.groupTitle1!.offsetHeight / 2;
}
} else {
if (this.favoriteChartListEL?.collect2Expand) {
itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top + margin;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].sourceOffsetY! : itln[1].rowEL._frame!.height - 5;
} else {
itln[1].rowEL.translateY = this.groupTitle2!.getBoundingClientRect().top + margin;
itln[1].offsetY = this.groupTitle2!.offsetHeight / 2;
}
}
} else {
itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
itln[1].offsetY = itln[1].rowEL.funcExpand ? itln[1].offsetY! : itln[1].rowEL._frame!.height - 5;
}
}
itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
});
}
private scrollTimer: unknown;
favoriteRowsElOnScroll = (e: unknown): void => {
this.rowsElOnScroll(e);
};
offset = 147;
getRowsContentHeight(): number {
return [...this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row:not([sleeping])')]
.map((it) => it.clientHeight)
.reduce((acr, cur) => acr + cur, 0);
}
refreshCanvas(cache: boolean, from?: string): void {
if (this.visibleRows.length === 0) {
return;
}
this.canvasPanelCtx!.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight);
this.favoriteChartListEL!.clearRect();
let rowsContentHeight = this.getRowsContentHeight();
let canvasHeight =
rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight;
drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor());
this.favoriteChartListEL?.drawLines(TraceRow.range?.xs, this.timerShaftEL!.lineColor());
this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`;
this.visibleRows.forEach((v, i) => {
if (v.collect) {
v.translateY =
v.getBoundingClientRect().top -
this.timerShaftEL?.clientHeight! -
this.parentElement!.previousElementSibling!.clientHeight -
1;
} else {
v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop;
}
v.draw(cache);
});
this.drawAllLines();
}
drawWakeUpLine(): void {
drawWakeUp(
this.canvasPanelCtx,
CpuStruct.wakeupBean,
TraceRow.range!.startNS,
TraceRow.range!.endNS,
TraceRow.range!.totalNS,
{
x: 0,
y: 0,
width: TraceRow.FRAME_WIDTH,
height: this.canvasPanel!.clientHeight!,
} as Rect
);
this.favoriteChartListEL?.drawWakeUp();
for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) {
if (i + 1 === SpSystemTrace.wakeupList.length) {
return;
}
drawWakeUpList(
this.canvasPanelCtx,
SpSystemTrace.wakeupList[i + 1],
TraceRow.range!.startNS,
TraceRow.range!.endNS,
TraceRow.range!.totalNS,
{
x: 0,
y: 0,
width: this.timerShaftEL!.canvas!.clientWidth,
height: this.canvasPanel!.clientHeight!,
} as Rect
);
this.favoriteChartListEL?.drawWakeUpList(SpSystemTrace.wakeupList[i + 1]);
}
}
drawAllLines(): void {
drawFlagLineSegment(
this.canvasPanelCtx,
this.hoverFlag,
this.selectFlag,
{
x: 0,
y: 0,
width: this.timerShaftEL?.canvas?.clientWidth,
height: this.canvasPanel?.clientHeight,
} as Rect,
this.timerShaftEL!
);
this.favoriteChartListEL?.drawFlagLineSegment(this.hoverFlag, this.selectFlag, this.timerShaftEL!);
this.drawWakeUpLine();
drawLogsLineSegment(
this.canvasPanelCtx,
this.traceSheetEL?.systemLogFlag,
{
x: 0,
y: 0,
width: this.timerShaftEL?.canvas?.clientWidth,
height: this.canvasPanel?.clientHeight,
},
this.timerShaftEL!
);
this.favoriteChartListEL?.drawLogsLineSegment(this.traceSheetEL!.systemLogFlag, this.timerShaftEL!);
if (this.linkNodes && this.linkNodes.length > 0) {
drawLinkLines(
this.canvasPanelCtx!,
this.linkNodes,
this.timerShaftEL!,
false,
this.favoriteChartListEL!.clientHeight
);
this.favoriteChartListEL?.drawLinkLines(
this.linkNodes,
this.timerShaftEL!,
true,
this.favoriteChartListEL!.clientHeight
);
}
if (
ThreadStruct.isClickPrio &&
this.currentRow!.parentRowEl!.expansion &&
ThreadStruct.selectThreadStruct &&
ThreadStruct.contrast(ThreadStruct.selectThreadStruct, this.currentRow!.rowParentId, this.currentRow!.rowId)
) {
let context: CanvasRenderingContext2D;
if (this.currentRow!.currentContext) {
context = this.currentRow!.currentContext;
} else {
context = this.currentRow!.collect ? this.canvasFavoritePanelCtx! : this.canvasPanelCtx!;
}
this.drawPrioCurve(context, this.currentRow!);
}
}
drawPrioCurve(context: unknown, row: TraceRow<unknown>): void {
let curveDrawList: unknown = [];
let oldVal: number = -1;
let threadFilter = row.dataListCache.filter((it: unknown) => it.state === 'Running');
prioClickHandlerFun(ThreadStruct.prioCount, row, threadFilter, curveDrawList, oldVal);
context.globalAlpha = 1;
context.beginPath();
let x0;
let y0;
if (curveDrawList[0] && curveDrawList[0].frame) {
x0 = curveDrawList[0].frame.x;
y0 = curveDrawList[0].curveFloatY;
}
context!.moveTo(x0!, y0!);
if (curveDrawList.length < 90) {
for (let i = 0; i < curveDrawList.length - 1; i++) {
let re = curveDrawList[i];
let nextRe = curveDrawList[i + 1];
drawThreadCurve(context, re, nextRe);
}
context.closePath();
} else if (curveDrawList.length >= 90) {
let x;
let y;
if (curveDrawList[curveDrawList.length - 1] && curveDrawList[curveDrawList.length - 1].frame) {
x = curveDrawList[curveDrawList.length - 1].frame.x;
y = curveDrawList[curveDrawList.length - 1].curveFloatY;
}
context.lineWidth = 1;
context.strokeStyle = '#ffc90e';
context.lineCap = 'round';
context.lineTo(x, y);
context.stroke();
}
}
documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev);
onContextMenuHandler = (e: Event): void => {
setTimeout(() => {
for (let key of this.keyPressMap.keys()) {
if (this.keyPressMap.get(key)) {
this.timerShaftEL?.stopWASD({ key: key });
this.keyPressMap.set(key, false);
}
}
}, 100);
};
documentOnMouseUp = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseUp(this, ev);
cancelDrag(): void {
this.rangeSelect.drag = false;
this.rangeSelect.isMouseDown = false;
TraceRow.rangeSelectObject = {
startX: 0,
endX: 0,
startNS: 0,
endNS: 0,
};
}
documentOnMouseOut = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseOut(this, ev);
documentOnPointercancel = (ev: any): void => {
if (ev.pointerType == 'mouse') {
this.dispatchEvent(
new CustomEvent('abnormal-mouseup', {
detail: {
value: true,
},
})
);
}
};
keyPressMap: Map<string, boolean> = new Map([
['w', false],
['s', false],
['a', false],
['d', false],
['f', false],
]);
documentOnKeyDown = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyDown(this, ev);
documentOnKeyPress = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyPress(this, ev);
verticalScrollToRow(): void {
if (this.currentRow && !this.currentRow.folder) {
this.currentRow.scrollIntoViewIfNeeded();
}
}
setCurrentSlicesTime(): void {
if (CpuStruct.selectCpuStruct) {
this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime;
this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime! + CpuStruct.selectCpuStruct.dur!;
} else if (ThreadStruct.selectThreadStruct) {
this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime;
this.currentSlicesTime.endTime =
ThreadStruct.selectThreadStruct.startTime! + ThreadStruct.selectThreadStruct.dur!;
} else if (FuncStruct.selectFuncStruct) {
this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs;
this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs! + FuncStruct.selectFuncStruct.dur!;
} else if (IrqStruct.selectIrqStruct) {
this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS;
this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS! + IrqStruct.selectIrqStruct.dur!;
} else if (TraceRow.rangeSelectObject) {
this.currentRow = undefined;
if (TraceRow.rangeSelectObject.startNS && TraceRow.rangeSelectObject.endNS) {
this.currentSlicesTime.startTime = TraceRow.rangeSelectObject.startNS;
this.currentSlicesTime.endTime = TraceRow.rangeSelectObject.endNS;
}
} else if (JankStruct.selectJankStruct) {
this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts;
this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts! + JankStruct.selectJankStruct.dur!;
} else if (SampleStruct.selectSampleStruct) {
if (SampleStruct.selectSampleStruct.begin && SampleStruct.selectSampleStruct.end) {
this.currentSlicesTime.startTime =
SampleStruct.selectSampleStruct.begin - SampleStruct.selectSampleStruct.startTs!;
this.currentSlicesTime.endTime = SampleStruct.selectSampleStruct.end - SampleStruct.selectSampleStruct.startTs!;
}
} else if (GpuCounterStruct.selectGpuCounterStruct) {
this.currentSlicesTime.startTime =
GpuCounterStruct.selectGpuCounterStruct.startNS! - GpuCounterStruct.selectGpuCounterStruct.startTime!;
this.currentSlicesTime.endTime =
GpuCounterStruct.selectGpuCounterStruct.startNS! +
GpuCounterStruct.selectGpuCounterStruct.dur! -
GpuCounterStruct.selectGpuCounterStruct.startTime!;
} else if (AppStartupStruct.selectStartupStruct) {
this.currentSlicesTime.startTime = AppStartupStruct.selectStartupStruct.startTs;
this.currentSlicesTime.endTime = AppStartupStruct.selectStartupStruct.startTs! + AppStartupStruct.selectStartupStruct.dur!;
} else if (AllAppStartupStruct.selectStartupStruct) {
this.currentSlicesTime.startTime = AllAppStartupStruct.selectStartupStruct.startTs;
this.currentSlicesTime.endTime = AllAppStartupStruct.selectStartupStruct.startTs! + AllAppStartupStruct.selectStartupStruct.dur!;
} else if (PerfToolStruct.selectPerfToolStruct) {
this.currentSlicesTime.startTime = PerfToolStruct.selectPerfToolStruct.startTs;
this.currentSlicesTime.endTime = PerfToolStruct.selectPerfToolStruct.startTs! + PerfToolStruct.selectPerfToolStruct.dur!;
} else if (DmaFenceStruct.selectDmaFenceStruct) {
if (DmaFenceStruct.selectDmaFenceStruct.startTime && DmaFenceStruct.selectDmaFenceStruct.dur) {
this.currentSlicesTime.startTime = DmaFenceStruct.selectDmaFenceStruct.startTime;
this.currentSlicesTime.endTime = DmaFenceStruct.selectDmaFenceStruct.startTime + DmaFenceStruct.selectDmaFenceStruct.dur;
}
} else if (HangStruct.selectHangStruct) {
this.currentSlicesTime.startTime = HangStruct.selectHangStruct.startTime;
this.currentSlicesTime.endTime = HangStruct.selectHangStruct.startTime! + HangStruct.selectHangStruct.dur!;
} else if (IOStruct.selectIOStruct) {
this.currentSlicesTime.startTime = IOStruct.selectIOStruct.startNS;
this.currentSlicesTime.endTime = IOStruct.selectIOStruct.startNS! + IOStruct.selectIOStruct.dur!;
} else {
this.currentSlicesTime.startTime = 0;
this.currentSlicesTime.endTime = 0;
}
}
public setSLiceMark = (shiftKey: boolean): SlicesTime | null | undefined => {
const selectedStruct: unknown =
CpuStruct.selectCpuStruct ||
ThreadStruct.selectThreadStruct ||
TraceRow.rangeSelectObject ||
FuncStruct.selectFuncStruct ||
IrqStruct.selectIrqStruct ||
JankStruct.selectJankStruct ||
AppStartupStruct.selectStartupStruct ||
SoStruct.selectSoStruct ||
SampleStruct.selectSampleStruct ||
GpuCounterStruct.selectGpuCounterStruct ||
AllAppStartupStruct.selectStartupStruct ||
FrameAnimationStruct.selectFrameAnimationStruct ||
JsCpuProfilerStruct.selectJsCpuProfilerStruct ||
PerfToolStruct.selectPerfToolStruct ||
DmaFenceStruct.selectDmaFenceStruct ||
HangStruct.selectHangStruct ||
IOStruct.selectIOStruct;
this.calculateSlicesTime(selectedStruct, shiftKey);
return this.slicestime;
};
private calculateSlicesTime(selected: unknown, shiftKey: boolean): void {
if (selected) {
let startTs = 0;
if (selected.begin && selected.end) {
startTs = selected.begin - selected.startTs;
let end = selected.end - selected.startTs;
this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey);
} else if (selected.startNS && selected.dur) {
startTs = selected.startNS - selected.startTime;
let end = selected.startNS + selected.dur - selected.startTime;
this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey);
} else {
startTs = selected.startTs || selected.startTime || selected.startNS || selected.ts || 0;
let dur = selected.dur || selected.totalTime || selected.endNS - selected.startNS || 0;
this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey);
}
} else {
this.slicestime = this.timerShaftEL?.setSlicesMark();
}
}
stopWASD = (): void => {
setTimeout((): void => {
for (let key of this.keyPressMap.keys()) {
if (this.keyPressMap.get(key)) {
this.timerShaftEL?.stopWASD({ key: key });
this.keyPressMap.set(key, false);
}
}
}, 100);
};
continueSearch = (ev: KeyboardEvent): void => {
if (!this.keyboardEnable) {
return;
}
if (ev.key === 'Enter') {
if (ev.shiftKey) {
this.dispatchEvent(
new CustomEvent('trace-previous-data', {
detail: { down: true },
composed: false,
})
);
} else {
this.dispatchEvent(
new CustomEvent('trace-next-data', {
detail: { down: true },
composed: false,
})
);
}
}
};
documentOnKeyUp = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyUp(this, ev);
* 根据传入的参数实现卡尺和旗子的快捷跳转
* @param list 要跳转的数组
* @param type 标记类型(卡尺和旗子)
* @param direction 跳转方向(前一个/后一个)
*/
MarkJump(list: Array<unknown>, type: string, direction: string, ev: KeyboardEvent): void {
this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet');
let find = list.find((it) => it.selected);
if (!find) {
list.forEach((it) => (it.selected = false));
this.ifSliceInView(list[0], type, ev);
list[0].selected = true;
} else {
for (let i = 0; i < list.length; i++) {
if (list[i].selected) {
list[i].selected = false;
if (direction === 'previous') {
if (i === 0) {
this.ifSliceInView(list[list.length - 1], type, ev);
list[list.length - 1].selected = true;
break;
} else {
this.ifSliceInView(list[i - 1], type, ev);
list[i - 1].selected = true;
break;
}
} else if (direction === 'next') {
if (i === list.length - 1) {
this.ifSliceInView(list[0], type, ev);
list[0].selected = true;
break;
} else {
this.ifSliceInView(list[i + 1], type, ev);
list[i + 1].selected = true;
break;
}
}
}
}
}
if (type === 'flag') {
let currentPane = this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag');
list.forEach((flag, index) => {
this.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type);
if (flag.selected) {
currentPane!.setTableSelection(index + 1);
}
});
} else if (type === 'slice') {
this.refreshCanvas(true);
let currentPane = this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current');
list.forEach((slice, index) => {
if (slice.selected) {
currentPane!.setTableSelection(index + 1);
}
});
}
}
ifSliceInView(data: unknown, type: string, ev: KeyboardEvent): void {
let timeRangeEndNS = this.timerShaftEL?.getRangeRuler()?.range.endNS;
let timeRangeStartNS = this.timerShaftEL?.getRangeRuler()?.range.startNS;
if (type === 'flag') {
data.startTime = data.time;
data.endTime = data.time;
}
let endTime = data.endTime;
let startTime = data.startTime;
if (endTime > timeRangeEndNS! || startTime < timeRangeStartNS!) {
this.timerShaftEL!.documentOnKeyPress(ev, data);
setTimeout(() => {
this.timerShaftEL!.documentOnKeyUp(ev);
}, 1000);
}
}
isMouseInSheet = (ev: MouseEvent): boolean => {
this.isMousePointInSheet =
this.traceSheetEL?.getAttribute('mode') !== 'hidden' &&
ev.offsetX > this.traceSheetEL!.offsetLeft &&
ev.offsetY > this.traceSheetEL!.offsetTop;
return this.isMousePointInSheet;
};
favoriteChangeHandler = (row: TraceRow<unknown>): void => {
info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight);
};
* 根据选择的traceRow 处理foler
* @param currentRow 当前点击checkbox的row
*/
setParentCheckStatus(currentRow: TraceRow<unknown>): void {
if (currentRow.parentRowEl?.folder && currentRow.parentRowEl?.childrenList) {
const parent = currentRow.parentRowEl;
const childrenList = parent.childrenList;
const selectList = [];
const unSelectList = [];
for (const child of childrenList) {
if (child.checkType === '2') {
selectList.push(child);
} else {
unSelectList.push(child);
}
}
if (unSelectList.length === 0) {
parent.setAttribute('check-type', '2');
parent.rangeSelect = true;
parent.checkBoxEL!.checked = true;
parent.checkBoxEL!.indeterminate = false;
} else if (selectList.length === 0) {
parent.setAttribute('check-type', '0');
parent.rangeSelect = false;
parent.checkBoxEL!.checked = false;
parent.checkBoxEL!.indeterminate = false;
} else {
parent.setAttribute('check-type', '1');
parent.rangeSelect = false;
parent.checkBoxEL!.checked = false;
parent.checkBoxEL!.indeterminate = true;
}
}
}
* 处理点击checkbox的逻辑
* @param row 当前点击checkbox的row
*/
selectChangeHandler = (row: TraceRow<unknown>): void => {
this.setParentCheckStatus(row);
const foldSelectParentRowList: Array<TraceRow<unknown>> = this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[check-type='1']");
const foldSelectRowList: Array<TraceRow<unknown>> = [];
foldSelectParentRowList.length && foldSelectParentRowList.forEach((item) => item.childrenList.filter((child: { checkType: string }) => child!.checkType === '2' && foldSelectRowList.push(child)));
const rows = [
...foldSelectRowList,
...this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[check-type='2']"),
...this.favoriteChartListEL!.getAllSelectCollectRows(),
];
this.isSelectClick = true;
this.rangeSelect.rangeTraceRow = rows;
this.rangeSelect.checkRowsName(this.rangeSelect.rangeTraceRow);
let changeTraceRows: Array<TraceRow<unknown>> = [];
if (this.rangeTraceRow!.length < rows.length) {
rows!.forEach((currentTraceRow: TraceRow<unknown>) => {
let changeFilter = this.rangeTraceRow!.filter(
(prevTraceRow: TraceRow<unknown>) => prevTraceRow === currentTraceRow
);
if (changeFilter.length < 1) {
changeTraceRows.push(currentTraceRow);
}
});
if (changeTraceRows.length > 0) {
changeTraceRows!.forEach((changeTraceRow: TraceRow<unknown>) => {
let pointEvent = this.createPointEvent(changeTraceRow);
SpStatisticsHttpUtil.addOrdinaryVisitAction({
action: 'trace_row',
event: pointEvent,
});
});
}
}
this.rangeTraceRow = rows;
let search = document.querySelector('body > sp-application')!.shadowRoot!.querySelector<LitSearch>('#lit-search');
if (search?.isClearValue) {
spSystemTraceDocumentOnMouseMoveMouseDown(this, search!);
}
this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false);
};
inFavoriteArea: boolean | undefined;
documentOnMouseMove = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseMove(this, ev);
hoverStructNull(): SpSystemTrace {
CpuStruct.hoverCpuStruct = undefined;
CpuFreqStruct.hoverCpuFreqStruct = undefined;
ThreadStruct.hoverThreadStruct = undefined;
ThreadSysCallStruct.hoverStruct = undefined;
FuncStruct.hoverFuncStruct = undefined;
ProcessMemStruct.hoverProcessMemStruct = undefined;
HiPerfCpuStruct.hoverStruct = undefined;
HiPerfProcessStruct.hoverStruct = undefined;
HiPerfThreadStruct.hoverStruct = undefined;
HiPerfEventStruct.hoverStruct = undefined;
HiPerfReportStruct.hoverStruct = undefined;
CpuStateStruct.hoverStateStruct = undefined;
CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined;
DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined;
MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined;
NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined;
CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined;
FpsStruct.hoverFpsStruct = undefined;
ClockStruct.hoverClockStruct = undefined;
IrqStruct.hoverIrqStruct = undefined;
HeapStruct.hoverHeapStruct = undefined;
JankStruct.hoverJankStruct = undefined;
AppStartupStruct.hoverStartupStruct = undefined;
SoStruct.hoverSoStruct = undefined;
HeapSnapshotStruct.hoverSnapshotStruct = undefined;
FrameAnimationStruct.hoverFrameAnimationStruct = undefined;
FrameDynamicStruct.hoverFrameDynamicStruct = undefined;
FrameSpacingStruct.hoverFrameSpacingStruct = undefined;
JsCpuProfilerStruct.hoverJsCpuProfilerStruct = undefined;
SnapshotStruct.hoverSnapshotStruct = undefined;
HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined;
SampleStruct.hoverSampleStruct = undefined;
PerfToolStruct.hoverPerfToolStruct = undefined;
GpuCounterStruct.hoverGpuCounterStruct = undefined;
DmaFenceStruct.hoverDmaFenceStruct = undefined;
SnapShotStruct.hoverSnapShotStruct = undefined;
IOStruct.hoverIOStruct = null;
this.tipEL!.style.display = 'none';
return this;
}
selectStructNull(): SpSystemTrace {
CpuStruct.selectCpuStruct = undefined;
CpuStruct.wakeupBean = null;
CpuFreqStruct.selectCpuFreqStruct = undefined;
ThreadStruct.selectThreadStruct = undefined;
ThreadStruct.isClickPrio = false;
ThreadSysCallStruct.selectStruct = undefined;
FuncStruct.selectFuncStruct = undefined;
SpHiPerf.selectCpuStruct = undefined;
CpuStateStruct.selectStateStruct = undefined;
CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined;
ClockStruct.selectClockStruct = undefined;
HangStruct.selectHangStruct = undefined;
IrqStruct.selectIrqStruct = undefined;
JankStruct.selectJankStruct = undefined;
HeapStruct.selectHeapStruct = undefined;
AppStartupStruct.selectStartupStruct = undefined;
SoStruct.selectSoStruct = undefined;
HeapSnapshotStruct.selectSnapshotStruct = undefined;
FrameSpacingStruct.selectFrameSpacingStruct = undefined;
FrameAnimationStruct.selectFrameAnimationStruct = undefined;
FrameDynamicStruct.selectFrameDynamicStruct = undefined;
JsCpuProfilerStruct.selectJsCpuProfilerStruct = undefined;
SnapshotStruct.selectSnapshotStruct = undefined;
HiPerfCallChartStruct.selectStruct = undefined;
AllAppStartupStruct.selectStartupStruct = undefined;
LtpoStruct.selectLtpoStruct = undefined;
HitchTimeStruct.selectHitchTimeStruct = undefined;
SampleStruct.selectSampleStruct = undefined;
PerfToolStruct.selectPerfToolStruct = undefined;
GpuCounterStruct.selectGpuCounterStruct = undefined;
DmaFenceStruct.selectDmaFenceStruct = undefined;
XpowerAppDetailStruct.selectXpowerStruct = undefined;
XpowerStatisticStruct.selectXpowerStruct = undefined;
XpowerWifiStruct.selectBytesXpowerStruct = undefined;
XpowerWifiStruct.selectPacketsXpowerStruct = undefined;
XpowerThreadInfoStruct.selectXpowerStruct = undefined;
XpowerGpuFreqStruct.selectXpowerStruct = undefined;
SnapShotStruct.selectSnapShotStruct = undefined;
IOStruct.selectIOStruct = null;
IOStruct.selectIOStructList = [];
return this;
}
isWASDKeyPress(): boolean | undefined {
return (
this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s')
);
}
documentOnClick = (ev: MouseEvent): void => spSystemTraceDocumentOnClick(this, ev);
clickEmptyArea(): void {
this.queryAllTraceRow().forEach((it) => {
it.checkType = '-1';
it.rangeSelect = false;
});
this.rangeSelect.rangeTraceRow = [];
TraceRow.rangeSelectObject = undefined;
SpAiAnalysisPage.selectChangeListener(TraceRow.range?.startNS!, TraceRow.range?.endNS!);
this.selectStructNull();
this.wakeupListNull();
this.observerScrollHeightEnable = false;
this.selectFlag = null;
this.timerShaftEL?.removeTriangle('inverted');
if (!SportRuler.isMouseInSportRuler) {
this.traceSheetEL?.setMode('hidden');
}
this.removeLinkLinesByBusinessType('task', 'thread', 'func');
this.removeLinkLinesByBusinessType('task', 'thread', 'distributed');
this.refreshCanvas(true, 'click empty');
JankStruct.delJankLineFlag = true;
}
traceRowClickJudgmentConditions: Map<string, () => boolean> = new Map<string, () => boolean>([
[TraceRow.ROW_TYPE_CPU, (): boolean => CpuStruct.hoverCpuStruct !== null && CpuStruct.hoverCpuStruct !== undefined],
[
TraceRow.ROW_TYPE_THREAD,
(): boolean => ThreadStruct.hoverThreadStruct !== null && ThreadStruct.hoverThreadStruct !== undefined,
],
[
TraceRow.ROW_TYPE_FUNC,
(): boolean => FuncStruct.hoverFuncStruct !== null && FuncStruct.hoverFuncStruct !== undefined,
],
[
TraceRow.ROW_TYPE_SAMPLE,
(): boolean => SampleStruct.hoverSampleStruct !== null && SampleStruct.hoverSampleStruct !== undefined,
],
[
TraceRow.ROW_TYPE_GPU_COUNTER,
(): boolean =>
GpuCounterStruct.hoverGpuCounterStruct !== null && GpuCounterStruct.hoverGpuCounterStruct !== undefined,
],
[
TraceRow.ROW_TYPE_CPU_FREQ,
(): boolean => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined,
],
[
TraceRow.ROW_TYPE_CPU_STATE,
(): boolean => CpuStateStruct.hoverStateStruct !== null && CpuStateStruct.hoverStateStruct !== undefined,
],
[
TraceRow.ROW_TYPE_CPU_FREQ_LIMIT,
(): boolean =>
CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct !== null &&
CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct !== undefined,
],
[
TraceRow.ROW_TYPE_CLOCK,
(): boolean => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined,
],
[TraceRow.ROW_TYPE_IRQ, (): boolean => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined],
[
TraceRow.ROW_TYPE_APP_STARTUP,
(): boolean => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined,
],
[
TraceRow.ROW_TYPE_ALL_APPSTARTUPS,
(): boolean =>
AllAppStartupStruct.hoverStartupStruct !== null && AllAppStartupStruct.hoverStartupStruct !== undefined,
],
[
TraceRow.ROW_TYPE_STATIC_INIT,
(): boolean => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined,
],
[
TraceRow.ROW_TYPE_JANK,
(): boolean => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined,
],
[
TraceRow.ROW_TYPE_HEAP,
(): boolean => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined,
],
[
TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_HEAP_SNAPSHOT,
(): boolean =>
HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_FRAME_ANIMATION,
(): boolean =>
FrameAnimationStruct.hoverFrameAnimationStruct !== null &&
FrameAnimationStruct.hoverFrameAnimationStruct !== undefined,
],
[
TraceRow.ROW_TYPE_FRAME_DYNAMIC,
(): boolean =>
FrameDynamicStruct.hoverFrameDynamicStruct !== null && FrameDynamicStruct.hoverFrameDynamicStruct !== undefined,
],
[
TraceRow.ROW_TYPE_FRAME_SPACING,
(): boolean =>
FrameSpacingStruct.hoverFrameSpacingStruct !== null && FrameSpacingStruct.hoverFrameSpacingStruct !== undefined,
],
[
TraceRow.ROW_TYPE_JS_CPU_PROFILER,
(): boolean =>
JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== null &&
JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== undefined,
],
[
TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_PURGEABLE_PIN_ABILITY,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_PURGEABLE_PIN_VM,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_DMA_ABILITY,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_DMA_VMTRACKER,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_GPU_MEMORY_ABILITY,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_VMTRACKER_SHM,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_VM_TRACKER_SMAPS,
(): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
],
[
TraceRow.ROW_TYPE_HANG,
(): boolean => HangStruct.hoverHangStruct !== null && HangStruct.hoverHangStruct !== undefined,
],
[
TraceRow.ROW_TYPE_FILE_SYSTEM_IO,
(): boolean => IOStruct.hoverIOStruct !== null && IOStruct.hoverIOStruct !== undefined,
],
]);
onClickHandler(clickRowType: string, row?: TraceRow<unknown>, entry?: unknown): void {
spSystemTraceOnClickHandler(this, clickRowType, row as TraceRow<BaseStruct>, entry);
}
makePoint(
ts: number,
dur: number,
translateY: number,
rowStruct: unknown,
offsetY: number,
business: string,
lineType: LineType,
isRight: boolean
): PairPoint {
return {
x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!),
y: translateY!,
offsetY: offsetY,
ns: ts + dur,
rowEL: rowStruct!,
isRight: isRight,
business: business,
lineType: lineType,
};
}
drawTaskPollLine(row?: TraceRow<unknown>): void {
spSystemTraceDrawTaskPollLine(this, row);
}
drawJankLine(
endParentRow: unknown,
selectJankStruct: JankStruct,
data: unknown,
isBinderClick: boolean = false
): void {
spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data, isBinderClick);
}
drawDistributedLine(
sourceData: FuncStruct,
targetData: FuncStruct,
selectFuncStruct: FuncStruct,
): void {
spSystemTraceDrawDistributedLine(this, sourceData, targetData, selectFuncStruct);
}
drawThreadLine(endParentRow: unknown, selectThreadStruct: ThreadStruct | undefined, data: unknown): void {
spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data);
}
drawFuncLine(endParentRow: unknown, selectFuncStruct: FuncStruct | undefined, data: unknown, binderTid: Number): void {
spSystemTraceDrawFuncLine(this, endParentRow, selectFuncStruct, data, binderTid);
}
getStartRow(selectRowId: number | undefined, selectRowPid: number | undefined, collectList: unknown[]): unknown {
let startRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
`trace-row[row-id='${selectRowId}'][row-parent-id='${selectRowPid}'][row-type='thread']`
);
if (!startRow) {
for (let collectChart of collectList) {
if (collectChart.rowId === selectRowId?.toString() && collectChart.rowParentId === selectRowPid?.toString() && collectChart.rowType === 'thread') {
startRow = collectChart;
break;
}
}
}
return startRow;
}
calculateStartY(startRow: unknown, pid: number | undefined, tid: number | undefined, selectFuncStruct?: FuncStruct): [number, unknown, number] {
let startY = startRow ? startRow!.translateY! : 0;
let startRowEl = startRow;
let startOffSetY = selectFuncStruct ? 20 * (0.5 + Number(selectFuncStruct.depth)) : 20 * 0.5;
let startParentRow = startRow ? this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(`trace-row[row-id='${startRow.rowParentId}'][folder]`) : this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
`trace-row[row-id='${pid}'][folder]`
);
if (startParentRow && startParentRow.expansion) {
let filterRow = startParentRow?.childrenList.filter((item) => item.rowId === tid)[0];
!filterRow && startParentRow?.childrenList.forEach((i) => {
if (i.rowId === 'sameThreadProcess') {
filterRow = startParentRow?.childrenList.concat(i.childrenList).filter((item) => item.rowId === String(tid))[0];
startParentRow = filterRow!.parentRowEl!;
}
});
}
const expansionFlag = this.collectionHasThread(startRow);
if (startParentRow && !startParentRow.expansion && expansionFlag) {
startY = startParentRow.translateY!;
startRowEl = startParentRow;
startOffSetY = selectFuncStruct ? 10 * (0.5 + Number(selectFuncStruct.depth)) : 10 * 0.5;
}
return [startY, startRowEl, startOffSetY];
}
calculateEndY(endParentRow: unknown, endRowStruct: unknown, data?: unknown): [number, unknown, number] {
let endY = endRowStruct.translateY!;
let endRowEl = endRowStruct;
let endOffSetY = data ? 20 * (0.5 + Number(data.depth)) : 20 * 0.5;
const expansionFlag = this.collectionHasThread(endRowStruct);
if (!endParentRow.expansion && expansionFlag) {
endY = endParentRow.translateY!;
endRowEl = endParentRow;
endOffSetY = data ? 10 * (0.5 + Number(data.depth)) : 10 * 0.5;
}
return [endY, endRowEl, endOffSetY];
}
collectionHasThread(threadRow: unknown): boolean {
const collectList = this.favoriteChartListEL!.getCollectRows();
for (let item of collectList!) {
if (threadRow && item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) {
return false;
}
}
return true;
}
translateByMouseMove(ev: MouseEvent): void {
ev.preventDefault();
let offset = 0;
if (this.offsetMouse === 0) {
this.offsetMouse = ev.clientX;
offset = ev.clientX - this.mouseCurrentPosition;
} else {
offset = ev.clientX - this.offsetMouse;
}
this.offsetMouse = ev.clientX;
const rangeRuler = this.timerShaftEL?.getRangeRuler()!;
rangeRuler.translate(offset);
}
private eventListener(): void {
* 监听时间轴区间变化
*/
this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange;
this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick;
this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange;
this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler;
* 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘)
*/
this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, {
passive: true,
});
this.favoriteChartListEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, {
passive: true,
});
* 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入
*/
this.addEventListener('mousemove', this.documentOnMouseMove);
this.addEventListener('click', this.documentOnClick);
this.addEventListener('mousedown', this.documentOnMouseDown);
this.addEventListener('mouseup', this.documentOnMouseUp);
this.addEventListener('mouseout', this.documentOnMouseOut);
this.addEventListener('pointercancel', this.documentOnPointercancel);
document.addEventListener('keydown', this.documentOnKeyDown);
document.addEventListener('keypress', this.documentOnKeyPress);
document.addEventListener('keyup', this.documentOnKeyUp);
document.addEventListener('contextmenu', this.onContextMenuHandler);
this.wheelListener();
}
private subRecordExportListener(): void {
window.subscribe(window.SmartEvent.UI.ExportRecord, (params) => {
let range = this.timerShaftEL?.rangeRuler?.range;
let searchVal = document.querySelector('body > sp-application').shadowRoot.querySelector('#lit-search').shadowRoot.querySelector('div.root > input')!.value;
if (range) {
let expandRows =
Array.from(this.rowsEL!.querySelectorAll<TraceRow<BaseStruct>>('trace-row[folder][expansion]')) || [];
let data = JSON.stringify({
leftNS: range.startNS,
rightNS: range.endNS,
G1: this.favoriteChartListEL!.getCollectRowsInfo('1'),
G2: this.favoriteChartListEL!.getCollectRowsInfo('2'),
expand: expandRows.map((row) => {
return {
type: row.rowType,
name: row.name,
id: row.rowId,
};
}),
scrollTop: this.rowsEL!.scrollTop,
favoriteScrollTop: this.favoriteChartListEL!.scrollTop,
drawFlag: this.timerShaftEL!.sportRuler!.flagList,
markFlag: this.timerShaftEL!.sportRuler!.slicesTimeList,
search: searchVal ? searchVal : ''
});
this.downloadRecordFile(data).then(() => { });
}
});
}
private async downloadRecordFile(jsonStr: string): Promise<void> {
let a = document.createElement('a');
let buffer = await readTraceFileBuffer();
if (buffer) {
let str = `MarkPositionJSON->${jsonStr}\n`;
let mark = new Blob([str]);
let markBuf = await mark.arrayBuffer();
a.href = URL.createObjectURL(new Blob([`${markBuf.byteLength}`, mark, buffer]));
a.download = (window as unknown).traceFileName || `${new Date().getTime()}`;
a.click();
window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Downloading trace file with mark' });
} else {
let search = document.querySelector('body > sp-application')!.shadowRoot!.querySelector<LitSearch>('#lit-search');
let progressEL = document.querySelector("body > sp-application")!.shadowRoot!.querySelector<LitProgressBar>("div > div.search-vessel > lit-progress-bar");
progressEL!.loading = false;
search!.setPercent('import the trace file again...', -3);
}
}
private subRecordImportListener(): void {
window.subscribe(window.SmartEvent.UI.ImportRecord, (data: string) => {
let record = JSON.parse(data);
this.favoriteChartListEL?.removeAllCollectRow();
let currentGroup = this.currentCollectGroup;
if (record.G1) {
this.currentCollectGroup = '1';
this.restoreRecordCollectRows(record.G1);
}
if (record.G2) {
this.currentCollectGroup = '2';
this.restoreRecordCollectRows(record.G2);
}
this.restoreRecordExpandAndTimeRange(record);
this.currentCollectGroup = currentGroup;
if (record.drawFlag !== undefined) {
this.timerShaftEL!.sportRuler!.flagList = record.drawFlag;
this.selectFlag = this.timerShaftEL!.sportRuler!.flagList.find((it) => it.selected);
}
if (record.markFlag !== undefined) {
this.timerShaftEL!.sportRuler!.slicesTimeList = record.markFlag;
}
TraceRow.range!.refresh = true;
this.refreshCanvas(true);
this.restoreRecordScrollTop(record.scrollTop, record.favoriteScrollTop);
document.querySelector('body > sp-application').shadowRoot.querySelector('#lit-search').shadowRoot.querySelector('div.root > input')!.value = record.search ? record.search : '';
document.querySelector('body > sp-application').shadowRoot.querySelector('#lit-search')!.valueChangeHandler!(record.search ? record.search : '');
});
}
private restoreRecordExpandAndTimeRange(record: unknown): void {
if (record.expand) {
let expandRows =
Array.from(this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row[folder][expansion]')) || [];
let expands: Array<unknown> = record.expand;
for (let expandRow of expandRows) {
if (
!expands.includes(
(it: unknown) =>
it.id === expandRow.rowId && it.name === expandRow.name && it.type === expandRow.rowType
)
) {
expandRow.expansion = false;
}
}
for (let it of record.expand) {
let traceRow = this.rowsEL!.querySelector<TraceRow<unknown>>(
`trace-row[folder][row-id='${it.id}'][row-type='${it.type}']`
);
if (traceRow && !traceRow.expansion) {
traceRow.expansion = true;
}
}
}
if (record.leftNS && record.rightNS) {
this.timerShaftEL?.setRangeNS(record.leftNS, record.rightNS);
}
}
private restoreRecordScrollTop(mainScrollTop: number, favoriteScrollTop: number): void {
if (mainScrollTop && mainScrollTop > 0) {
this.rowsPaneEL!.scroll({
top: mainScrollTop,
left: 0,
behavior: 'smooth',
});
}
if (favoriteScrollTop && favoriteScrollTop > 0) {
this.favoriteChartListEL?.scroll({
top: favoriteScrollTop,
left: 0,
behavior: 'smooth',
});
}
}
private restoreRecordCollectRows(group: Array<unknown>): void {
group.forEach((it: unknown) => {
let traceRow: TraceRow<unknown> | undefined | null = this.rowsEL!.querySelector<TraceRow<unknown>>(
`trace-row[row-id='${it.id}'][row-type='${it.type}']`
);
if (traceRow === null || traceRow === undefined) {
if (it.parents.length > 0) {
let rootFolder = it.parents[0];
let folderRow: TraceRow<unknown> | undefined | null = this.rowsEL!.querySelector<TraceRow<unknown>>(
`trace-row[row-id='${rootFolder.id}'][row-type='${rootFolder.type}']`
);
if (folderRow) {
if (!folderRow!.expansion) {
folderRow!.expansion = true;
}
for (let i = 1; i < it.parents.length; i++) {
folderRow = folderRow!.childrenList.find(
(child) => child.rowId === it.parents[i].id && child.rowType === it.parents[i].type
);
if (!folderRow!.expansion) {
folderRow!.expansion = true;
}
}
}
if (folderRow) {
traceRow = folderRow.childrenList.find((child) => child.rowId === it.id && child.rowType === it.type);
}
}
}
if (traceRow) {
traceRow.collectEL?.click();
}
});
}
private wheelListener(): void {
document.addEventListener(
'wheel',
(e): void => {
if (e.ctrlKey) {
if (e.deltaY > 0) {
e.preventDefault();
e.stopPropagation();
let eventS = new KeyboardEvent('keypress', {
key: 's',
code: '83',
keyCode: 83,
});
this.timerShaftEL!.documentOnKeyPress(eventS);
setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventS), 200);
}
if (e.deltaY < 0) {
e.preventDefault();
e.stopPropagation();
let eventW = new KeyboardEvent('keypress', {
key: 'w',
code: '87',
keyCode: 87,
});
this.timerShaftEL!.documentOnKeyPress(eventW);
setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventW), 200);
}
}
},
{ passive: false }
);
}
connectedCallback(): void {
this.initPointToEvent();
this.eventListener();
this.subRecordExportListener();
this.subRecordImportListener();
* 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。
* 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用,
* 否则泳道图会一直放大或一直缩小。
* setTimeout()函数中的时间参数可以控制鼠标滚轮的频率。
*/
SpApplication.skinChange2 = (val: boolean): void => {
this.timerShaftEL?.render();
};
window.subscribe(window.SmartEvent.UI.UploadSOFile, (data): void => {
this.chartManager?.importSoFileUpdate().then(() => {
window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Import So File' });
let updateCanvas = this.traceSheetEL?.updateRangeSelect();
if (updateCanvas) {
this.refreshCanvas(true);
}
});
});
window.subscribe(window.SmartEvent.UI.KeyPath, (data): void => {
this.invisibleRows.forEach((it) => (it.needRefresh = true));
this.visibleRows.forEach((it) => (it.needRefresh = true));
if (data.length === 0) {
SpSystemTrace.keyPathList = [];
this.refreshCanvas(false);
} else {
queryCpuKeyPathData(data).then((res): void => {
SpSystemTrace.keyPathList = res;
this.refreshCanvas(false);
});
}
});
window.subscribe(window.SmartEvent.UI.CheckALL, (data): void => {
this.getCollectRows((row) => row.rowParentId === data.rowId).forEach((it) => {
it.checkType = data.isCheck ? '2' : '0';
});
});
window.subscribe(window.SmartEvent.UI.HoverNull, () => this.hoverStructNull());
this.subscribeBottomTabVisibleEvent();
}
public scrollH: number = 0;
subscribeBottomTabVisibleEvent(): void {
window.subscribe(window.SmartEvent.UI.ShowBottomTab, (data: { show: number; delta: number }): void => {
let heightTimeOut: unknown = undefined;
if (heightTimeOut) {
clearTimeout(heightTimeOut);
}
if (data.show === 1) {
this.scrollH = this.rowsEL!.scrollHeight;
} else {
if (this.rowsEL!.scrollHeight > this.scrollH) {
heightTimeOut = setTimeout(() => {
let litTab = this.traceSheetEL?.shadowRoot?.querySelector<LitTabs>('#tabs');
if (this.traceSheetEL?.getAttribute('mode') === 'hidden') {
this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta;
}
if (litTab?.style.height && litTab?.style.height === '38px') {
this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta;
}
}, 50);
}
}
});
}
favoriteAreaSearchHandler(row: TraceRow<unknown>): void {
if (this.timerShaftEL!.collecBtn!.hasAttribute('close')) {
this.timerShaftEL!.collecBtn!.removeAttribute('close');
this.favoriteChartListEL!.showCollectArea();
}
this.favoriteChartListEL?.expandSearchRowGroup(row);
}
scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void {
let id = Utils.getDistributedRowId(rowId);
let parentId = Utils.getDistributedRowId(rowParentId);
let traceRow =
this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${id}'][row-parent-id='${parentId}'][row-type='${rowType}']`) ||
this.favoriteChartListEL!.getCollectRow((row) => row.rowId === id && row.rowType === rowType);
if (traceRow?.collect) {
this.favoriteChartListEL!.scroll({
top:
(traceRow?.offsetTop || 0) -
this.favoriteChartListEL!.getCanvas()!.offsetHeight +
(traceRow?.offsetHeight || 0),
left: 0,
behavior: smooth ? 'smooth' : undefined,
});
} else {
let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${parentId}'][folder]`);
if (row && !row.expansion) {
row.expansion = true;
}
if (traceRow && traceRow.offsetTop >= 0 && traceRow.offsetHeight >= 0) {
this.rowsPaneEL!.scroll({
top: (traceRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (traceRow?.offsetHeight || 0),
left: 0,
behavior: smooth ? 'smooth' : undefined,
});
}
}
}
scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number): void {
let rootRow =
this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) ||
this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType);
if (rootRow && rootRow!.collect) {
this.favoriteAreaSearchHandler(rootRow);
rootRow.expandFunc(rootRow, this);
if (!this.isInViewport(rootRow)) {
setTimeout(() => {
rootRow!.scrollIntoView({ behavior: 'smooth' });
}, 500);
}
} else {
let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
if (row && !row.expansion) {
row.expansion = true;
}
if (rootRow) {
rootRow.expandFunc(rootRow, this);
}
setTimeout(() => {
rootRow!.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}, 500);
}
}
isInViewport(e: unknown): boolean {
const rect = e.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void {
let id = Utils.getDistributedRowId(rowId);
let parentId = Utils.getDistributedRowId(rowParentId);
let condition = `trace-row[row-id='${id}'][row-type='${rowType}'][row-parent-id='${parentId}']`;
let rootRow =
this.rowsEL!.querySelector<TraceRow<unknown>>(condition) ||
this.favoriteChartListEL!.getCollectRow((row) => {
return row.rowId === id && row.rowType === rowType && row.rowParentId === parentId;
});
if (rootRow?.collect) {
this.favoriteAreaSearchHandler(rootRow);
this.favoriteChartListEL!.scroll({
top:
(rootRow?.offsetTop || 0) -
this.favoriteChartListEL!.getCanvas()!.offsetHeight +
(rootRow?.offsetHeight || 0),
left: 0,
behavior: smooth ? 'smooth' : undefined,
});
} else {
let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
if (row && !row.expansion) {
row.expansion = true;
}
if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) {
this.rowsPaneEL!.scroll({
top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + 20,
left: 0,
behavior: smooth ? 'smooth' : undefined,
});
}
}
}
disconnectedCallback(): void {
this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange);
this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll);
this.favoriteChartListEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll);
this.removeEventListener('mousemove', this.documentOnMouseMove);
this.removeEventListener('click', this.documentOnClick);
this.removeEventListener('mousedown', this.documentOnMouseDown);
this.removeEventListener('mouseup', this.documentOnMouseUp);
this.removeEventListener('mouseout', this.documentOnMouseOut);
this.removeEventListener('pointercancel', this.documentOnPointercancel);
document.removeEventListener('keypress', this.documentOnKeyPress);
document.removeEventListener('keydown', this.documentOnKeyDown);
document.removeEventListener('keyup', this.documentOnKeyUp);
document.removeEventListener('contextmenu', this.onContextMenuHandler);
window.unsubscribe(window.SmartEvent.UI.SliceMark, this.sliceMarkEventHandler.bind(this));
}
sliceMarkEventHandler(ev: unknown): void {
SpSystemTrace.sliceRangeMark = ev;
let startNS = ev.timestamp - (window as unknown).recordStartNS;
let endNS = ev.maxDuration + startNS;
TraceRow.rangeSelectObject = {
startX: 0,
startNS: startNS,
endNS: endNS,
endX: 0,
};
window.publish(window.SmartEvent.UI.MenuTrace, {});
window.publish(window.SmartEvent.UI.TimeRange, {
startNS: startNS - ev.maxDuration,
endNS: endNS + ev.maxDuration,
});
this.queryAllTraceRow().forEach((it) => (it.checkType = '-1'));
this.rangeSelect.rangeTraceRow = [];
this.selectStructNull();
this.wakeupListNull();
this.traceSheetEL?.setMode('hidden');
this.removeLinkLinesByBusinessType('janks');
this.removeLinkLinesByBusinessType('distributed');
TraceRow.range!.refresh = true;
this.refreshCanvas(false, 'slice mark event');
}
loadDatabaseUrl(
url: string,
progress: Function,
complete?: ((res: { status: boolean; msg: string }) => void) | undefined
): void {
this.observerScrollHeightEnable = false;
this.init({ url: url }, '', '', progress, false).then((res) => {
if (complete) {
complete(res);
window.publish(window.SmartEvent.UI.MouseEventEnable, {
mouseEnable: true,
});
}
});
}
loadDatabaseArrayBuffer(
buf: ArrayBuffer,
thirdPartyWasmConfigUrl: string,
configUrl: string,
progress: (name: string, percent: number) => void,
isDistributed: boolean,
complete?: ((res: { status: boolean; msg: string }) => void) | undefined,
buf2?: ArrayBuffer,
fileName1?: string,
fileName2?: string
): void {
this.observerScrollHeightEnable = false;
if (isDistributed) {
this.timerShaftEL?.setAttribute('distributed', '');
} else {
this.timerShaftEL?.removeAttribute('distributed');
}
this.init({ buf, buf2, fileName1, fileName2 }, thirdPartyWasmConfigUrl, configUrl, progress, isDistributed).then((res) => {
this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
if (complete) {
complete(res);
window.publish(window.SmartEvent.UI.MouseEventEnable, {
mouseEnable: true,
});
}
});
}
loadSample = async (ev: File): Promise<void> => {
this.observerScrollHeightEnable = false;
await this.initSample(ev);
this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
window.publish(window.SmartEvent.UI.MouseEventEnable, {
mouseEnable: true,
});
};
initSample = async (ev: File): Promise<void> => {
this.rowsPaneEL!.scroll({
top: 0,
left: 0,
});
this.chartManager?.initSample(ev).then((): void => {
this.loadTraceCompleted = true;
this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it): void => {
this.intersectionObserver?.observe(it);
});
});
};
loadGpuCounter = async (ev: File): Promise<void> => {
this.observerScrollHeightEnable = false;
await this.initGpuCounter(ev);
this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
window.publish(window.SmartEvent.UI.MouseEventEnable, {
mouseEnable: true,
});
};
initGpuCounter = async (ev: File): Promise<void> => {
this.rowsPaneEL!.scroll({
top: 0,
left: 0,
});
this.chartManager?.initGpuCounter(ev).then(() => {
this.loadTraceCompleted = true;
this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it) => {
this.intersectionObserver?.observe(it);
});
});
};
queryAllTraceRow<T>(selectors?: string, filter?: (row: TraceRow<unknown>) => boolean): TraceRow<unknown>[] {
return [
...this.rowsEL!.querySelectorAll<TraceRow<unknown>>(selectors ?? 'trace-row'),
...this.favoriteChartListEL!.getCollectRows(filter),
];
}
search(query: string): void {
this.queryAllTraceRow().forEach((item): void => {
if (query === null || query === undefined || query === '') {
if (
item.rowType === TraceRow.ROW_TYPE_CPU ||
item.rowType === TraceRow.ROW_TYPE_CPU_FREQ ||
item.rowType === TraceRow.ROW_TYPE_NATIVE_MEMORY ||
item.rowType === TraceRow.ROW_TYPE_FPS ||
item.rowType === TraceRow.ROW_TYPE_PROCESS ||
item.rowType === TraceRow.ROW_TYPE_CPU_ABILITY ||
item.rowType === TraceRow.ROW_TYPE_MEMORY_ABILITY ||
item.rowType === TraceRow.ROW_TYPE_DISK_ABILITY ||
item.rowType === TraceRow.ROW_TYPE_NETWORK_ABILITY
) {
item.expansion = false;
item.rowHidden = false;
} else {
item.rowHidden = true;
}
} else {
item.rowHidden = item.name.toLowerCase().indexOf(query.toLowerCase()) < 0;
}
});
this.visibleRows.forEach((it) => (it.rowHidden = false && it.draw(true)));
}
async searchCPU(query: string): Promise<Array<unknown>> {
let pidArr: Array<number> = [];
let tidArr: Array<number> = [];
let processMap = Utils.getInstance().getProcessMap(Utils.currentSelectTrace);
let threadMap = Utils.getInstance().getThreadMap(Utils.currentSelectTrace);
for (let key of processMap.keys()) {
if (`${key}`.includes(query) || (processMap.get(key) || '').includes(query)) {
pidArr.push(key);
}
}
for (let key of threadMap.keys()) {
if (`${key}`.includes(query) || (threadMap.get(key) || '').includes(query)) {
tidArr.push(key);
}
}
return await searchCpuDataSender(pidArr, tidArr, Utils.currentSelectTrace);
}
seachAsyncFunc(query: string): unknown[] {
let asyncFuncArr: Array<unknown> = [];
let strNew = (str: unknown): string => {
const specialChars = {
'': '\\^',
'$': '\\$',
'.': '\\.',
'*': '\\*',
'+': '\\+',
'?': '\\?',
'-': '\\-',
'|': '\\|',
'(': '\\(',
')': '\\)',
'[': '\\[',
']': '\\]',
'{': '\\{',
'}': '\\}',
};
return str.replace(/[$\^.*+?|()\[\]{}-]/g, (match: string) => specialChars[match as keyof typeof specialChars]);
};
let regex = new RegExp(strNew(query), 'i');
SpProcessChart.asyncFuncCache.forEach((item: unknown) => {
if (regex.test(item.funName)) {
asyncFuncArr.push(item);
}
});
return asyncFuncArr;
}
async searchFunction(cpuList: Array<unknown>, asynList: Array<unknown>, query: string): Promise<Array<unknown>> {
let processList: Array<string> = [];
let traceRow =
this.shadowRoot!.querySelector<TraceRow<unknown>>('trace-row[scene]') ||
this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
if (traceRow) {
this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[row-type='process'][scene]").forEach(
(row): void => {
let rowId = row.rowId;
if (rowId && rowId.includes('-')) {
rowId = rowId.split('-')[0];
}
processList.push(rowId as string);
}
);
if (query.includes('_')) {
query = query.replace(/_/g, '\\_');
}
if (query.includes('%')) {
query = query.replace(/%/g, '\\%');
}
let list = await querySceneSearchFunc(query, processList);
cpuList = cpuList.concat(asynList);
cpuList = cpuList.concat(list);
cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
return cpuList;
} else {
let list = await querySearchFunc(query);
cpuList = cpuList.concat(asynList);
cpuList = cpuList.concat(list);
cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
return cpuList;
}
}
searchTargetTraceHandler(): void {
if (Utils.currentSelectTrace) {
let traceFolder1 = this.shadowRoot!.querySelector<TraceRow<unknown>>(`trace-row[row-id='trace-1']`);
let traceFolder2 = this.shadowRoot!.querySelector<TraceRow<unknown>>(`trace-row[row-id='trace-2']`);
if (Utils.currentSelectTrace === '1') {
if (traceFolder2?.expansion) {
traceFolder2!.expansion = false;
}
traceFolder1!.expansion = true;
} else {
if (traceFolder1?.expansion) {
traceFolder1!.expansion = false;
}
traceFolder2!.expansion = true;
}
}
}
searchSdk(dataList: Array<unknown>, query: string): Array<unknown> {
let traceRow =
this.shadowRoot!.querySelector<TraceRow<unknown>>('trace-row[scene]') ||
this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
let dataAll = "trace-row[row-type^='sdk']";
if (traceRow) {
dataAll = "trace-row[row-type^='sdk'][scene]";
}
let allTraceRow: unknown = [];
let parentRows = this.shadowRoot!.querySelectorAll<TraceRow<unknown>>(`${dataAll}`);
parentRows.forEach((parentRow: TraceRow<unknown>): void => {
allTraceRow.push(parentRow);
if (parentRow.childrenList && parentRow.childrenList.length > 0) {
allTraceRow.push(...parentRow.childrenList);
}
});
allTraceRow.forEach((row: unknown): void => {
if (row!.name.indexOf(query) >= 0) {
let searchSdkBean = new SearchSdkBean();
searchSdkBean.startTime = TraceRow.range!.startNS;
searchSdkBean.dur = TraceRow.range!.totalNS;
searchSdkBean.name = row.name;
searchSdkBean.rowId = row.rowId;
searchSdkBean.type = 'sdk';
searchSdkBean.rowType = row.rowType;
searchSdkBean.rowParentId = row.rowParentId;
dataList.push(searchSdkBean);
}
});
return dataList;
}
showStruct(previous: boolean, currentIndex: number, structs: Array<unknown>, retargetIndex?: number): number {
let tagIndex = spSystemTraceShowStruct(this, previous, currentIndex, structs, retargetIndex);
return tagIndex === -1 ? currentIndex : tagIndex;
}
private toTargetDepth = (entry: unknown, funcRowID: string, funcStract: unknown): void => {
if (entry) {
this.hoverStructNull();
this.selectStructNull();
this.wakeupListNull();
FuncStruct.hoverFuncStruct = entry;
FuncStruct.selectFuncStruct = entry;
this.scrollToDepth(
`${funcRowID}`,
`${Utils.getDistributedRowId(funcStract.pid)}`,
'func',
true,
entry.depth || 0
);
if (FuncStruct.funcSelect) {
this.onClickHandler(TraceRow.ROW_TYPE_FUNC, undefined, entry);
}
FuncStruct.funcSelect = true;
}
};
scrollToActFunc(funcStract: unknown, highlight: boolean): void {
if (!Utils.isBinder(funcStract)) {
if (funcStract.dur === -1 || funcStract.dur === null || funcStract.dur === undefined) {
funcStract.dur = (TraceRow.range?.totalNS || 0) - (funcStract.startTs || 0);
funcStract.flag = 'Did not end';
}
}
let funId = funcStract.row_id === null ? `${funcStract.funName}-${funcStract.pid}` : funcStract.row_id;
let funcRowID = (funcStract.cookie === null || funcStract.cookie === undefined) ? `${Utils.getDistributedRowId(funcStract.tid)}` : funId;
let targetRow = this.favoriteChartListEL?.getCollectRow((row) => {
return row.rowId === funcRowID && row.rowType === 'func';
});
if (targetRow) {
targetRow.fixedList[0] = funcStract;
targetRow.highlight = highlight;
this.toTargetDepth(funcStract, funcRowID, funcStract);
return;
}
let parentRow = this.rowsEL!.querySelector<TraceRow<BaseStruct>>(
`trace-row[row-id='${Utils.getDistributedRowId(funcStract.pid)}'][folder]`
);
if (!parentRow) {
return;
}
let filterRow: TraceRow<unknown> | undefined;
let isSameThreadProcess = false;
parentRow.childrenList.forEach((item) => {
if (item.rowId === 'sameThreadProcess') {
filterRow = parentRow.childrenList.concat(item.childrenList).filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0];
item.childrenList.forEach((i) => {
if (filterRow!.rowId === i.rowId) {
isSameThreadProcess = true;
}
});
} else {
filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0];
}
});
if (!filterRow) {
let funcRow = this.rowsEL?.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcRowID}'][row-type='func']`);
if (funcRow) {
filterRow = funcRow;
} else {
return;
}
}
filterRow.fixedList = [funcStract];
filterRow!.highlight = highlight;
let row = this.rowsEL!.querySelector<TraceRow<BaseStruct>>(
`trace-row[row-id='${Utils.getDistributedRowId(funcStract.pid)}'][folder]`
);
this.currentRow = row;
if (row && !row.expansion) {
row.expansion = true;
}
if (row!.expansion) {
if (isSameThreadProcess) {
this.currentRow = this.rowsEL!.querySelector<TraceRow<BaseStruct>>(
'trace-row[row-id="sameThreadProcess"][folder]');
this.currentRow!.expansion = true;
}
}
const completeEntry = (): void => {
this.toTargetDepth(filterRow!.fixedList[0], funcRowID, funcStract);
};
if (filterRow!.isComplete) {
completeEntry();
} else {
this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'thread', false);
this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true);
completeEntry();
}
}
closeAllExpandRows(pid: string): void {
let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>("trace-row[row-type='process'][expansion]");
expandRows?.forEach((row): void => {
if (row.rowId !== pid) {
row.expansion = false;
}
});
}
moveRangeToLeft(startTime: number, dur: number): void {
let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
let harfDur = Math.trunc(endNS - startNS - dur / 2);
let leftNs = startTime;
let rightNs = startTime + dur + harfDur;
if (startTime - harfDur < 0) {
leftNs = 0;
rightNs += harfDur - startTime;
}
this.timerShaftEL?.setRangeNS(leftNs, rightNs);
TraceRow.range!.refresh = true;
this.refreshCanvas(true, 'move range to left');
}
moveRangeToCenter(startTime: number, dur: number): void {
let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2);
let leftNs = startTime - harfDur;
let rightNs = startTime + dur + harfDur;
if (startTime - harfDur < 0) {
leftNs = 0;
rightNs += harfDur - startTime;
}
this.timerShaftEL?.setRangeNS(leftNs, rightNs);
TraceRow.range!.refresh = true;
this.refreshCanvas(true, 'move range to center');
}
rechargeCpuData(it: CpuStruct, next: CpuStruct | undefined): void {
let p = Utils.getInstance().getProcessMap().get(it.processId!);
let t = Utils.getInstance().getThreadMap().get(it.tid!);
let slice = Utils.getInstance().getSchedSliceMap().get(`${it.id}-${it.startTime}`);
if (slice) {
it.end_state = slice.endState;
it.priority = slice.priority;
}
it.processName = p;
it.processCmdLine = p;
it.name = t;
if (next) {
if (it.startTime! + it.dur! > next!.startTime! || it.dur === -1 || it.dur === null || it.dur === undefined) {
it.dur = next!.startTime! - it.startTime!;
it.nofinish = true;
}
} else {
if (it.dur === -1 || it.dur === null || it.dur === undefined) {
it.dur = TraceRow.range!.endNS - it.startTime!;
it.nofinish = true;
}
}
}
reset(progress: Function | undefined | null): void {
this.visibleRows.length = 0;
this.tipEL!.style.display = 'none';
this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight);
this.loadTraceCompleted = false;
this.collectRows = [];
this.visibleRows = [];
TraceRowConfig.allTraceRowList.forEach((it) => {
it.clearMemory();
});
TraceRowConfig.allTraceRowList = [];
this.favoriteChartListEL!.reset();
if (this.rowsEL) {
this.rowsEL.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((row) => {
row.clearMemory();
this.rowsEL!.removeChild(row);
});
}
this.traceSheetEL?.clearMemory();
this.spacerEL!.style.height = '0px';
this.rangeSelect.rangeTraceRow = [];
SpSystemTrace.SDK_CONFIG_MAP = undefined;
SpSystemTrace.sliceRangeMark = undefined;
this.timerShaftEL?.displayCollect(false);
this.timerShaftEL!.collecBtn!.removeAttribute('close');
CpuStruct.wakeupBean = undefined;
this.selectStructNull();
this.hoverStructNull();
this.wakeupListNull();
this.traceSheetEL?.setMode('hidden');
progress?.('rest timershaft', 8);
this.timerShaftEL?.reset();
progress?.('clear cache', 10);
HeapDataInterface.getInstance().clearData();
procedurePool.clearCache();
Utils.clearData();
InitAnalysis.getInstance().isInitAnalysis = true;
InitAnalysis.getInstance().isInitGMAnalysis = true;
InitAnalysis.getInstance().isInitOSAnalysis = true;
procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: unknown) => { });
if (threadPool) {
threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => { });
}
if (threadPool2) {
threadPool2.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => { });
}
this.times.clear();
resetVSync();
SpSystemTrace.keyPathList = [];
Utils.isTransformed = false;
}
init = async (
param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string },
wasmConfigUri: string,
configUrl: string,
progress: Function,
isDistributed: boolean
): Promise<unknown> => {
return spSystemTraceInit(this, param, wasmConfigUri, configUrl, progress, isDistributed);
};
extracted(it: TraceRow<unknown>) {
return (): void => {
if (it.hasAttribute('expansion')) {
it.childrenList.forEach((child): void => {
if (child.hasAttribute('scene') && !child.collect) {
child.rowHidden = false;
}
if (child.folder) {
child.addEventListener('expansion-change', this.extracted(child));
}
this.intersectionObserver?.observe(child);
});
} else {
let parentElTopHeight = it.hasParentRowEl ?
(it.parentRowEl.getBoundingClientRect().top + it.parentRowEl.clientHeight) : this.rowsPaneEL!.getBoundingClientRect().top;
it.childrenList.forEach((child): void => {
if (child.hasAttribute('scene') && !child.collect) {
child.rowHidden = true;
this.intersectionObserver?.unobserve(child);
}
if (child.folder) {
child.removeEventListener('expansion-change', this.extracted(child));
}
});
if (it.getBoundingClientRect().top < 0) {
this.rowsPaneEL!.scrollTop =
this.rowsPaneEL!.scrollTop -
(it.getBoundingClientRect().top * -1 + parentElTopHeight);
} else if (it.getBoundingClientRect().top > 0) {
this.rowsPaneEL!.scrollTop =
parentElTopHeight <
it.getBoundingClientRect().top ?
this.rowsPaneEL!.scrollTop :
this.rowsPaneEL!.scrollTop -
(parentElTopHeight - it.getBoundingClientRect().top);
} else {
this.rowsPaneEL!.scrollTop =
this.rowsPaneEL!.scrollTop -
parentElTopHeight;
}
this.linkNodes.map((value): void => {
if ('task' === value[0].business && value[0].rowEL.parentRowEl?.rowId === it.rowId) {
value[0].hidden = true;
value[1].hidden = true;
this.clickEmptyArea();
}
});
}
this.resetDistributedLine();
if (!this.collapseAll) {
this.refreshCanvas(false, 'extracted');
}
};
}
resetDistributedLine(): void {
if (FuncStruct.selectLineFuncStruct.length > 5) {
return;
}
if (FuncStruct.selectFuncStruct) {
let dataList = FuncStruct.selectLineFuncStruct;
this.removeLinkLinesByBusinessType('distributed');
FuncStruct.selectLineFuncStruct = dataList;
for (let index = 0; index < FuncStruct.selectLineFuncStruct.length; index++) {
let sourceData = FuncStruct.selectLineFuncStruct[index];
if (index !== FuncStruct.selectLineFuncStruct.length - 1) {
let targetData = FuncStruct.selectLineFuncStruct[index + 1];
this.drawDistributedLine(sourceData, targetData, FuncStruct.selectFuncStruct!);
}
}
this.refreshCanvas(true);
}
}
displayTip(row: TraceRow<unknown>, struct: unknown, html: string): void {
let x = row.hoverX + 248;
let y = row.getBoundingClientRect().top - this.getBoundingClientRect().top;
if ((struct === undefined || struct === null) && this.tipEL) {
this.tipEL.style.display = 'none';
return;
}
if (this.tipEL) {
this.tipEL.innerHTML = html;
if (
row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER ||
row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART ||
row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT
) {
this.tipEL.style.maxWidth = `${row.clientWidth / 3} px`;
this.tipEL.style.wordBreak = ' break-all';
this.tipEL.style.height = 'unset';
this.tipEL.style.display = 'block';
y = y + struct.depth * 20;
if (row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) {
this.tipEL.style.height = 'auto';
y = row.hoverY + row.getBoundingClientRect().top - this.getBoundingClientRect().top;
}
} else {
this.tipEL.style.display = 'flex';
if (
row.rowType === TraceRow.ROW_TYPE_XPOWER_STATISTIC ||
row.rowType === TraceRow.ROW_TYPE_XPOWER_WIFI_BYTES ||
row.rowType === TraceRow.ROW_TYPE_XPOWER_WIFI_PACKETS ||
row.rowType === TraceRow.ROW_TYPE_XPOWER_APP_DETAIL_DISPLAY ||
row.rowType === TraceRow.ROW_TYPE_XPOWER_THREAD_INFO ||
row.rowType === TraceRow.ROW_TYPE_XPOWER_GPU_FREQUENCY
) {
this.tipEL.style.height = 'unset';
y = row.hoverY + row.getBoundingClientRect().top - this.getBoundingClientRect().top - this.tipEL.clientHeight;
} else {
this.tipEL.style.height = row.style.height;
}
}
if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) {
this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`;
} else {
this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`;
}
}
}
queryCPUWakeUpList(data: WakeupBean): void {
if (this._checkclick) {
this.wakeupListTbl!.loading = true;
}
TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: unknown) => {
if (a === null) {
window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList);
this.wakeupListTbl!.loading = false;
this._checkclick = false;
this.refreshCanvas(true);
return null;
}
SpSystemTrace.wakeupList.push(a);
this.queryCPUWakeUpList(a);
});
}
wakeupListNull(): SpSystemTrace {
SpSystemTrace.wakeupList = [];
return this;
}
initPointToEvent(): void {
spSystemTraceInitPointToEvent(this);
}
initHtml(): string {
return SpSystemTraceHtml;
}
}