1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { SpSystemTrace } from '../SpSystemTrace';
17fb726d48Sopenharmony_ciimport { TraceRow } from '../trace/base/TraceRow';
18fb726d48Sopenharmony_ciimport { Utils } from '../trace/base/Utils';
19fb726d48Sopenharmony_ciimport { PerfThread } from '../../bean/PerfProfile';
20fb726d48Sopenharmony_ciimport { HiPerfCpuStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2';
21fb726d48Sopenharmony_ciimport {
22fb726d48Sopenharmony_ci  HiPerfCallChartRender,
23fb726d48Sopenharmony_ci  HiPerfCallChartStruct,
24fb726d48Sopenharmony_ci} from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfCallChart';
25fb726d48Sopenharmony_ciimport { HiPerfThreadStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2';
26fb726d48Sopenharmony_ciimport { HiPerfProcessStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2';
27fb726d48Sopenharmony_ciimport { info } from '../../../log/Log';
28fb726d48Sopenharmony_ciimport { HiPerfEventStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent';
29fb726d48Sopenharmony_ciimport { perfDataQuery } from './PerfDataQuery';
30fb726d48Sopenharmony_ciimport { type HiPerfReportStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport';
31fb726d48Sopenharmony_ciimport { folderThreadHandler, getRowContext, rowThreadHandler, SpChartManager } from './SpChartManager';
32fb726d48Sopenharmony_ciimport { HiperfCpuRender2 } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2';
33fb726d48Sopenharmony_ciimport { hiperfCpuDataSender } from '../../database/data-trafic/hiperf/HiperfCpuDataSender';
34fb726d48Sopenharmony_ciimport { hiperfProcessDataSender } from '../../database/data-trafic/hiperf/HiperfProcessDataSender';
35fb726d48Sopenharmony_ciimport { HiperfProcessRender2 } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2';
36fb726d48Sopenharmony_ciimport { hiperfThreadDataSender } from '../../database/data-trafic/hiperf/HiperfThreadDataSender';
37fb726d48Sopenharmony_ciimport { HiperfThreadRender2 } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2';
38fb726d48Sopenharmony_ciimport {
39fb726d48Sopenharmony_ci  hiperfCallChartDataCacheSender,
40fb726d48Sopenharmony_ci  hiperfCallChartDataSender,
41fb726d48Sopenharmony_ci  hiperfCallStackCacheSender,
42fb726d48Sopenharmony_ci} from '../../database/data-trafic/hiperf/HiperfCallChartSender';
43fb726d48Sopenharmony_ciimport {
44fb726d48Sopenharmony_ci  queryHiPerfCpuMergeData2,
45fb726d48Sopenharmony_ci  queryPerfCmdline,
46fb726d48Sopenharmony_ci  queryPerfEventType,
47fb726d48Sopenharmony_ci  queryPerfThread,
48fb726d48Sopenharmony_ci} from '../../database/sql/Perf.sql';
49fb726d48Sopenharmony_ciimport { renders } from '../../database/ui-worker/ProcedureWorker';
50fb726d48Sopenharmony_ciimport { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil';
51fb726d48Sopenharmony_ci
52fb726d48Sopenharmony_ciexport interface ResultData {
53fb726d48Sopenharmony_ci  existA: boolean | null | undefined;
54fb726d48Sopenharmony_ci  existF: boolean | null | undefined;
55fb726d48Sopenharmony_ci  fValue: number;
56fb726d48Sopenharmony_ci}
57fb726d48Sopenharmony_ciconst FOLD_HEIGHT = 20;
58fb726d48Sopenharmony_ciexport class SpHiPerf {
59fb726d48Sopenharmony_ci  static selectCpuStruct: HiPerfCpuStruct | undefined;
60fb726d48Sopenharmony_ci  static stringResult: ResultData | undefined;
61fb726d48Sopenharmony_ci
62fb726d48Sopenharmony_ci  private cpuData: Array<unknown> | undefined;
63fb726d48Sopenharmony_ci  public maxCpuId: number = 0; //@ts-ignore
64fb726d48Sopenharmony_ci  private rowFolder!: TraceRow<unknown>;
65fb726d48Sopenharmony_ci  private perfThreads: Array<PerfThread> | undefined;
66fb726d48Sopenharmony_ci  private trace: SpSystemTrace;
67fb726d48Sopenharmony_ci  private group: unknown; //@ts-ignore
68fb726d48Sopenharmony_ci  private rowList: TraceRow<unknown>[] | undefined;
69fb726d48Sopenharmony_ci  private eventTypeList: Array<{ id: number; report: string }> = [];
70fb726d48Sopenharmony_ci  private callChartType: number = 0;
71fb726d48Sopenharmony_ci  private callChartId: number = 0;
72fb726d48Sopenharmony_ci  private eventTypeId: number = -2;
73fb726d48Sopenharmony_ci
74fb726d48Sopenharmony_ci  constructor(trace: SpSystemTrace) {
75fb726d48Sopenharmony_ci    this.trace = trace;
76fb726d48Sopenharmony_ci  }
77fb726d48Sopenharmony_ci
78fb726d48Sopenharmony_ci  async init(): Promise<void> {
79fb726d48Sopenharmony_ci    await this.initCmdLine();
80fb726d48Sopenharmony_ci    this.eventTypeList = await queryPerfEventType();
81fb726d48Sopenharmony_ci    this.rowList = [];
82fb726d48Sopenharmony_ci    this.perfThreads = await queryPerfThread();
83fb726d48Sopenharmony_ci    info('PerfThread Data size is: ', this.perfThreads!.length);
84fb726d48Sopenharmony_ci    this.group = Utils.groupBy(this.perfThreads || [], 'pid');
85fb726d48Sopenharmony_ci    this.cpuData = await queryHiPerfCpuMergeData2();
86fb726d48Sopenharmony_ci    this.callChartType = 0;
87fb726d48Sopenharmony_ci    this.callChartId = 0;
88fb726d48Sopenharmony_ci    this.eventTypeId = -2; //@ts-ignore
89fb726d48Sopenharmony_ci    this.maxCpuId = this.cpuData.length > 0 ? this.cpuData[0].cpu_id : -Infinity;
90fb726d48Sopenharmony_ci    if (this.cpuData.length > 0) {
91fb726d48Sopenharmony_ci      // 统计hiperf插件
92fb726d48Sopenharmony_ci      let requestBody = {
93fb726d48Sopenharmony_ci        eventData: {
94fb726d48Sopenharmony_ci          plugin: ['hiperf-plugin']
95fb726d48Sopenharmony_ci        }
96fb726d48Sopenharmony_ci      };
97fb726d48Sopenharmony_ci      SpStatisticsHttpUtil.recordPluginUsage(requestBody);
98fb726d48Sopenharmony_ci      await this.initFolder();
99fb726d48Sopenharmony_ci      await this.initCallChart();
100fb726d48Sopenharmony_ci      await this.initCpuMerge();
101fb726d48Sopenharmony_ci      await this.initCpu();
102fb726d48Sopenharmony_ci      await this.initProcess();
103fb726d48Sopenharmony_ci    }
104fb726d48Sopenharmony_ci    info('HiPerf Data initialized');
105fb726d48Sopenharmony_ci  }
106fb726d48Sopenharmony_ci
107fb726d48Sopenharmony_ci  getStringResult(s: string = ''): void {
108fb726d48Sopenharmony_ci    let list = s.split(' ');
109fb726d48Sopenharmony_ci    let sA = list.findIndex((item) => item === '-a');
110fb726d48Sopenharmony_ci    let sF = list.findIndex((item) => item === '-f');
111fb726d48Sopenharmony_ci    SpHiPerf.stringResult = {
112fb726d48Sopenharmony_ci      existA: sA !== -1,
113fb726d48Sopenharmony_ci      existF: sF !== -1,
114fb726d48Sopenharmony_ci      fValue: Number((1000 / (sF !== -1 ? parseInt(list[sF + 1]) : 1000)).toFixed(2)),
115fb726d48Sopenharmony_ci    };
116fb726d48Sopenharmony_ci  }
117fb726d48Sopenharmony_ci
118fb726d48Sopenharmony_ci  async initCmdLine(): Promise<void> {
119fb726d48Sopenharmony_ci    let perfCmdLines = await queryPerfCmdline();
120fb726d48Sopenharmony_ci    if (perfCmdLines.length > 0) {
121fb726d48Sopenharmony_ci      this.getStringResult(perfCmdLines[0].report_value);
122fb726d48Sopenharmony_ci    } else {
123fb726d48Sopenharmony_ci      SpHiPerf.stringResult = {
124fb726d48Sopenharmony_ci        existA: true,
125fb726d48Sopenharmony_ci        existF: false,
126fb726d48Sopenharmony_ci        fValue: 1,
127fb726d48Sopenharmony_ci      };
128fb726d48Sopenharmony_ci    }
129fb726d48Sopenharmony_ci  }
130fb726d48Sopenharmony_ci
131fb726d48Sopenharmony_ci  async initFolder(): Promise<void> {
132fb726d48Sopenharmony_ci    let row = TraceRow.skeleton();
133fb726d48Sopenharmony_ci    row.rowId = 'HiPerf';
134fb726d48Sopenharmony_ci    row.index = 0;
135fb726d48Sopenharmony_ci    row.rowType = TraceRow.ROW_TYPE_HIPERF;
136fb726d48Sopenharmony_ci    row.rowParentId = '';
137fb726d48Sopenharmony_ci    row.folder = true;
138fb726d48Sopenharmony_ci    row.drawType = -2;
139fb726d48Sopenharmony_ci    row.addRowSettingPop();
140fb726d48Sopenharmony_ci    row.rowSetting = 'enable';
141fb726d48Sopenharmony_ci    row.rowSettingPopoverDirection = 'bottomLeft';
142fb726d48Sopenharmony_ci    row.style.height = '40px';
143fb726d48Sopenharmony_ci    this.folderRowSettingConfig(row);
144fb726d48Sopenharmony_ci    if (SpHiPerf.stringResult?.existA === true) {
145fb726d48Sopenharmony_ci      row.name = 'HiPerf (All)';
146fb726d48Sopenharmony_ci    } else {
147fb726d48Sopenharmony_ci      //@ts-ignore
148fb726d48Sopenharmony_ci      let names = Reflect.ownKeys(this.group)
149fb726d48Sopenharmony_ci        .map((pid: unknown) => {
150fb726d48Sopenharmony_ci          //@ts-ignore
151fb726d48Sopenharmony_ci          let array = this.group[pid] as Array<PerfThread>;
152fb726d48Sopenharmony_ci          let process = array.filter((th) => th.pid === th.tid)[0];
153fb726d48Sopenharmony_ci          return process.processName;
154fb726d48Sopenharmony_ci        })
155fb726d48Sopenharmony_ci        .join(',');
156fb726d48Sopenharmony_ci      row.name = `HiPerf (${names})`;
157fb726d48Sopenharmony_ci    } //@ts-ignore
158fb726d48Sopenharmony_ci    row.supplier = (): Promise<Array<unknown>> => new Promise<Array<unknown>>((resolve) => resolve([]));
159fb726d48Sopenharmony_ci    row.onThreadHandler = folderThreadHandler(row, this.trace);
160fb726d48Sopenharmony_ci    this.rowFolder = row;
161fb726d48Sopenharmony_ci    this.trace.rowsEL?.appendChild(row);
162fb726d48Sopenharmony_ci  }
163fb726d48Sopenharmony_ci
164fb726d48Sopenharmony_ci  //@ts-ignore
165fb726d48Sopenharmony_ci  folderRowSettingConfig(row: TraceRow<unknown>): void {
166fb726d48Sopenharmony_ci    row.rowSettingList = [
167fb726d48Sopenharmony_ci      {
168fb726d48Sopenharmony_ci        key: '-2',
169fb726d48Sopenharmony_ci        title: 'Cpu Usage',
170fb726d48Sopenharmony_ci        checked: true,
171fb726d48Sopenharmony_ci      },
172fb726d48Sopenharmony_ci      ...this.eventTypeList.map((et) => {
173fb726d48Sopenharmony_ci        return {
174fb726d48Sopenharmony_ci          key: `${et.id}`,
175fb726d48Sopenharmony_ci          title: et.report,
176fb726d48Sopenharmony_ci        };
177fb726d48Sopenharmony_ci      }),
178fb726d48Sopenharmony_ci    ];
179fb726d48Sopenharmony_ci    row.onRowSettingChangeHandler = (value): void => {
180fb726d48Sopenharmony_ci      let drawType = parseInt(value[0]);
181fb726d48Sopenharmony_ci      if (this.eventTypeId !== drawType) {
182fb726d48Sopenharmony_ci        this.eventTypeId = drawType;
183fb726d48Sopenharmony_ci        row.drawType = drawType;
184fb726d48Sopenharmony_ci        row.childrenList.forEach((child): void => {
185fb726d48Sopenharmony_ci          if (child.drawType !== drawType) {
186fb726d48Sopenharmony_ci            child.drawType = drawType;
187fb726d48Sopenharmony_ci            child.needRefresh = true;
188fb726d48Sopenharmony_ci            child.isComplete = false;
189fb726d48Sopenharmony_ci            child.childrenList.forEach((sz) => {
190fb726d48Sopenharmony_ci              sz.drawType = drawType;
191fb726d48Sopenharmony_ci              sz.isComplete = false;
192fb726d48Sopenharmony_ci              sz.needRefresh = true;
193fb726d48Sopenharmony_ci            });
194fb726d48Sopenharmony_ci          }
195fb726d48Sopenharmony_ci        });
196fb726d48Sopenharmony_ci        TraceRow.range!.refresh = true;
197fb726d48Sopenharmony_ci        this.trace.refreshCanvas(false);
198fb726d48Sopenharmony_ci      }
199fb726d48Sopenharmony_ci    };
200fb726d48Sopenharmony_ci  }
201fb726d48Sopenharmony_ci
202fb726d48Sopenharmony_ci  async initCallChart(): Promise<void> {
203fb726d48Sopenharmony_ci    await hiperfCallStackCacheSender();
204fb726d48Sopenharmony_ci    await hiperfCallChartDataCacheSender();
205fb726d48Sopenharmony_ci    let perfCallCutRow = TraceRow.skeleton<HiPerfCallChartStruct>();
206fb726d48Sopenharmony_ci    perfCallCutRow.rowId = 'HiPerf-callchart';
207fb726d48Sopenharmony_ci    perfCallCutRow.index = 0;
208fb726d48Sopenharmony_ci    perfCallCutRow.rowType = TraceRow.ROW_TYPE_PERF_CALLCHART;
209fb726d48Sopenharmony_ci    perfCallCutRow.enableCollapseChart(FOLD_HEIGHT, this.trace);
210fb726d48Sopenharmony_ci    perfCallCutRow.rowParentId = 'HiPerf';
211fb726d48Sopenharmony_ci    perfCallCutRow.rowHidden = !this.rowFolder.expansion;
212fb726d48Sopenharmony_ci    perfCallCutRow.folder = false;
213fb726d48Sopenharmony_ci    perfCallCutRow.drawType = -2;
214fb726d48Sopenharmony_ci    perfCallCutRow.name = 'CallChart [cpu0]';
215fb726d48Sopenharmony_ci    perfCallCutRow.funcExpand = false;
216fb726d48Sopenharmony_ci    perfCallCutRow.setAttribute('children', '');
217fb726d48Sopenharmony_ci    perfCallCutRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
218fb726d48Sopenharmony_ci    perfCallCutRow.selectChangeHandler = this.trace.selectChangeHandler;
219fb726d48Sopenharmony_ci    this.rowFolder.addChildTraceRow(perfCallCutRow);
220fb726d48Sopenharmony_ci    perfCallCutRow.focusHandler = (): void => {
221fb726d48Sopenharmony_ci      this.callChartRowFocusHandler(perfCallCutRow);
222fb726d48Sopenharmony_ci    };
223fb726d48Sopenharmony_ci    // @ts-ignore
224fb726d48Sopenharmony_ci    perfCallCutRow.supplierFrame = async (): Promise<unknown> => {
225fb726d48Sopenharmony_ci      const res = await hiperfCallChartDataSender(perfCallCutRow, {
226fb726d48Sopenharmony_ci        startTime: window.recordStartNS,
227fb726d48Sopenharmony_ci        eventTypeId: this.eventTypeId,
228fb726d48Sopenharmony_ci        type: this.callChartType,
229fb726d48Sopenharmony_ci        id: this.callChartId,
230fb726d48Sopenharmony_ci      });
231fb726d48Sopenharmony_ci      // @ts-ignore
232fb726d48Sopenharmony_ci      let maxHeight = res.maxDepth * FOLD_HEIGHT;
233fb726d48Sopenharmony_ci      perfCallCutRow.funcMaxHeight = maxHeight;
234fb726d48Sopenharmony_ci      if (perfCallCutRow.funcExpand) {
235fb726d48Sopenharmony_ci        perfCallCutRow!.style.height = `${maxHeight}px`;
236fb726d48Sopenharmony_ci        if (perfCallCutRow.collect) {
237fb726d48Sopenharmony_ci          window.publish(window.SmartEvent.UI.RowHeightChange, {
238fb726d48Sopenharmony_ci            expand: true,
239fb726d48Sopenharmony_ci            value: perfCallCutRow.funcMaxHeight - FOLD_HEIGHT,
240fb726d48Sopenharmony_ci          });
241fb726d48Sopenharmony_ci        }
242fb726d48Sopenharmony_ci      }
243fb726d48Sopenharmony_ci      // @ts-ignore
244fb726d48Sopenharmony_ci      return res.dataList;
245fb726d48Sopenharmony_ci    };
246fb726d48Sopenharmony_ci    perfCallCutRow.findHoverStruct = (): void => {
247fb726d48Sopenharmony_ci      HiPerfCallChartStruct.hoverPerfCallCutStruct = perfCallCutRow.getHoverStruct();
248fb726d48Sopenharmony_ci    };
249fb726d48Sopenharmony_ci    await this.setCallTotalRow(perfCallCutRow, this.cpuData, this.perfThreads);
250fb726d48Sopenharmony_ci  }
251fb726d48Sopenharmony_ci
252fb726d48Sopenharmony_ci  callChartRowFocusHandler(perfCallCutRow: TraceRow<HiPerfCallChartStruct>): void {
253fb726d48Sopenharmony_ci    let hoverStruct = HiPerfCallChartStruct.hoverPerfCallCutStruct;
254fb726d48Sopenharmony_ci    if (hoverStruct) {
255fb726d48Sopenharmony_ci      let callName = hoverStruct.name;
256fb726d48Sopenharmony_ci      callName = callName.replace(/</g, '&lt;').replace(/>/g, '&gt;');
257fb726d48Sopenharmony_ci      this.trace?.displayTip(
258fb726d48Sopenharmony_ci        perfCallCutRow!,
259fb726d48Sopenharmony_ci        hoverStruct,
260fb726d48Sopenharmony_ci        `<span style="font-weight: bold;color:'#000'">Name: </span>
261fb726d48Sopenharmony_ci        <span>${callName}</span><br>
262fb726d48Sopenharmony_ci        <span style='font-weight: bold;'>Lib: </span>
263fb726d48Sopenharmony_ci        <span>${perfDataQuery.getLibName(hoverStruct!.fileId, hoverStruct!.symbolId)}</span><br>
264fb726d48Sopenharmony_ci        <span style='font-weight: bold;'>Self Time: </span>
265fb726d48Sopenharmony_ci        <span>${Utils.getProbablyTime(hoverStruct.selfDur || 0)}</span><br>
266fb726d48Sopenharmony_ci        <span style='font-weight: bold;'>Duration: </span>
267fb726d48Sopenharmony_ci        <span>${Utils.getProbablyTime(hoverStruct.totalTime)}</span><br>
268fb726d48Sopenharmony_ci        <span style='font-weight: bold;'>Event Count: </span>
269fb726d48Sopenharmony_ci        <span>${hoverStruct.eventCount || ''}</span><br>`
270fb726d48Sopenharmony_ci      );
271fb726d48Sopenharmony_ci    }
272fb726d48Sopenharmony_ci  }
273fb726d48Sopenharmony_ci
274fb726d48Sopenharmony_ci  //@ts-ignore
275fb726d48Sopenharmony_ci  async setCallTotalRow(row: TraceRow<unknown>, cpuData: unknown = Array, threadData: unknown = Array): Promise<void> {
276fb726d48Sopenharmony_ci    //@ts-ignore
277fb726d48Sopenharmony_ci    let pt: Map<string, unknown> = threadData.reduce((map: Map<string, unknown>, current: unknown) => {
278fb726d48Sopenharmony_ci      //@ts-ignore
279fb726d48Sopenharmony_ci      const key = `${current.processName || 'Process'}(${current.pid})`;
280fb726d48Sopenharmony_ci      const thread = {
281fb726d48Sopenharmony_ci        //@ts-ignore
282fb726d48Sopenharmony_ci        key: `${current.tid}-t`, //@ts-ignore
283fb726d48Sopenharmony_ci        title: `${current.threadName || 'Thread'}(${current.tid})`,
284fb726d48Sopenharmony_ci      };
285fb726d48Sopenharmony_ci      if (map.has(key)) {
286fb726d48Sopenharmony_ci        //@ts-ignore
287fb726d48Sopenharmony_ci        if (map.get(key).children) {
288fb726d48Sopenharmony_ci          //@ts-ignore
289fb726d48Sopenharmony_ci          map.get(key).children.push(thread);
290fb726d48Sopenharmony_ci        } else {
291fb726d48Sopenharmony_ci          //@ts-ignore
292fb726d48Sopenharmony_ci          map.get(key).children = [thread];
293fb726d48Sopenharmony_ci        }
294fb726d48Sopenharmony_ci      } else {
295fb726d48Sopenharmony_ci        map.set(key, {
296fb726d48Sopenharmony_ci          //@ts-ignore
297fb726d48Sopenharmony_ci          key: `${current.pid}-p`,
298fb726d48Sopenharmony_ci          title: key,
299fb726d48Sopenharmony_ci          children: [thread],
300fb726d48Sopenharmony_ci          disable: true,
301fb726d48Sopenharmony_ci        });
302fb726d48Sopenharmony_ci      }
303fb726d48Sopenharmony_ci      return map;
304fb726d48Sopenharmony_ci    }, new Map<string, unknown>());
305fb726d48Sopenharmony_ci    row.addTemplateTypes('hiperf-callchart');
306fb726d48Sopenharmony_ci    row.addRowSettingPop();
307fb726d48Sopenharmony_ci    row.rowSetting = 'enable'; //@ts-ignore
308fb726d48Sopenharmony_ci    this.setCallChartRowSetting(row, cpuData, pt);
309fb726d48Sopenharmony_ci    row.onThreadHandler = rowThreadHandler<HiPerfCallChartRender>(
310fb726d48Sopenharmony_ci      'HiPerf-callchart',
311fb726d48Sopenharmony_ci      'context',
312fb726d48Sopenharmony_ci      {
313fb726d48Sopenharmony_ci        type: 'HiPerf-callchart',
314fb726d48Sopenharmony_ci      },
315fb726d48Sopenharmony_ci      row,
316fb726d48Sopenharmony_ci      this.trace
317fb726d48Sopenharmony_ci    );
318fb726d48Sopenharmony_ci  }
319fb726d48Sopenharmony_ci
320fb726d48Sopenharmony_ci  setCallChartRowSetting(
321fb726d48Sopenharmony_ci    row: TraceRow<HiPerfCallChartStruct>,
322fb726d48Sopenharmony_ci    cpuData: Array<unknown>,
323fb726d48Sopenharmony_ci    pt: Map<string, unknown>
324fb726d48Sopenharmony_ci  ): void {
325fb726d48Sopenharmony_ci    //@ts-ignore
326fb726d48Sopenharmony_ci    row.rowSettingList = [
327fb726d48Sopenharmony_ci      ...cpuData.reverse().map(
328fb726d48Sopenharmony_ci        (
329fb726d48Sopenharmony_ci          it: unknown
330fb726d48Sopenharmony_ci        ): {
331fb726d48Sopenharmony_ci          key: string;
332fb726d48Sopenharmony_ci          title: string;
333fb726d48Sopenharmony_ci          checked?: boolean;
334fb726d48Sopenharmony_ci        } => {
335fb726d48Sopenharmony_ci          return {
336fb726d48Sopenharmony_ci            //@ts-ignore
337fb726d48Sopenharmony_ci            key: `${it.cpu_id}-c`,
338fb726d48Sopenharmony_ci            //@ts-ignore
339fb726d48Sopenharmony_ci            checked: it.cpu_id === 0,
340fb726d48Sopenharmony_ci            //@ts-ignore
341fb726d48Sopenharmony_ci            title: `cpu${it.cpu_id}`,
342fb726d48Sopenharmony_ci          };
343fb726d48Sopenharmony_ci        }
344fb726d48Sopenharmony_ci      ),
345fb726d48Sopenharmony_ci      ...Array.from(pt.values()),
346fb726d48Sopenharmony_ci    ];
347fb726d48Sopenharmony_ci    row.onRowSettingChangeHandler = (setting: unknown, nodes): void => {
348fb726d48Sopenharmony_ci      //@ts-ignore
349fb726d48Sopenharmony_ci      if (setting && setting.length > 0) {
350fb726d48Sopenharmony_ci        //type 0:cpu,1:process,2:thread
351fb726d48Sopenharmony_ci        //@ts-ignore
352fb726d48Sopenharmony_ci        let key: string = setting[0];
353fb726d48Sopenharmony_ci        let type = this.callChartType;
354fb726d48Sopenharmony_ci        if (key.includes('p')) {
355fb726d48Sopenharmony_ci          type = 1;
356fb726d48Sopenharmony_ci        } else if (key.includes('t')) {
357fb726d48Sopenharmony_ci          type = 2;
358fb726d48Sopenharmony_ci        } else {
359fb726d48Sopenharmony_ci          type = 0;
360fb726d48Sopenharmony_ci        }
361fb726d48Sopenharmony_ci        let id = Number(key.split('-')[0]);
362fb726d48Sopenharmony_ci        if (this.callChartType === type && this.callChartId === id) {
363fb726d48Sopenharmony_ci          return;
364fb726d48Sopenharmony_ci        }
365fb726d48Sopenharmony_ci        this.callChartType = type;
366fb726d48Sopenharmony_ci        this.callChartId = id; // @ts-ignore
367fb726d48Sopenharmony_ci        row.name = `CallChart [${nodes[0].title}]`;
368fb726d48Sopenharmony_ci        row.isComplete = false;
369fb726d48Sopenharmony_ci        row.needRefresh = true;
370fb726d48Sopenharmony_ci        row.drawFrame();
371fb726d48Sopenharmony_ci      }
372fb726d48Sopenharmony_ci    };
373fb726d48Sopenharmony_ci  }
374fb726d48Sopenharmony_ci
375fb726d48Sopenharmony_ci  async initCpuMerge(): Promise<void> {
376fb726d48Sopenharmony_ci    let cpuMergeRow = TraceRow.skeleton<HiPerfCpuStruct>();
377fb726d48Sopenharmony_ci    cpuMergeRow.rowId = 'HiPerf-cpu-merge';
378fb726d48Sopenharmony_ci    cpuMergeRow.index = 0;
379fb726d48Sopenharmony_ci    cpuMergeRow.rowType = TraceRow.ROW_TYPE_HIPERF_CPU;
380fb726d48Sopenharmony_ci    cpuMergeRow.rowParentId = 'HiPerf';
381fb726d48Sopenharmony_ci    cpuMergeRow.rowHidden = !this.rowFolder.expansion;
382fb726d48Sopenharmony_ci    cpuMergeRow.folder = false;
383fb726d48Sopenharmony_ci    cpuMergeRow.drawType = -2;
384fb726d48Sopenharmony_ci    cpuMergeRow.name = 'HiPerf';
385fb726d48Sopenharmony_ci    cpuMergeRow.style.height = '40px';
386fb726d48Sopenharmony_ci    cpuMergeRow.setAttribute('children', '');
387fb726d48Sopenharmony_ci    cpuMergeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
388fb726d48Sopenharmony_ci    cpuMergeRow.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore
389fb726d48Sopenharmony_ci    cpuMergeRow.supplierFrame = (): Promise<unknown> => {
390fb726d48Sopenharmony_ci      return hiperfCpuDataSender(
391fb726d48Sopenharmony_ci        -1,
392fb726d48Sopenharmony_ci        cpuMergeRow.drawType,
393fb726d48Sopenharmony_ci        this.maxCpuId + 1,
394fb726d48Sopenharmony_ci        SpHiPerf.stringResult?.fValue || 1,
395fb726d48Sopenharmony_ci        TraceRow.range?.scale || 50,
396fb726d48Sopenharmony_ci        cpuMergeRow
397fb726d48Sopenharmony_ci      );
398fb726d48Sopenharmony_ci    };
399fb726d48Sopenharmony_ci    cpuMergeRow.focusHandler = (): void => this.hoverTip(cpuMergeRow, HiPerfCpuStruct.hoverStruct);
400fb726d48Sopenharmony_ci    cpuMergeRow.findHoverStruct = (): void => {
401fb726d48Sopenharmony_ci      HiPerfCpuStruct.hoverStruct = cpuMergeRow.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000);
402fb726d48Sopenharmony_ci    };
403fb726d48Sopenharmony_ci    cpuMergeRow.onThreadHandler = this.rowThreadHandler<HiperfCpuRender2>(
404fb726d48Sopenharmony_ci      'HiPerf-Cpu-2',
405fb726d48Sopenharmony_ci      'context',
406fb726d48Sopenharmony_ci      {
407fb726d48Sopenharmony_ci        type: 'HiPerf-Cpu-Merge',
408fb726d48Sopenharmony_ci        maxCpu: this.maxCpuId + 1,
409fb726d48Sopenharmony_ci        intervalPerf: SpHiPerf.stringResult?.fValue || 1,
410fb726d48Sopenharmony_ci      },
411fb726d48Sopenharmony_ci      cpuMergeRow,
412fb726d48Sopenharmony_ci      this.trace
413fb726d48Sopenharmony_ci    );
414fb726d48Sopenharmony_ci    this.rowFolder.addChildTraceRow(cpuMergeRow);
415fb726d48Sopenharmony_ci    this.rowList?.push(cpuMergeRow);
416fb726d48Sopenharmony_ci  }
417fb726d48Sopenharmony_ci
418fb726d48Sopenharmony_ci  //@ts-ignore
419fb726d48Sopenharmony_ci  rowThreadHandler<T>(tag: string, contextField: string, arg: unknown, row: TraceRow<unknown>, trace: SpSystemTrace) {
420fb726d48Sopenharmony_ci    return (useCache: boolean): void => {
421fb726d48Sopenharmony_ci      let context: CanvasRenderingContext2D = getRowContext(row, trace);
422fb726d48Sopenharmony_ci      row.canvasSave(context); //@ts-ignore
423fb726d48Sopenharmony_ci      arg.useCache = useCache; //@ts-ignore
424fb726d48Sopenharmony_ci      arg.scale = TraceRow.range?.scale || 50; //@ts-ignore
425fb726d48Sopenharmony_ci      arg.range = TraceRow.range;
426fb726d48Sopenharmony_ci      if (contextField) {
427fb726d48Sopenharmony_ci        //@ts-ignore
428fb726d48Sopenharmony_ci        arg[contextField] = context;
429fb726d48Sopenharmony_ci      } //@ts-ignore
430fb726d48Sopenharmony_ci      (renders[tag] as unknown).renderMainThread(arg, row);
431fb726d48Sopenharmony_ci      row.canvasRestore(context, trace);
432fb726d48Sopenharmony_ci    };
433fb726d48Sopenharmony_ci  }
434fb726d48Sopenharmony_ci
435fb726d48Sopenharmony_ci  async initCpu(): Promise<void> {
436fb726d48Sopenharmony_ci    for (let i = 0; i <= this.maxCpuId; i++) {
437fb726d48Sopenharmony_ci      let perfCpuRow = TraceRow.skeleton<HiPerfCpuStruct>();
438fb726d48Sopenharmony_ci      perfCpuRow.rowId = `HiPerf-cpu-${i}`;
439fb726d48Sopenharmony_ci      perfCpuRow.index = i;
440fb726d48Sopenharmony_ci      perfCpuRow.rowType = TraceRow.ROW_TYPE_HIPERF_CPU;
441fb726d48Sopenharmony_ci      perfCpuRow.rowParentId = 'HiPerf';
442fb726d48Sopenharmony_ci      perfCpuRow.rowHidden = !this.rowFolder.expansion;
443fb726d48Sopenharmony_ci      perfCpuRow.folder = false;
444fb726d48Sopenharmony_ci      perfCpuRow.drawType = -2;
445fb726d48Sopenharmony_ci      perfCpuRow.name = `Cpu ${i}`;
446fb726d48Sopenharmony_ci      perfCpuRow.setAttribute('children', '');
447fb726d48Sopenharmony_ci      perfCpuRow.favoriteChangeHandler = this.trace.favoriteChangeHandler;
448fb726d48Sopenharmony_ci      perfCpuRow.selectChangeHandler = this.trace.selectChangeHandler;
449fb726d48Sopenharmony_ci      perfCpuRow.style.height = '40px'; //@ts-ignore
450fb726d48Sopenharmony_ci      perfCpuRow.supplierFrame = (): Promise<unknown> => {
451fb726d48Sopenharmony_ci        return hiperfCpuDataSender(
452fb726d48Sopenharmony_ci          i,
453fb726d48Sopenharmony_ci          perfCpuRow.drawType,
454fb726d48Sopenharmony_ci          this.maxCpuId + 1,
455fb726d48Sopenharmony_ci          SpHiPerf.stringResult?.fValue || 1,
456fb726d48Sopenharmony_ci          TraceRow.range?.scale || 50,
457fb726d48Sopenharmony_ci          perfCpuRow
458fb726d48Sopenharmony_ci        );
459fb726d48Sopenharmony_ci      };
460fb726d48Sopenharmony_ci      perfCpuRow.focusHandler = (): void => this.hoverTip(perfCpuRow, HiPerfCpuStruct.hoverStruct);
461fb726d48Sopenharmony_ci      perfCpuRow.findHoverStruct = (): void => {
462fb726d48Sopenharmony_ci        HiPerfCpuStruct.hoverStruct = perfCpuRow.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000);
463fb726d48Sopenharmony_ci      };
464fb726d48Sopenharmony_ci      perfCpuRow.onThreadHandler = this.rowThreadHandler<HiperfCpuRender2>(
465fb726d48Sopenharmony_ci        'HiPerf-Cpu-2',
466fb726d48Sopenharmony_ci        'context',
467fb726d48Sopenharmony_ci        {
468fb726d48Sopenharmony_ci          type: `HiPerf-Cpu-${i}`,
469fb726d48Sopenharmony_ci          maxCpu: this.maxCpuId + 1,
470fb726d48Sopenharmony_ci          intervalPerf: SpHiPerf.stringResult?.fValue || 1,
471fb726d48Sopenharmony_ci        },
472fb726d48Sopenharmony_ci        perfCpuRow,
473fb726d48Sopenharmony_ci        this.trace
474fb726d48Sopenharmony_ci      );
475fb726d48Sopenharmony_ci      this.rowFolder.addChildTraceRow(perfCpuRow);
476fb726d48Sopenharmony_ci      this.rowList?.push(perfCpuRow);
477fb726d48Sopenharmony_ci    }
478fb726d48Sopenharmony_ci  }
479fb726d48Sopenharmony_ci
480fb726d48Sopenharmony_ci  async initProcess(): Promise<void> {
481fb726d48Sopenharmony_ci    //@ts-ignore
482fb726d48Sopenharmony_ci    Reflect.ownKeys(this.group).forEach((key, index): void => {
483fb726d48Sopenharmony_ci      //@ts-ignore
484fb726d48Sopenharmony_ci      let array = this.group[key] as Array<PerfThread>;
485fb726d48Sopenharmony_ci      let process = array.filter((th): boolean => th.pid === th.tid)[0];
486fb726d48Sopenharmony_ci      let row = TraceRow.skeleton<HiPerfProcessStruct>();
487fb726d48Sopenharmony_ci      row.rowId = `${process.pid}-Perf-Process`;
488fb726d48Sopenharmony_ci      row.index = index;
489fb726d48Sopenharmony_ci      row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS;
490fb726d48Sopenharmony_ci      row.rowParentId = 'HiPerf';
491fb726d48Sopenharmony_ci      row.rowHidden = !this.rowFolder.expansion;
492fb726d48Sopenharmony_ci      row.folder = true;
493fb726d48Sopenharmony_ci      row.drawType = -2;
494fb726d48Sopenharmony_ci      if (SpChartManager.APP_STARTUP_PID_ARR.find((pid) => pid === process.pid) !== undefined) {
495fb726d48Sopenharmony_ci        row.addTemplateTypes('AppStartup');
496fb726d48Sopenharmony_ci      }
497fb726d48Sopenharmony_ci      row.addTemplateTypes('HiPerf');
498fb726d48Sopenharmony_ci      row.name = `${process.processName || 'Process'} [${process.pid}]`;
499fb726d48Sopenharmony_ci      row.folderPaddingLeft = 6;
500fb726d48Sopenharmony_ci      row.style.height = '40px';
501fb726d48Sopenharmony_ci      row.favoriteChangeHandler = this.trace.favoriteChangeHandler;
502fb726d48Sopenharmony_ci      row.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore
503fb726d48Sopenharmony_ci      row.supplierFrame = (): Promise<unknown> => {
504fb726d48Sopenharmony_ci        return hiperfProcessDataSender(
505fb726d48Sopenharmony_ci          process.pid,
506fb726d48Sopenharmony_ci          row.drawType,
507fb726d48Sopenharmony_ci          this.maxCpuId + 1,
508fb726d48Sopenharmony_ci          SpHiPerf.stringResult?.fValue || 1,
509fb726d48Sopenharmony_ci          TraceRow.range?.scale || 50,
510fb726d48Sopenharmony_ci          row
511fb726d48Sopenharmony_ci        );
512fb726d48Sopenharmony_ci      };
513fb726d48Sopenharmony_ci      row.focusHandler = (): void => this.hoverTip(row, HiPerfProcessStruct.hoverStruct);
514fb726d48Sopenharmony_ci      row.findHoverStruct = (): void => {
515fb726d48Sopenharmony_ci        HiPerfProcessStruct.hoverStruct = row.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000);
516fb726d48Sopenharmony_ci      };
517fb726d48Sopenharmony_ci      row.onThreadHandler = this.rowThreadHandler<HiperfProcessRender2>(
518fb726d48Sopenharmony_ci        'HiPerf-Process-2',
519fb726d48Sopenharmony_ci        'context',
520fb726d48Sopenharmony_ci        {
521fb726d48Sopenharmony_ci          type: `HiPerf-Process-${row.index}`,
522fb726d48Sopenharmony_ci          intervalPerf: SpHiPerf.stringResult?.fValue || 1,
523fb726d48Sopenharmony_ci        },
524fb726d48Sopenharmony_ci        row,
525fb726d48Sopenharmony_ci        this.trace
526fb726d48Sopenharmony_ci      );
527fb726d48Sopenharmony_ci      this.rowFolder.addChildTraceRow(row);
528fb726d48Sopenharmony_ci      this.rowList?.push(row);
529fb726d48Sopenharmony_ci      this.addHiPerfThreadRow(array, row);
530fb726d48Sopenharmony_ci    });
531fb726d48Sopenharmony_ci  }
532fb726d48Sopenharmony_ci
533fb726d48Sopenharmony_ci  addHiPerfThreadRow(array: PerfThread[], row: TraceRow<HiPerfProcessStruct>): void {
534fb726d48Sopenharmony_ci    array.forEach((thObj, thIdx): void => {
535fb726d48Sopenharmony_ci      let thread = TraceRow.skeleton<HiPerfThreadStruct>();
536fb726d48Sopenharmony_ci      thread.rowId = `${thObj.tid}-Perf-Thread`;
537fb726d48Sopenharmony_ci      thread.index = thIdx;
538fb726d48Sopenharmony_ci      thread.rowType = TraceRow.ROW_TYPE_HIPERF_THREAD;
539fb726d48Sopenharmony_ci      thread.rowParentId = row.rowId;
540fb726d48Sopenharmony_ci      thread.rowHidden = !row.expansion;
541fb726d48Sopenharmony_ci      thread.folder = false;
542fb726d48Sopenharmony_ci      thread.drawType = -2;
543fb726d48Sopenharmony_ci      thread.name = `${thObj.threadName || 'Thread'} [${thObj.tid}]`;
544fb726d48Sopenharmony_ci      thread.setAttribute('children', '');
545fb726d48Sopenharmony_ci      thread.folderPaddingLeft = 0;
546fb726d48Sopenharmony_ci      thread.style.height = '40px';
547fb726d48Sopenharmony_ci      thread.favoriteChangeHandler = this.trace.favoriteChangeHandler;
548fb726d48Sopenharmony_ci      thread.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore
549fb726d48Sopenharmony_ci      thread.supplierFrame = (): Promise<unknown> => {
550fb726d48Sopenharmony_ci        return hiperfThreadDataSender(
551fb726d48Sopenharmony_ci          thObj.tid,
552fb726d48Sopenharmony_ci          thread.drawType,
553fb726d48Sopenharmony_ci          this.maxCpuId + 1,
554fb726d48Sopenharmony_ci          SpHiPerf.stringResult?.fValue || 1,
555fb726d48Sopenharmony_ci          TraceRow.range?.scale || 50,
556fb726d48Sopenharmony_ci          thread
557fb726d48Sopenharmony_ci        );
558fb726d48Sopenharmony_ci      };
559fb726d48Sopenharmony_ci      thread.focusHandler = (): void => this.hoverTip(thread, HiPerfThreadStruct.hoverStruct);
560fb726d48Sopenharmony_ci      thread.findHoverStruct = (): void => {
561fb726d48Sopenharmony_ci        HiPerfThreadStruct.hoverStruct = thread.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000);
562fb726d48Sopenharmony_ci      };
563fb726d48Sopenharmony_ci      thread.onThreadHandler = this.rowThreadHandler<HiperfThreadRender2>(
564fb726d48Sopenharmony_ci        'HiPerf-Thread-2',
565fb726d48Sopenharmony_ci        'context',
566fb726d48Sopenharmony_ci        {
567fb726d48Sopenharmony_ci          type: `HiPerf-Thread-${row.index}-${thread.index}`,
568fb726d48Sopenharmony_ci          intervalPerf: SpHiPerf.stringResult?.fValue || 1,
569fb726d48Sopenharmony_ci        },
570fb726d48Sopenharmony_ci        thread,
571fb726d48Sopenharmony_ci        this.trace
572fb726d48Sopenharmony_ci      );
573fb726d48Sopenharmony_ci      row.addChildTraceRow(thread);
574fb726d48Sopenharmony_ci      this.rowList?.push(thread);
575fb726d48Sopenharmony_ci    });
576fb726d48Sopenharmony_ci  }
577fb726d48Sopenharmony_ci
578fb726d48Sopenharmony_ci  //@ts-ignore
579fb726d48Sopenharmony_ci  resetChartData(row: TraceRow<unknown>): void {
580fb726d48Sopenharmony_ci    row.dataList = [];
581fb726d48Sopenharmony_ci    row.dataList2 = [];
582fb726d48Sopenharmony_ci    row.dataListCache = [];
583fb726d48Sopenharmony_ci    row.isComplete = false;
584fb726d48Sopenharmony_ci  }
585fb726d48Sopenharmony_ci
586fb726d48Sopenharmony_ci  resetAllChartData(): void {
587fb726d48Sopenharmony_ci    const callChartRow = this.rowList?.find(row => row.rowId === 'HiPerf-callchart');
588fb726d48Sopenharmony_ci    if (callChartRow) {
589fb726d48Sopenharmony_ci      this.resetChartData(callChartRow);
590fb726d48Sopenharmony_ci    }
591fb726d48Sopenharmony_ci  }
592fb726d48Sopenharmony_ci
593fb726d48Sopenharmony_ci  hoverTip(
594fb726d48Sopenharmony_ci    //@ts-ignore
595fb726d48Sopenharmony_ci    row: TraceRow<unknown>,
596fb726d48Sopenharmony_ci    struct:
597fb726d48Sopenharmony_ci      | HiPerfThreadStruct
598fb726d48Sopenharmony_ci      | HiPerfProcessStruct
599fb726d48Sopenharmony_ci      | HiPerfEventStruct
600fb726d48Sopenharmony_ci      | HiPerfReportStruct
601fb726d48Sopenharmony_ci      | HiPerfCpuStruct
602fb726d48Sopenharmony_ci      | undefined
603fb726d48Sopenharmony_ci  ): void {
604fb726d48Sopenharmony_ci    let tip = '';
605fb726d48Sopenharmony_ci    let groupBy10MS = (TraceRow.range?.scale || 50) > 30_000_000;
606fb726d48Sopenharmony_ci    if (struct) {
607fb726d48Sopenharmony_ci      if (groupBy10MS) {
608fb726d48Sopenharmony_ci        if (row.drawType === -2) {
609fb726d48Sopenharmony_ci          let num: number | string = 0;
610fb726d48Sopenharmony_ci          if (struct instanceof HiPerfEventStruct) {
611fb726d48Sopenharmony_ci            num = Math.trunc(((struct.sum || 0) / (struct.max || 0)) * 100);
612fb726d48Sopenharmony_ci          } else {
613fb726d48Sopenharmony_ci            let interval = SpHiPerf.stringResult?.fValue || 1;
614fb726d48Sopenharmony_ci            num = ((struct.sampleCount! / (10 / interval)) * 100).toFixed(2);
615fb726d48Sopenharmony_ci          }
616fb726d48Sopenharmony_ci          tip = `<span>${num}% (10.00ms)</span>`;
617fb726d48Sopenharmony_ci        } else {
618fb726d48Sopenharmony_ci          tip = `<span>${struct.event_count || struct.eventCount} (10.00ms)</span>`;
619fb726d48Sopenharmony_ci        }
620fb726d48Sopenharmony_ci      } else {
621fb726d48Sopenharmony_ci        let perfCall = perfDataQuery.callChainMap.get(struct.callchain_id || 0);
622fb726d48Sopenharmony_ci        if (perfCall) {
623fb726d48Sopenharmony_ci          let perfName;
624fb726d48Sopenharmony_ci          typeof perfCall.name === 'number'
625fb726d48Sopenharmony_ci            ? (perfName = SpSystemTrace.DATA_DICT.get(parseInt(perfCall.name)))
626fb726d48Sopenharmony_ci            : (perfName = perfCall.name);
627fb726d48Sopenharmony_ci          tip = `<span>${perfCall ? perfName : ''} (${perfCall ? perfCall.depth : '0'} other frames)</span>`;
628fb726d48Sopenharmony_ci        }
629fb726d48Sopenharmony_ci      }
630fb726d48Sopenharmony_ci    }
631fb726d48Sopenharmony_ci    this.trace?.displayTip(row, struct, tip);
632fb726d48Sopenharmony_ci  }
633fb726d48Sopenharmony_ci}
634