13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ciimport * as fs from 'fs'; 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_ciexport enum EventList { 193af6ab5fSopenharmony_ci OBFUSCATION_INITIALIZATION = 'Obfuscation initialization', 203af6ab5fSopenharmony_ci ALL_FILES_OBFUSCATION = 'All files obfuscation', 213af6ab5fSopenharmony_ci CREATE_AST = 'Create AST', 223af6ab5fSopenharmony_ci OBFUSCATE_AST = 'Obfuscate AST', 233af6ab5fSopenharmony_ci VIRTUAL_CONSTRUCTOR_OBFUSCATION = 'Virtual constructor obfuscation', 243af6ab5fSopenharmony_ci SHORT_HAND_OBFUSCATION = 'Shorthand obfuscation', 253af6ab5fSopenharmony_ci REMOVE_CONSOLE = 'Remove console', 263af6ab5fSopenharmony_ci PROPERTY_OBFUSCATION = 'Property obfuscation', 273af6ab5fSopenharmony_ci IDENTIFIER_OBFUSCATION = 'Identifier obfuscation', 283af6ab5fSopenharmony_ci CREATE_CHECKER = 'Create checker', 293af6ab5fSopenharmony_ci SCOPE_ANALYZE = 'Scope analyze', 303af6ab5fSopenharmony_ci CREATE_OBFUSCATED_NAMES = 'Create obfuscated names', 313af6ab5fSopenharmony_ci OBFUSCATE_NODES = 'Obfuscate nodes', 323af6ab5fSopenharmony_ci FILENAME_OBFUSCATION = 'Filename obfuscation', 333af6ab5fSopenharmony_ci CREATE_PRINTER = 'Create Printer' 343af6ab5fSopenharmony_ci} 353af6ab5fSopenharmony_ci 363af6ab5fSopenharmony_ciexport enum EventIndentation { 373af6ab5fSopenharmony_ci TWOSPACE = 2, 383af6ab5fSopenharmony_ci ONESPACE = 1, 393af6ab5fSopenharmony_ci NOSPACE = 0, 403af6ab5fSopenharmony_ci}; 413af6ab5fSopenharmony_ci 423af6ab5fSopenharmony_ciexport const eventList = new Map<string, number>([ 433af6ab5fSopenharmony_ci [EventList.OBFUSCATION_INITIALIZATION, EventIndentation.NOSPACE], 443af6ab5fSopenharmony_ci [EventList.ALL_FILES_OBFUSCATION, EventIndentation.NOSPACE], 453af6ab5fSopenharmony_ci [EventList.CREATE_AST, EventIndentation.ONESPACE], 463af6ab5fSopenharmony_ci [EventList.OBFUSCATE_AST, EventIndentation.ONESPACE], 473af6ab5fSopenharmony_ci [EventList.VIRTUAL_CONSTRUCTOR_OBFUSCATION, EventIndentation.TWOSPACE], 483af6ab5fSopenharmony_ci [EventList.SHORT_HAND_OBFUSCATION, EventIndentation.TWOSPACE], 493af6ab5fSopenharmony_ci [EventList.REMOVE_CONSOLE, EventIndentation.TWOSPACE], 503af6ab5fSopenharmony_ci [EventList.PROPERTY_OBFUSCATION, EventIndentation.TWOSPACE], 513af6ab5fSopenharmony_ci [EventList.IDENTIFIER_OBFUSCATION, EventIndentation.TWOSPACE], 523af6ab5fSopenharmony_ci [EventList.CREATE_CHECKER, EventIndentation.TWOSPACE], 533af6ab5fSopenharmony_ci [EventList.SCOPE_ANALYZE, EventIndentation.TWOSPACE], 543af6ab5fSopenharmony_ci [EventList.CREATE_OBFUSCATED_NAMES, EventIndentation.TWOSPACE], 553af6ab5fSopenharmony_ci [EventList.OBFUSCATE_NODES, EventIndentation.TWOSPACE], 563af6ab5fSopenharmony_ci [EventList.FILENAME_OBFUSCATION, EventIndentation.TWOSPACE], 573af6ab5fSopenharmony_ci [EventList.CREATE_PRINTER, EventIndentation.ONESPACE], 583af6ab5fSopenharmony_ci]); 593af6ab5fSopenharmony_ci 603af6ab5fSopenharmony_ciexport interface TimeAndMemInfo { 613af6ab5fSopenharmony_ci start: number; 623af6ab5fSopenharmony_ci duration: number; 633af6ab5fSopenharmony_ci startMemory: number; 643af6ab5fSopenharmony_ci endMemory: number; 653af6ab5fSopenharmony_ci memoryUsage: number; 663af6ab5fSopenharmony_ci} 673af6ab5fSopenharmony_ci 683af6ab5fSopenharmony_ciconst MILLISECOND_TO_SECOND = 1000; 693af6ab5fSopenharmony_ciconst BYTE_TO_MB = 1024 * 1024; 703af6ab5fSopenharmony_ciconst SIG_FIGS = 3;// 有效数字位数 713af6ab5fSopenharmony_ciconst INDENT = ' '; 723af6ab5fSopenharmony_ci 733af6ab5fSopenharmony_ciabstract class BasePrinter { 743af6ab5fSopenharmony_ci protected outputPath: string | undefined; 753af6ab5fSopenharmony_ci 763af6ab5fSopenharmony_ci protected abstract getCurrentEventData(): string; 773af6ab5fSopenharmony_ci 783af6ab5fSopenharmony_ci constructor(outputPath: string = "") { 793af6ab5fSopenharmony_ci this.outputPath = outputPath; 803af6ab5fSopenharmony_ci } 813af6ab5fSopenharmony_ci 823af6ab5fSopenharmony_ci setOutputPath(outputPath: string | undefined) { 833af6ab5fSopenharmony_ci this.outputPath = outputPath; 843af6ab5fSopenharmony_ci } 853af6ab5fSopenharmony_ci 863af6ab5fSopenharmony_ci print(message: string): void { 873af6ab5fSopenharmony_ci if (this.outputPath && this.outputPath !== "") { 883af6ab5fSopenharmony_ci fs.appendFileSync(`${this.outputPath}`, message + "\n"); 893af6ab5fSopenharmony_ci } else { 903af6ab5fSopenharmony_ci console.log(message); 913af6ab5fSopenharmony_ci } 923af6ab5fSopenharmony_ci } 933af6ab5fSopenharmony_ci 943af6ab5fSopenharmony_ci outputData(): void { 953af6ab5fSopenharmony_ci const eventData = this.getCurrentEventData(); 963af6ab5fSopenharmony_ci this.print(eventData); 973af6ab5fSopenharmony_ci } 983af6ab5fSopenharmony_ci 993af6ab5fSopenharmony_ci // Only used for ut 1003af6ab5fSopenharmony_ci getOutputPath(): string { 1013af6ab5fSopenharmony_ci return this.outputPath; 1023af6ab5fSopenharmony_ci } 1033af6ab5fSopenharmony_ci} 1043af6ab5fSopenharmony_ci 1053af6ab5fSopenharmony_ciexport class TimeTracker extends BasePrinter { 1063af6ab5fSopenharmony_ci private eventStack: Map<string, TimeAndMemInfo> = new Map<string, TimeAndMemInfo>(); 1073af6ab5fSopenharmony_ci private filesTimeSum: number = 0; 1083af6ab5fSopenharmony_ci private maxTimeUsage = 0; 1093af6ab5fSopenharmony_ci private maxTimeFile = ""; 1103af6ab5fSopenharmony_ci private maxMemoryUsage: number = 0; 1113af6ab5fSopenharmony_ci private maxMemoryFile: string = ''; 1123af6ab5fSopenharmony_ci 1133af6ab5fSopenharmony_ci startEvent(eventName: string, timeSumPrinter?: TimeSumPrinter, currentFile?: string): void { 1143af6ab5fSopenharmony_ci this.eventStack.set(eventName, {start: Date.now(), duration: 0, startMemory: process.memoryUsage().heapUsed, 1153af6ab5fSopenharmony_ci endMemory: 0, memoryUsage: 0}); 1163af6ab5fSopenharmony_ci timeSumPrinter?.addEventDuration(eventName, 0); 1173af6ab5fSopenharmony_ci if (eventName === EventList.CREATE_AST) { 1183af6ab5fSopenharmony_ci this.print(currentFile); 1193af6ab5fSopenharmony_ci } 1203af6ab5fSopenharmony_ci } 1213af6ab5fSopenharmony_ci 1223af6ab5fSopenharmony_ci endEvent(eventName: string, timeSumPrinter?: TimeSumPrinter, isFilesPrinter?: boolean): void { 1233af6ab5fSopenharmony_ci if (!this.eventStack.get(eventName)) { 1243af6ab5fSopenharmony_ci throw new Error(`Event "${eventName}" not started`); 1253af6ab5fSopenharmony_ci } 1263af6ab5fSopenharmony_ci 1273af6ab5fSopenharmony_ci const eventStartTime = this.eventStack.get(eventName).start; 1283af6ab5fSopenharmony_ci const duration = (Date.now() - eventStartTime)/MILLISECOND_TO_SECOND; 1293af6ab5fSopenharmony_ci const eventEndMemory = process.memoryUsage().heapUsed; 1303af6ab5fSopenharmony_ci const eventStartMemory = this.eventStack.get(eventName).startMemory; 1313af6ab5fSopenharmony_ci const memoryUsage = eventEndMemory - eventStartMemory; 1323af6ab5fSopenharmony_ci 1333af6ab5fSopenharmony_ci if (isFilesPrinter) { 1343af6ab5fSopenharmony_ci this.filesTimeSum += duration; 1353af6ab5fSopenharmony_ci 1363af6ab5fSopenharmony_ci if (duration > this.maxTimeUsage) { 1373af6ab5fSopenharmony_ci this.maxTimeUsage = duration; 1383af6ab5fSopenharmony_ci this.maxTimeFile = eventName; 1393af6ab5fSopenharmony_ci } 1403af6ab5fSopenharmony_ci 1413af6ab5fSopenharmony_ci if (eventStartMemory > this.maxMemoryUsage) { 1423af6ab5fSopenharmony_ci this.maxMemoryUsage = eventStartMemory; 1433af6ab5fSopenharmony_ci this.maxMemoryFile = eventName; 1443af6ab5fSopenharmony_ci } 1453af6ab5fSopenharmony_ci 1463af6ab5fSopenharmony_ci if (eventEndMemory > this.maxMemoryUsage) { 1473af6ab5fSopenharmony_ci this.maxMemoryUsage = eventEndMemory; 1483af6ab5fSopenharmony_ci this.maxMemoryFile = eventName; 1493af6ab5fSopenharmony_ci } 1503af6ab5fSopenharmony_ci } 1513af6ab5fSopenharmony_ci 1523af6ab5fSopenharmony_ci this.eventStack.get(eventName).duration = duration; 1533af6ab5fSopenharmony_ci this.eventStack.get(eventName).endMemory = eventEndMemory; 1543af6ab5fSopenharmony_ci this.eventStack.get(eventName).memoryUsage = memoryUsage; 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ci timeSumPrinter?.addEventDuration(eventName, duration); 1573af6ab5fSopenharmony_ci 1583af6ab5fSopenharmony_ci if ((eventName === EventList.ALL_FILES_OBFUSCATION)) { 1593af6ab5fSopenharmony_ci this.eventStack.get(eventName).duration = this.filesTimeSum; 1603af6ab5fSopenharmony_ci this.outputData(); 1613af6ab5fSopenharmony_ci const maxTimeUsage = this.maxTimeUsage.toFixed(SIG_FIGS); 1623af6ab5fSopenharmony_ci const maxMemoryUsage = (this.maxMemoryUsage/BYTE_TO_MB).toFixed(SIG_FIGS); 1633af6ab5fSopenharmony_ci this.print(`Max time cost: ${this.maxTimeFile}: ${maxTimeUsage}s`) 1643af6ab5fSopenharmony_ci this.print(`Max memory usage: ${this.maxMemoryFile}: ${maxMemoryUsage}MB\n`) 1653af6ab5fSopenharmony_ci } 1663af6ab5fSopenharmony_ci 1673af6ab5fSopenharmony_ci if ((eventName === EventList.CREATE_PRINTER)) { 1683af6ab5fSopenharmony_ci this.outputData(); 1693af6ab5fSopenharmony_ci } 1703af6ab5fSopenharmony_ci } 1713af6ab5fSopenharmony_ci 1723af6ab5fSopenharmony_ci getCurrentEventData(): string { 1733af6ab5fSopenharmony_ci let eventData = ""; 1743af6ab5fSopenharmony_ci for (const eventName of this.eventStack.keys()) { 1753af6ab5fSopenharmony_ci let depth = eventList.get(eventName)?? 0; 1763af6ab5fSopenharmony_ci let eventInfo = this.eventStack.get(eventName); 1773af6ab5fSopenharmony_ci const duration = eventInfo.duration; 1783af6ab5fSopenharmony_ci const startMemory = eventInfo.startMemory/BYTE_TO_MB; 1793af6ab5fSopenharmony_ci const endMemory = eventInfo.endMemory/BYTE_TO_MB; 1803af6ab5fSopenharmony_ci const memoryUsage = eventInfo.memoryUsage/BYTE_TO_MB; 1813af6ab5fSopenharmony_ci eventData += this.formatEvent(eventName, duration, startMemory, endMemory, memoryUsage, depth); 1823af6ab5fSopenharmony_ci } 1833af6ab5fSopenharmony_ci return eventData; 1843af6ab5fSopenharmony_ci } 1853af6ab5fSopenharmony_ci 1863af6ab5fSopenharmony_ci private formatEvent(eventName: string, duration: number, startMemory: number, endMemory: number, 1873af6ab5fSopenharmony_ci memoryUsage: number, depth: number): string { 1883af6ab5fSopenharmony_ci const indent = INDENT.repeat(depth); 1893af6ab5fSopenharmony_ci const formattedDuration = duration.toFixed(SIG_FIGS) + 's'; 1903af6ab5fSopenharmony_ci const formatttedStartMemory = startMemory.toFixed(SIG_FIGS) + 'MB'; 1913af6ab5fSopenharmony_ci const formatttedEndMemory = endMemory.toFixed(SIG_FIGS) + 'MB'; 1923af6ab5fSopenharmony_ci const formatttedMemoryUsage = memoryUsage.toFixed(SIG_FIGS) + 'MB'; 1933af6ab5fSopenharmony_ci return `${indent}${eventName}: timeCost:${formattedDuration} startMemory:${formatttedStartMemory} `+ 1943af6ab5fSopenharmony_ci `endMemory:${formatttedEndMemory} memoryUsage:${formatttedMemoryUsage}\n`; 1953af6ab5fSopenharmony_ci } 1963af6ab5fSopenharmony_ci 1973af6ab5fSopenharmony_ci // Only used for ut 1983af6ab5fSopenharmony_ci getEventStack(): Map<string, TimeAndMemInfo> { 1993af6ab5fSopenharmony_ci return this.eventStack; 2003af6ab5fSopenharmony_ci } 2013af6ab5fSopenharmony_ci 2023af6ab5fSopenharmony_ci getFilesTimeSum(): number { 2033af6ab5fSopenharmony_ci return this.filesTimeSum; 2043af6ab5fSopenharmony_ci } 2053af6ab5fSopenharmony_ci 2063af6ab5fSopenharmony_ci getMaxTimeUsage(): number { 2073af6ab5fSopenharmony_ci return this.maxTimeUsage; 2083af6ab5fSopenharmony_ci } 2093af6ab5fSopenharmony_ci 2103af6ab5fSopenharmony_ci getMaxTimeFile(): string { 2113af6ab5fSopenharmony_ci return this.maxTimeFile; 2123af6ab5fSopenharmony_ci } 2133af6ab5fSopenharmony_ci 2143af6ab5fSopenharmony_ci getMaxMemoryUsage(): number { 2153af6ab5fSopenharmony_ci return this.maxMemoryUsage; 2163af6ab5fSopenharmony_ci } 2173af6ab5fSopenharmony_ci 2183af6ab5fSopenharmony_ci getMaxMemoryFile(): string { 2193af6ab5fSopenharmony_ci return this.maxMemoryFile; 2203af6ab5fSopenharmony_ci } 2213af6ab5fSopenharmony_ci} 2223af6ab5fSopenharmony_ci 2233af6ab5fSopenharmony_ciexport class TimeSumPrinter extends BasePrinter { 2243af6ab5fSopenharmony_ci private eventSum: Map<string, number> = new Map<string, number>(); 2253af6ab5fSopenharmony_ci addEventDuration(eventName: string, duration: number): void { 2263af6ab5fSopenharmony_ci const currentValue = this.eventSum.get(eventName) ?? 0; 2273af6ab5fSopenharmony_ci this.eventSum.set(eventName, currentValue + duration); 2283af6ab5fSopenharmony_ci } 2293af6ab5fSopenharmony_ci 2303af6ab5fSopenharmony_ci summarizeEventDuration(): void { 2313af6ab5fSopenharmony_ci const eventData = this.getCurrentEventData(); 2323af6ab5fSopenharmony_ci this.print(eventData); 2333af6ab5fSopenharmony_ci } 2343af6ab5fSopenharmony_ci 2353af6ab5fSopenharmony_ci getCurrentEventData(): string { 2363af6ab5fSopenharmony_ci let eventData = ""; 2373af6ab5fSopenharmony_ci for (const eventName of this.eventSum.keys()) { 2383af6ab5fSopenharmony_ci let depth = eventList.get(eventName)?? 0; 2393af6ab5fSopenharmony_ci const duration = this.eventSum.get(eventName); 2403af6ab5fSopenharmony_ci eventData += this.formatEvent(eventName, duration, depth); 2413af6ab5fSopenharmony_ci } 2423af6ab5fSopenharmony_ci return eventData; 2433af6ab5fSopenharmony_ci } 2443af6ab5fSopenharmony_ci 2453af6ab5fSopenharmony_ci private formatEvent(eventName: string, duration: number, depth: number): string { 2463af6ab5fSopenharmony_ci const indent = INDENT.repeat(depth); 2473af6ab5fSopenharmony_ci const formattedDuration = duration.toFixed(SIG_FIGS) + 's'; 2483af6ab5fSopenharmony_ci return `${indent}${eventName}: ${formattedDuration}\n`; 2493af6ab5fSopenharmony_ci } 2503af6ab5fSopenharmony_ci 2513af6ab5fSopenharmony_ci getEventSum(): Map<string, number> { 2523af6ab5fSopenharmony_ci return this.eventSum; 2533af6ab5fSopenharmony_ci } 2543af6ab5fSopenharmony_ci}