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 groupByMap(array: Array<unknown>, key: string): Map<unknown, unknown> { 442 let result = new Map(); 443 array.forEach((item) => { 444 // @ts-ignore 445 let value = item[key]; 446 if (!result.has(value)) { 447 result.set(value, []); 448 } 449 result.get(value).push(item); 450 }); 451 return result; 452 } 453 454 public static groupBy(array: Array<unknown>, key: string): unknown { 455 return array.reduce((pre, current, index, arr) => { 456 // @ts-ignore 457 (pre[current[key]] = pre[current[key]] || []).push(current); 458 return pre; 459 }, {}); 460 } 461 462 public static timeMsFormat2p(ms: number): string { 463 let currentNs = ms; 464 let hour1 = 3600_000; 465 let minute1 = 60_000; 466 let second1 = 1_000; // 1 second 467 let result = ''; 468 if (currentNs >= hour1) { 469 result += `${Math.round(currentNs / hour1).toFixed(2)}h`; 470 return result; 471 } 472 if (currentNs >= minute1) { 473 result += `${Math.round(currentNs / minute1).toFixed(2)}min`; 474 return result; 475 } 476 if (currentNs >= second1) { 477 result += `${Math.round(currentNs / second1).toFixed(2)}s`; 478 return result; 479 } 480 if (currentNs > 0) { 481 result += `${currentNs.toFixed(2)}ms`; 482 return result; 483 } 484 if (result === '') { 485 result = '0s'; 486 } 487 return result; 488 } 489 490 public static uuid(): string { 491 // @ts-ignore 492 return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => 493 (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 494 ); 495 } 496 497 public static getBinaryKBWithUnit(kbytes: number): string { 498 if (kbytes === 0) { 499 return '0KB'; 500 } 501 let currentBytes = kbytes; 502 let mib1 = 1024; 503 let gib1 = 1024 * 1024; 504 let res = ''; 505 if (currentBytes >= gib1) { 506 res += `${(currentBytes / gib1).toFixed(2)}GB`; 507 } else if (currentBytes >= mib1) { 508 res += `${(currentBytes / mib1).toFixed(2)}MB`; 509 } else { 510 res += `${currentBytes.toFixed(2)}KB`; 511 } 512 return res; 513 } 514 515 public static getBinaryByteWithUnit(bytes: number): string { 516 if (bytes === 0) { 517 return '0Bytes'; 518 } 519 let currentBytes = bytes; 520 let kib1 = 1024; 521 let mib1 = 1024 * 1024; 522 let gib1 = 1024 * 1024 * 1024; 523 let res = ''; 524 if (bytes < 0) { 525 res = '-'; 526 currentBytes = Math.abs(currentBytes); 527 } 528 if (currentBytes >= gib1) { 529 res += `${(currentBytes / gib1).toFixed(2)}GB`; 530 } else if (currentBytes >= mib1) { 531 res += `${(currentBytes / mib1).toFixed(2)}MB`; 532 } else if (currentBytes >= kib1) { 533 res += `${(currentBytes / kib1).toFixed(2)}KB`; 534 } else { 535 res += `${currentBytes.toFixed(2)}Bytes`; 536 } 537 return res; 538 } 539 540 public static getTimeStampHMS(ns: number): string { 541 let currentNs = ns; 542 let hour1 = 3600_000_000_000; 543 let minute1 = 60_000_000_000; 544 let second1 = 1_000_000_000; // 1 second 545 let millisecond1 = 1_000_000; // 1 millisecond 546 let microsecond1 = 1_000; // 1 microsecond 547 let res = ''; 548 if (currentNs >= hour1) { 549 res += `${this.getCompletionTime(Math.floor(currentNs / hour1), 2)}:`; 550 currentNs = currentNs - Math.floor(currentNs / hour1) * hour1; 551 } 552 if (currentNs >= minute1) { 553 res += `${this.getCompletionTime(Math.floor(currentNs / minute1), 2)}:`; 554 currentNs = currentNs - Math.floor(ns / minute1) * minute1; 555 } 556 if (currentNs >= second1) { 557 res += `${this.getCompletionTime(Math.floor(currentNs / second1), 2)}:`; 558 currentNs = currentNs - Math.floor(currentNs / second1) * second1; 559 } else { 560 res += '00:'; 561 } 562 if (currentNs >= millisecond1) { 563 res += `${this.getCompletionTime(Math.floor(currentNs / millisecond1), 3)}.`; 564 currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1; 565 } else { 566 res += '000.'; 567 } 568 if (currentNs >= microsecond1) { 569 res += `${this.getCompletionTime(Math.floor(currentNs / microsecond1), 3)}.`; 570 currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1; 571 } else { 572 res += '000'; 573 } 574 if (currentNs > 0) { 575 res += this.getCompletionTime(currentNs, 3); 576 } 577 if (res === '') { 578 res = `${ns}`; 579 } 580 return res; 581 } 582 583 public static getDurString(ns: number): string { 584 let currentNs = ns; 585 let second1 = 1000000000; 586 let millisecond1 = 1000000; 587 let res = ''; 588 if (currentNs >= second1) { 589 let cu = currentNs / second1; 590 res += `${cu.toFixed(3)} s `; 591 return res; 592 } 593 if (currentNs >= millisecond1) { 594 res += `${Math.floor(currentNs / millisecond1)} ms `; 595 return res; 596 } 597 if (res === '') { 598 res = `${ns}`; 599 } 600 return res; 601 } 602 603 private static getCompletionTime(time: number, maxLength: number): string { 604 if (maxLength === 2) { 605 if (time.toString().length === 2) { 606 return `${time}`; 607 } else { 608 return `0${time}`; 609 } 610 } else if (maxLength === 3) { 611 if (time.toString().length === 3) { 612 return time.toString(); 613 } else if (time.toString().length === 2) { 614 return `0${time}`; 615 } else { 616 return `00${time}`; 617 } 618 } else { 619 return '0'; 620 } 621 } 622 623 public getStatusMap(): Map<string, string> { 624 return Utils.statusMap; 625 } 626 627 public static removeDuplicates(array1: unknown[], array2: unknown[], key: string): unknown { 628 let obj: unknown = {}; 629 return array1.concat(array2).reduce(function (total, item) { 630 // @ts-ignore 631 if (!obj[`${item[key]}-${item.pid}`]) { 632 // @ts-ignore 633 obj[`${item[key]}-${item.pid}`] = true; // @ts-ignore 634 total.push(item); 635 } 636 return total; 637 }, []); 638 } 639 640 // 线程排序去重 641 public static sortThreadRow(array1: unknown[], array2: unknown[], flag: string): unknown { 642 let total = new Array(); 643 let arr2Map = new Map(); 644 // 将array2转为map 645 for (let i = 0; i < array2.length; i++) { 646 // @ts-ignore 647 arr2Map.set(flag === 'thread' ? `${array2[i].pid}-${array2[i].tid}` : `${array2[i].pid}`, array2[i]); 648 } 649 for (let i = 0; i < array1.length; i++) { 650 // @ts-ignore 651 total.push(arr2Map.get(`${array1[i][0]}`)); 652 // @ts-ignore 653 arr2Map.delete(`${array1[i][0]}`); 654 }; 655 // 将map中剩余的循环加在total后 656 // @ts-ignore 657 arr2Map.forEach((v) => { 658 total.push(v); 659 }); 660 return total; 661 } 662 663 static getFrequencyWithUnit = ( 664 maxFreq: number 665 ): { 666 maxFreqName: string; 667 maxFreq: number; 668 } => { 669 let maxFreqObj = { 670 maxFreqName: ' ', 671 maxFreq: 0, 672 }; 673 let units: Array<string> = ['', 'K', 'M', 'G', 'T', 'E']; 674 let sb = ' '; 675 if (maxFreq > 0) { 676 let log10: number = Math.ceil(Math.log10(maxFreq)); 677 let pow10: number = Math.pow(10, log10); 678 let afterCeil: number = Math.ceil(maxFreq / (pow10 / 4)) * 1000; 679 let afterDivision: number = (afterCeil * ((pow10 / 4) * 1000)) / 1000000; 680 maxFreqObj.maxFreq = afterDivision; 681 let unitIndex: number = Math.floor(log10 / 3); 682 sb = `${afterDivision / Math.pow(10, unitIndex * 3)}${units[unitIndex + 1]}`; 683 } 684 maxFreqObj.maxFreqName = sb.toString(); 685 return maxFreqObj; 686 }; 687 688 public static getTimeIsCross(startTime: number, endTime: number, startTime1: number, endTime1: number): boolean { 689 return Math.max(startTime, startTime1) <= Math.min(endTime, endTime1); 690 } 691 692 initResponseTypeList(val: SelectionParam): void { 693 const isStatistic = val.nativeMemoryStatistic.length > 0; 694 const selection = isStatistic ? val.nativeMemoryStatistic : val.nativeMemory; 695 let types: Array<string | number> = []; 696 if (selection.indexOf('All Heap & Anonymous VM') !== -1) { 697 if (isStatistic) { 698 types.push(0, 1); 699 } else { 700 types.push("'AllocEvent'", "'MmapEvent'"); 701 } 702 } else { 703 if (selection.indexOf('All Heap') !== -1) { 704 if (isStatistic) { 705 types.push(0); 706 } else { 707 types.push("'AllocEvent'"); 708 } 709 } 710 if (selection.indexOf('All Anonymous VM') !== -1) { 711 if (isStatistic) { 712 types.push(1); 713 } else { 714 types.push("'MmapEvent'"); 715 } 716 } 717 } 718 queryNativeHookResponseTypes(val.leftNs, val.rightNs, types, isStatistic).then((res): void => { 719 procedurePool.submitWithName('logic0', 'native-memory-init-responseType', res, undefined, (): void => { }); 720 }); 721 } 722 723 setCurrentSelectIPid(ipid: number): void { 724 procedurePool.submitWithName('logic0', 'native-memory-set-current_ipid', ipid, undefined, (): void => { }); 725 } 726 727 public static convertJSON(arr: ArrayBuffer | Array<unknown>): unknown { 728 if (arr instanceof ArrayBuffer) { 729 let dec = new TextDecoder(); 730 let str = dec.decode(arr); 731 let jsonArray: Array<unknown> = []; 732 str = str.substring(str.indexOf('\n') + 1); 733 if (!str) { 734 } else { 735 let parse; 736 let tansStr: string; 737 try { 738 tansStr = str.replace(/[\t\r\n]/g, ''); 739 parse = JSON.parse(tansStr); 740 } catch { 741 try { 742 tansStr = tansStr!.replace(/[^\x20-\x7E]/g, '?'); //匹配乱码字 符,将其转换为? 743 parse = JSON.parse(tansStr); 744 } catch { 745 tansStr = tansStr!.replace(/\\/g, '\\\\'); 746 parse = JSON.parse(tansStr); 747 } 748 } 749 let columns = parse.columns; 750 let values = parse.values; 751 for (let i = 0; i < values.length; i++) { 752 let obj: unknown = {}; 753 for (let j = 0; j < columns.length; j++) { 754 //@ts-ignore 755 obj[columns[j]] = values[i][j]; 756 } 757 jsonArray.push(obj); 758 } 759 } 760 return jsonArray; 761 } else { 762 return arr; 763 } 764 } 765} 766