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