• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { SelectionParam } from '../../../bean/BoxSelection';
17import { procedurePool } from '../../../database/Procedure';
18import { queryNativeHookResponseTypes } from '../../../database/sql/NativeHook.sql';
19import { TraceMode } from '../../../SpApplicationPublicFunc';
20
21export class Utils {
22  static isTransformed: boolean = false;
23  static currentSelectTrace: string | null | undefined;
24  static currentTraceMode: TraceMode = TraceMode.NORMAL;
25  static distributedTrace: string[] = [];
26  static isRangeSelectRefresh: boolean = false;
27  static currentTraceName: string = '';
28  static DMAFENCECAT_MAP: Map<
29    number,
30    {
31      id: number;
32      cat: string;
33      seqno: number;
34      driver: string;
35      context: string
36    }> = new Map<
37      number,
38      {
39        id: number;
40        cat: string;
41        seqno: number;
42        driver: string;
43        context: string
44      }
45    >();
46  private static statusMap: Map<string, string> = new Map<string, string>();
47  private static instance: Utils | null = null;
48  private trace1CpuCount: number = 1;
49  private trace1WinCpuCount: number = 1;
50  private trace2CpuCount: number = 1;
51  private trace2WinCpuCount: number = 1;
52  trace1RecordStartNS: number = 1;
53  trace2RecordStartNS: number = 1;
54  trace1RecordEndNS: number = 1;
55  trace2RecordEndNS: number = 1;
56  totalNS: number = 1;
57  private trace1ThreadMap: Map<number, string> = new Map<number, string>();
58  private trace1ProcessMap: Map<number, string> = new Map<number, string>();
59  sysCallEventTidsMap: Map<number, { tid: number; pid: number, itid: number, ipid: number }> = new Map();
60  private trace1SchedSliceMap: Map<
61    string,
62    {
63      endState: string;
64      priority: number;
65    }
66  > = new Map<
67    string,
68    {
69      endState: string;
70      priority: number;
71    }
72  >();
73  private trace2ThreadMap: Map<number, string> = new Map<number, string>();
74  private trace2ProcessMap: Map<number, string> = new Map<number, string>();
75  private trace2SchedSliceMap: Map<
76    string,
77    {
78      endState: string;
79      priority: number;
80    }
81  > = new Map<
82    string,
83    {
84      endState: string;
85      priority: number;
86    }
87  >();
88  private callStackMap: Map<number | string, string> = new Map<number | string, string>();
89
90  constructor() {
91    Utils.statusMap.set('D', 'Uninterruptible Sleep');
92    Utils.statusMap.set('D-NIO', 'Uninterruptible Sleep(non-IO)');
93    Utils.statusMap.set('D-IO', 'Uninterruptible Sleep(IO)');
94    Utils.statusMap.set('DK', 'Uninterruptible Sleep + Wake Kill');
95    Utils.statusMap.set('DK-NIO', 'Uninterruptible Sleep(non-IO) + Wake Kill');
96    Utils.statusMap.set('DK-IO', 'Uninterruptible Sleep(IO) + Wake Kill');
97    Utils.statusMap.set('S', 'Sleeping');
98    Utils.statusMap.set('R', 'Runnable');
99    Utils.statusMap.set('Running', 'Running');
100    Utils.statusMap.set('R+', 'Runnable (Preempted)');
101    Utils.statusMap.set('R-B', 'Runnable (Binder)');
102    Utils.statusMap.set('I', 'Task Dead');
103    Utils.statusMap.set('T', 'Stopped');
104    Utils.statusMap.set('t', 'Traced');
105    Utils.statusMap.set('X', 'Exit (Dead)');
106    Utils.statusMap.set('Z', 'Exit (Zombie)');
107    Utils.statusMap.set('P', 'Parked');
108    Utils.statusMap.set('N', 'No Load');
109  }
110
111  public getProcessMap(traceId?: string | null): Map<number, string> {
112    if (traceId) {
113      return (traceId === '2' ? this.trace2ProcessMap : this.trace1ProcessMap);
114    } else {
115      return (Utils.currentSelectTrace === '2' ? this.trace2ProcessMap : this.trace1ProcessMap);
116    }
117  }
118
119  public getThreadMap(traceId?: string | null): Map<number, string> {
120    if (traceId) {
121      return (traceId === '2' ? this.trace2ThreadMap : this.trace1ThreadMap);
122    } else {
123      return (Utils.currentSelectTrace === '2' ? this.trace2ThreadMap : this.trace1ThreadMap);
124    }
125  }
126
127  public getCallStatckMap(): Map<number | string, string> {
128    return this.callStackMap;
129  }
130
131  public getSchedSliceMap(traceId?: string | null): Map<string, {
132    endState: string;
133    priority: number;
134  }> {
135    if (traceId) {
136      return (traceId === '2' ? this.trace2SchedSliceMap : this.trace1SchedSliceMap);
137    } else {
138      return (Utils.currentSelectTrace === '2' ? this.trace2SchedSliceMap : this.trace1SchedSliceMap);
139    }
140  }
141
142  public getCpuCount(traceId?: string | null): number {
143    if (traceId) {
144      return (traceId === '2' ? this.trace2CpuCount : this.trace1CpuCount);
145    } else {
146      return (Utils.currentSelectTrace === '2' ? this.trace2CpuCount : this.trace1CpuCount);
147    }
148  }
149
150  public setCpuCount(count: number, traceId?: string | null): void {
151    if (traceId) {
152      if (traceId === '2') {
153        this.trace2CpuCount = count;
154      } else {
155        this.trace1CpuCount = count;
156      }
157    } else {
158      if (Utils.currentSelectTrace === '2') {
159        this.trace2CpuCount = count;
160      } else {
161        this.trace1CpuCount = count;
162      }
163    }
164  }
165
166  public getWinCpuCount(traceId?: string | null): number {
167    if (traceId) {
168      return (traceId === '2' ? this.trace2WinCpuCount : this.trace1WinCpuCount);
169    } else {
170      return (Utils.currentSelectTrace === '2' ? this.trace2WinCpuCount : this.trace1WinCpuCount);
171    }
172  }
173
174  public setWinCpuCount(count: number, traceId?: string | null): void {
175    if (traceId) {
176      if (traceId === '2') {
177        this.trace2WinCpuCount = count;
178      } else {
179        this.trace1WinCpuCount = count;
180      }
181    } else {
182      if (Utils.currentSelectTrace === '2') {
183        this.trace2WinCpuCount = count;
184      } else {
185        this.trace1WinCpuCount = count;
186      }
187    }
188  }
189
190  public getRecordStartNS(traceId?: string | null): number {
191    if (traceId) {
192      return (traceId === '2' ? this.trace2RecordStartNS : this.trace1RecordStartNS);
193    } else {
194      return (Utils.currentSelectTrace === '2' ? this.trace2RecordStartNS : this.trace1RecordStartNS);
195    }
196  }
197
198  public getRecordEndNS(traceId?: string | null): number {
199    if (traceId) {
200      return (traceId === '2' ? this.trace2RecordEndNS : this.trace1RecordEndNS);
201    } else {
202      return (Utils.currentSelectTrace === '2' ? this.trace2RecordEndNS : this.trace1RecordEndNS);
203    }
204  }
205
206  public getTotalNS(traceId?: string | null): number {
207    return this.totalNS;
208  }
209
210  public static isDistributedMode(): boolean {
211    return Utils.currentTraceMode === TraceMode.DISTRIBUTED;
212  }
213
214  public static getInstance(): Utils {
215    if (Utils.instance === null) {
216      Utils.instance = new Utils();
217    }
218    return Utils.instance;
219  }
220
221  public clearCache(): void {
222    this.trace1ProcessMap.clear();
223    this.trace2ProcessMap.clear();
224    this.trace1ThreadMap.clear();
225    this.trace2ThreadMap.clear();
226    this.trace1SchedSliceMap.clear();
227    this.trace2SchedSliceMap.clear();
228    this.sysCallEventTidsMap.clear();
229    Utils.distributedTrace = [];
230  }
231
232  public static clearData(): void {
233    Utils.getInstance().clearCache();
234    Utils.DMAFENCECAT_MAP.clear();
235  }
236
237  public static getDistributedRowId(id: unknown): string {
238    let rowId = id;
239    if (rowId === null || rowId === undefined) {
240      rowId = '';
241    }
242    return this.currentSelectTrace ? `${rowId}-${this.currentSelectTrace}` : `${rowId}`;
243  }
244
245  public static getEndState(state: string): string {
246    if (Utils.getInstance().getStatusMap().has(state)) {
247      return Utils.getInstance().getStatusMap().get(state) || 'Unknown State';
248    } else {
249      if ('' === state || state === null) {
250        return '';
251      }
252      return 'Unknown State';
253    }
254  }
255
256  public static isBinder(data: unknown): boolean {
257    return (
258      // @ts-ignore
259      data.funName !== null && // @ts-ignore
260      (data.funName.toLowerCase().startsWith('binder transaction async') || //binder transaction
261        // @ts-ignore
262        data.funName.toLowerCase().startsWith('binder async') || // @ts-ignore
263        data.funName.toLowerCase().startsWith('binder reply'))
264    );
265  }
266
267  public static transferPTSTitle(ptsValue: unknown): string {
268    // @ts-ignore
269    if (ptsValue.startsWith('S-')) {
270      // @ts-ignore
271      return Utils.getEndState(ptsValue.replace('S-', '')); // @ts-ignore
272    } else if (ptsValue.startsWith('P-')) {
273      // @ts-ignore
274      let pid = ptsValue.replace('P-', '');
275      let process = Utils.getInstance().getProcessMap(Utils.currentSelectTrace).get(parseInt(pid)) || 'Process';
276      return `${process} [${pid}]`; // @ts-ignore
277    } else if (ptsValue.startsWith('T-')) {
278      // @ts-ignore
279      let tid = ptsValue.replace('T-', '');
280      let thread = Utils.getInstance().getThreadMap(Utils.currentSelectTrace).get(parseInt(tid)) || 'Thread';
281      return `${thread} [${tid}]`;
282    } else {
283      return '';
284    }
285  }
286
287  public static transferBinderTitle(value: unknown, traceId?: string | null): string {
288    // @ts-ignore
289    if (value.startsWith('P-')) {
290      // @ts-ignore
291      let pid = value.replace('P-', '');
292      let process = Utils.getInstance().getProcessMap(traceId).get(parseInt(pid)) || 'Process';
293      return `${process} [${pid}]`; // @ts-ignore
294    } else if (value.startsWith('T-')) {
295      // @ts-ignore
296      let tid = value.replace('T-', '');
297      let thread = Utils.getInstance().getThreadMap(traceId).get(parseInt(tid)) || 'Thread';
298      return `${thread} [${tid}]`;
299    } else {
300      return '';
301    }
302  }
303
304  public static getStateColor(state: string): string {
305    if (state === 'D-NIO' || state === 'DK-NIO') {
306      return '#795548';
307    } else if (state === 'D-IO' || state === 'DK-IO' || state === 'D' || state === 'DK') {
308      return '#f19b38';
309    } else if (state === 'R' || state === 'R+') {
310      return '#a0b84d';
311    } else if (state === 'R-B') {
312      return '#87CEFA';
313    } else if (state === 'I') {
314      return '#673ab7';
315    } else if (state === 'Running') {
316      return '#467b3b';
317    } else if (state === 'S') {
318      return '#e0e0e0';
319    } else {
320      return '#ff6e40';
321    }
322  }
323
324  public static getTimeString(ns: number): string {
325    let currentTime = ns;
326    let hour1 = 3600_000_000_000;
327    let minute1 = 60_000_000_000;
328    let second1 = 1_000_000_000;
329    let millisecond1 = 1_000_000;
330    let microsecond1 = 1_000;
331    let res = '';
332    if (currentTime >= hour1) {
333      res += `${Math.floor(currentTime / hour1)}h `;
334      currentTime = currentTime - Math.floor(currentTime / hour1) * hour1;
335    }
336    if (currentTime >= minute1) {
337      res += `${Math.floor(currentTime / minute1)}m `;
338      currentTime = currentTime - Math.floor(ns / minute1) * minute1;
339    }
340    if (currentTime >= second1) {
341      res += `${Math.floor(currentTime / second1)}s `;
342      currentTime = currentTime - Math.floor(currentTime / second1) * second1;
343    }
344    if (currentTime >= millisecond1) {
345      res += `${Math.floor(currentTime / millisecond1)}ms `;
346      currentTime = currentTime - Math.floor(currentTime / millisecond1) * millisecond1;
347    }
348    if (currentTime >= microsecond1) {
349      res += `${Math.floor(currentTime / microsecond1)}μs `;
350      currentTime = currentTime - Math.floor(currentTime / microsecond1) * microsecond1;
351    }
352    if (currentTime > 0) {
353      res += `${currentTime}ns `;
354    }
355    if (res === '') {
356      res = `${ns}`;
357    }
358    return res;
359  }
360
361  public static getProbablyTime(timeNs: number): string {
362    let currentNs = timeNs;
363    let probablyHour = 3600_000_000_000;
364    let probablyMinute1 = 60_000_000_000;
365    let probablySecond1 = 1_000_000_000;
366    let probablyMillisecond1 = 1_000_000;
367    let probablyMicrosecond1 = 1_000;
368    let res = '';
369    if (currentNs >= probablyHour) {
370      res += `${(currentNs / probablyHour).toFixed(2)}h `;
371    } else if (currentNs >= probablyMinute1) {
372      res += `${(currentNs / probablyMinute1).toFixed(2)}m `;
373    } else if (currentNs >= probablySecond1) {
374      res += `${(currentNs / probablySecond1).toFixed(2)}s `;
375    } else if (currentNs >= probablyMillisecond1) {
376      res += `${(currentNs / probablyMillisecond1).toFixed(2)}ms `;
377    } else if (currentNs >= probablyMicrosecond1) {
378      res += `${(currentNs / probablyMicrosecond1).toFixed(2)}μs `;
379    } else if (currentNs > 0) {
380      res += `${currentNs}ns `;
381    } else if (res === '') {
382      res = `${timeNs}`;
383    }
384    return res;
385  }
386
387  public static getTimeStringHMS(ns: number): string {
388    let currentNs = ns;
389    let hour1 = 3600_000_000_000;
390    let minute1 = 60_000_000_000;
391    let second1 = 1_000_000_000; // 1 second
392    let millisecond1 = 1_000_000; // 1 millisecond
393    let microsecond1 = 1_000; // 1 microsecond
394    let res = '';
395    if (currentNs >= hour1) {
396      res += `${Math.floor(currentNs / hour1)}:`;
397      currentNs = currentNs - Math.floor(currentNs / hour1) * hour1;
398    }
399    if (currentNs >= minute1) {
400      res += `${Math.floor(currentNs / minute1)}:`;
401      currentNs = currentNs - Math.floor(ns / minute1) * minute1;
402    }
403    if (currentNs >= second1) {
404      res += `${Math.floor(currentNs / second1)}:`;
405      currentNs = currentNs - Math.floor(currentNs / second1) * second1;
406    }
407    if (currentNs >= millisecond1) {
408      res += `${Math.floor(currentNs / millisecond1)}.`;
409      currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1;
410    }
411    if (currentNs >= microsecond1) {
412      res += `${Math.floor(currentNs / microsecond1)}.`;
413      currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1;
414    }
415    if (currentNs > 0) {
416      res += `${currentNs}`;
417    }
418    if (res === '') {
419      res = `${ns}`;
420    }
421    return res;
422  }
423
424  public static getByteWithUnit(bytes: number): string {
425    if (bytes < 0) {
426      return `-${this.getByteWithUnit(Math.abs(bytes))}`;
427    }
428    let currentByte = bytes;
429    let kb1 = 1 << 10;
430    let mb1 = (1 << 10) << 10;
431    let gb1 = ((1 << 10) << 10) << 10; // 1 gb
432    let res = '';
433    if (currentByte > gb1) {
434      res += `${(currentByte / gb1).toFixed(2)} GB`;
435    } else if (currentByte > mb1) {
436      res += `${(currentByte / mb1).toFixed(2)} MB`;
437    } else if (currentByte > kb1) {
438      res += `${(currentByte / kb1).toFixed(2)} KB`;
439    } else {
440      res += `${Math.round(currentByte)} byte`;
441    }
442    return res;
443  }
444
445  public static timeFormat(ms: number): string {
446    let currentMsTime = ms;
447    let hours = 3600000;
448    let minute1 = 60000;
449    let second1 = 1000;
450    let res = '';
451    if (currentMsTime >= hours) {
452      res += `${Math.floor(currentMsTime / hours)} h `;
453      currentMsTime = currentMsTime - Math.floor(currentMsTime / hours) * hours;
454    }
455    if (currentMsTime >= minute1) {
456      res += `${Math.floor(currentMsTime / minute1)} min `;
457      currentMsTime = currentMsTime - Math.floor(currentMsTime / minute1) * minute1;
458    }
459    if (currentMsTime >= second1) {
460      res += `${Math.floor(currentMsTime / second1)} s `;
461      currentMsTime = currentMsTime - Math.floor(currentMsTime / second1) * second1;
462    }
463    if (currentMsTime > 0) {
464      currentMsTime = parseFloat(currentMsTime.toFixed(2));
465      res += `${currentMsTime} ms `;
466    } else if (res === '') {
467        res += '0 ms ';
468    }
469    return res;
470  }
471
472  public static groupByMap(array: Array<unknown>, key: string): Map<unknown, unknown> {
473    let result = new Map();
474    array.forEach((item) => {
475      // @ts-ignore
476      let value = item[key];
477      if (!result.has(value)) {
478        result.set(value, []);
479      }
480      result.get(value).push(item);
481    });
482    return result;
483  }
484
485  public static groupBy(array: Array<unknown>, key: string): unknown {
486    return array.reduce((pre, current, index, arr) => {
487      // @ts-ignore
488      (pre[current[key]] = pre[current[key]] || []).push(current);
489      return pre;
490    }, {});
491  }
492
493  public static timeMsFormat2p(ms: number): string {
494    let currentNs = ms;
495    let hour1 = 3600_000;
496    let minute1 = 60_000;
497    let second1 = 1_000; // 1 second
498    let result = '';
499    if (currentNs >= hour1) {
500      result += `${Math.round(currentNs / hour1).toFixed(2)}h`;
501      return result;
502    }
503    if (currentNs >= minute1) {
504      result += `${Math.round(currentNs / minute1).toFixed(2)}min`;
505      return result;
506    }
507    if (currentNs >= second1) {
508      result += `${Math.round(currentNs / second1).toFixed(2)}s`;
509      return result;
510    }
511    if (currentNs > 0) {
512      result += `${currentNs.toFixed(2)}ms`;
513      return result;
514    }
515    if (result === '') {
516      result = '0s';
517    }
518    return result;
519  }
520
521  public static uuid(): string {
522    // @ts-ignore
523    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
524      (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
525    );
526  }
527
528  public static getBinaryKBWithUnit(kbytes: number): string {
529    if (kbytes === 0) {
530      return '0KB';
531    }
532    let currentBytes = kbytes;
533    let mib1 = 1024;
534    let gib1 = 1024 * 1024;
535    let res = '';
536    if (currentBytes >= gib1) {
537      res += `${(currentBytes / gib1).toFixed(2)}GB`;
538    } else if (currentBytes >= mib1) {
539      res += `${(currentBytes / mib1).toFixed(2)}MB`;
540    } else {
541      res += `${currentBytes.toFixed(2)}KB`;
542    }
543    return res;
544  }
545
546  public static getBinaryByteWithUnit(bytes: number): string {
547    if (bytes === 0) {
548      return '0Bytes';
549    }
550    let currentBytes = bytes;
551    let kib1 = 1024;
552    let mib1 = 1024 * 1024;
553    let gib1 = 1024 * 1024 * 1024;
554    let res = '';
555    if (bytes < 0) {
556      res = '-';
557      currentBytes = Math.abs(currentBytes);
558    }
559    if (currentBytes >= gib1) {
560      res += `${(currentBytes / gib1).toFixed(2)}GB`;
561    } else if (currentBytes >= mib1) {
562      res += `${(currentBytes / mib1).toFixed(2)}MB`;
563    } else if (currentBytes >= kib1) {
564      res += `${(currentBytes / kib1).toFixed(2)}KB`;
565    } else {
566      res += `${currentBytes.toFixed(2)}Bytes`;
567    }
568    return res;
569  }
570
571  public static getTimeStampHMS(ns: number): string {
572    let currentNs = ns;
573    let hour1 = 3600_000_000_000;
574    let minute1 = 60_000_000_000;
575    let second1 = 1_000_000_000; // 1 second
576    let millisecond1 = 1_000_000; // 1 millisecond
577    let microsecond1 = 1_000; // 1 microsecond
578    let res = '';
579    if (currentNs >= hour1) {
580      res += `${this.getCompletionTime(Math.floor(currentNs / hour1), 2)}:`;
581      currentNs = currentNs - Math.floor(currentNs / hour1) * hour1;
582    }
583    if (currentNs >= minute1) {
584      res += `${this.getCompletionTime(Math.floor(currentNs / minute1), 2)}:`;
585      currentNs = currentNs - Math.floor(ns / minute1) * minute1;
586    }
587    if (currentNs >= second1) {
588      res += `${this.getCompletionTime(Math.floor(currentNs / second1), 2)}:`;
589      currentNs = currentNs - Math.floor(currentNs / second1) * second1;
590    } else {
591      res += '00:';
592    }
593    if (currentNs >= millisecond1) {
594      res += `${this.getCompletionTime(Math.floor(currentNs / millisecond1), 3)}.`;
595      currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1;
596    } else {
597      res += '000.';
598    }
599    if (currentNs >= microsecond1) {
600      res += `${this.getCompletionTime(Math.floor(currentNs / microsecond1), 3)}.`;
601      currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1;
602    } else {
603      res += '000';
604    }
605    if (currentNs > 0) {
606      res += this.getCompletionTime(currentNs, 3);
607    }
608    if (res === '') {
609      res = `${ns}`;
610    }
611    return res;
612  }
613
614  public static getDurString(ns: number): string {
615    let currentNs = ns;
616    let second1 = 1000000000;
617    let millisecond1 = 1000000;
618    let res = '';
619    if (currentNs >= second1) {
620      let cu = currentNs / second1;
621      res += `${cu.toFixed(3)} s `;
622      return res;
623    }
624    if (currentNs >= millisecond1) {
625      res += `${Math.floor(currentNs / millisecond1)} ms `;
626      return res;
627    }
628    if (res === '') {
629      res = `${ns}`;
630    }
631    return res;
632  }
633
634  private static getCompletionTime(time: number, maxLength: number): string {
635    if (maxLength === 2) {
636      if (time.toString().length === 2) {
637        return `${time}`;
638      } else {
639        return `0${time}`;
640      }
641    } else if (maxLength === 3) {
642      if (time.toString().length === 3) {
643        return time.toString();
644      } else if (time.toString().length === 2) {
645        return `0${time}`;
646      } else {
647        return `00${time}`;
648      }
649    } else {
650      return '0';
651    }
652  }
653
654  public getStatusMap(): Map<string, string> {
655    return Utils.statusMap;
656  }
657
658  public static removeDuplicates(array1: unknown[], array2: unknown[], key: string): unknown {
659    let obj: unknown = {};
660    return array1.concat(array2).reduce(function (total, item) {
661      // @ts-ignore
662      if (!obj[`${item[key]}-${item.pid}`]) {
663        // @ts-ignore
664        obj[`${item[key]}-${item.pid}`] = true; // @ts-ignore
665        total.push(item);
666      }
667      return total;
668    }, []);
669  }
670
671  // 线程排序去重
672  public static sortThreadRow(array1: unknown[], array2: unknown[], flag: string): unknown {
673    let total = new Array();
674    let arr2Map = new Map();
675    // 将array2转为map
676    for (let i = 0; i < array2.length; i++) {
677      // @ts-ignore
678      arr2Map.set(flag === 'thread' ? `${array2[i].pid}-${array2[i].tid}` : `${array2[i].pid}`, array2[i]);
679    }
680    for (let i = 0; i < array1.length; i++) {
681      // @ts-ignore
682      if (arr2Map.get(`${array1[i][0]}`)) {
683        // @ts-ignore
684        total.push(arr2Map.get(`${array1[i][0]}`));
685        // @ts-ignore
686        arr2Map.delete(`${array1[i][0]}`);
687      }
688    };
689    // 将map中剩余的循环加在total后
690    // @ts-ignore
691    arr2Map.forEach((v) => {
692      total.push(v);
693    });
694    return total;
695  }
696
697  static getFrequencyWithUnit = (
698    maxFreq: number
699  ): {
700    maxFreqName: string;
701    maxFreq: number;
702  } => {
703    let maxFreqObj = {
704      maxFreqName: ' ',
705      maxFreq: 0,
706    };
707    let units: Array<string> = ['', 'K', 'M', 'G', 'T', 'E'];
708    let sb = ' ';
709    if (maxFreq > 0) {
710      let log10: number = Math.ceil(Math.log10(maxFreq));
711      let pow10: number = Math.pow(10, log10);
712      let afterCeil: number = Math.ceil(maxFreq / (pow10 / 4)) * 1000;
713      let afterDivision: number = (afterCeil * ((pow10 / 4) * 1000)) / 1000000;
714      maxFreqObj.maxFreq = afterDivision;
715      let unitIndex: number = Math.floor(log10 / 3);
716      sb = `${afterDivision / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}`;
717    }
718    maxFreqObj.maxFreqName = sb.toString();
719    return maxFreqObj;
720  };
721
722  public static getTimeIsCross(startTime: number, endTime: number, startTime1: number, endTime1: number): boolean {
723    return Math.max(startTime, startTime1) <= Math.min(endTime, endTime1);
724  }
725
726  initResponseTypeList(val: SelectionParam): void {
727    const isStatistic = val.nativeMemoryStatistic.length > 0;
728    const selection = isStatistic ? val.nativeMemoryStatistic : val.nativeMemory;
729    let types: Array<string | number> = [];
730    if (selection.indexOf('All Heap & Anonymous VM') !== -1) {
731      if (isStatistic) {
732        types.push(0, 1);
733      } else {
734        types.push("'AllocEvent'", "'MmapEvent'");
735      }
736    } else {
737      if (selection.indexOf('All Heap') !== -1) {
738        if (isStatistic) {
739          types.push(0);
740        } else {
741          types.push("'AllocEvent'");
742        }
743      }
744      if (selection.indexOf('All Anonymous VM') !== -1) {
745        if (isStatistic) {
746          types.push(1);
747        } else {
748          types.push("'MmapEvent'");
749        }
750      }
751    }
752    queryNativeHookResponseTypes(val.leftNs, val.rightNs, types, val.nativeMemoryCurrentIPid, isStatistic).then((res): void => {
753      procedurePool.submitWithName('logic0', 'native-memory-init-responseType', res, undefined, (): void => { });
754    });
755  }
756
757  setCurrentSelectIPid(ipid: number): void {
758    procedurePool.submitWithName('logic0', 'native-memory-set-current_ipid', ipid, undefined, (): void => { });
759  }
760
761  public static convertJSON(arr: ArrayBuffer | Array<unknown>): unknown {
762    if (arr instanceof ArrayBuffer) {
763      let dec = new TextDecoder();
764      let str = dec.decode(arr);
765      let jsonArray: Array<unknown> = [];
766      str = str.substring(str.indexOf('\n') + 1);
767      if (!str) {
768      } else {
769        let parse;
770        let tansStr: string;
771        try {
772          tansStr = str.replace(/[\t\r\n]/g, '');
773          parse = JSON.parse(tansStr);
774        } catch {
775          try {
776            tansStr = tansStr!.replace(/[^\x20-\x7E]/g, '?'); //匹配乱码字 符,将其转换为?
777            parse = JSON.parse(tansStr);
778          } catch {
779            tansStr = tansStr!.replace(/\\/g, '\\\\');
780            parse = JSON.parse(tansStr);
781          }
782        }
783        let columns = parse.columns;
784        let values = parse.values;
785        for (let i = 0; i < values.length; i++) {
786          let obj: unknown = {};
787          for (let j = 0; j < columns.length; j++) {
788            //@ts-ignore
789            obj[columns[j]] = values[i][j];
790          }
791          jsonArray.push(obj);
792        }
793      }
794      return jsonArray;
795    } else {
796      return arr;
797    }
798  }
799}
800