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