From e419d2fdf44bf5c1e5e6ef1900b0262db5a6d91b Mon Sep 17 00:00:00 2001 From: liujia178 Date: Fri, 13 Jun 2025 09:56:25 +0800 Subject: [PATCH] Add the time and memory analysis Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICD7CY Signed-off-by: liujia178 --- .../build_system/src/build/base_mode.ts | 62 +++++- .../build_system/src/build/build_mode.ts | 4 + .../src/build/compile_thread_worker.ts | 29 ++- .../build_system/src/build/compile_worker.ts | 17 +- .../build_system/src/build/declgen_worker.ts | 16 +- .../src/init/process_build_config.ts | 5 + .../driver/build_system/src/pre_define.ts | 17 ++ .../build_system/src/record_time_mem.ts | 202 ++++++++++++++++++ ets2panda/driver/build_system/src/types.ts | 5 + 9 files changed, 342 insertions(+), 15 deletions(-) create mode 100644 ets2panda/driver/build_system/src/record_time_mem.ts diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 97e25efc5d..687bbb29eb 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -39,7 +39,8 @@ import { MERGED_ABC_FILE, TS_SUFFIX, DEPENDENCY_INPUT_FILE, - PROJECT_BUILD_CONFIG_FILE + PROJECT_BUILD_CONFIG_FILE, + RRCORD_COMPILE_NODE } from '../pre_define'; import { changeDeclgenFileExtension, @@ -75,6 +76,7 @@ import { ArkTSConfigGenerator } from './generate_arktsconfig'; import { SetupClusterOptions } from '../types'; import { create } from 'domain'; import { emitKeypressEvents } from 'readline'; +import { RecordTimeMem, CompileSingleData } from '../record_time_mem'; export abstract class BaseMode { buildConfig: BuildConfig; entryFiles: Set; @@ -150,6 +152,8 @@ export abstract class BaseMode { } public declgen(fileInfo: CompileFileInfo): void { + let compileSingleData = new CompileSingleData(fileInfo.filePath, this.buildConfig.recordType!); + compileSingleData.record(RRCORD_COMPILE_NODE.SOURCE_NODE); const source = fs.readFileSync(fileInfo.filePath, 'utf8'); let moduleInfo: ModuleInfo = this.moduleInfos.get(fileInfo.packageName)!; let filePathFromModuleRoot: string = path.relative(moduleInfo.moduleRootPath, fileInfo.filePath); @@ -176,20 +180,26 @@ export abstract class BaseMode { fileInfo.arktsConfigFile, fileInfo.filePath ]).peer; + compileSingleData.record(RRCORD_COMPILE_NODE.PROGRAM_NODE, RRCORD_COMPILE_NODE.SOURCE_NODE); arktsGlobal.compilerContext = arkts.Context.createFromString(source); PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); + compileSingleData.record(RRCORD_COMPILE_NODE.PARSE_NODE, RRCORD_COMPILE_NODE.PROGRAM_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer, true); let ast = arkts.EtsScript.fromContext(); + compileSingleData.record(RRCORD_COMPILE_NODE.UI1_NODE, RRCORD_COMPILE_NODE.PARSE_NODE); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + compileSingleData.record(RRCORD_COMPILE_NODE.CHECK_NODE, RRCORD_COMPILE_NODE.UI1_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer, true); + compileSingleData.record(RRCORD_COMPILE_NODE.UI2_NODE, RRCORD_COMPILE_NODE.CHECK_NODE); ast = arkts.EtsScript.fromContext(); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); + compileSingleData.record(RRCORD_COMPILE_NODE.DECLGEN_NODE, RRCORD_COMPILE_NODE.UI2_NODE); arkts.generateTsDeclarationsFromContext( declEtsOutputPath, @@ -197,6 +207,9 @@ export abstract class BaseMode { false ); // Generate 1.0 declaration files & 1.0 glue code this.logger.printInfo('declaration files generated'); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.DECLGEN_NODE); + let filePath = path.join(this.cacheDir, fileInfo.packageName) + compileSingleData.writeSumSingle(filePath, '_decl'); } catch (error) { errorStatus = true; if (error instanceof Error) { @@ -217,6 +230,8 @@ export abstract class BaseMode { } public compile(fileInfo: CompileFileInfo): void { + let compileSingleData = new CompileSingleData(fileInfo.filePath, this.buildConfig.recordType!); + compileSingleData.record(RRCORD_COMPILE_NODE.SOURCE_NODE); ensurePathExists(fileInfo.abcFilePath); let ets2pandaCmd: string[] = [ @@ -242,20 +257,26 @@ export abstract class BaseMode { arktsGlobal.filePath = fileInfo.filePath; arktsGlobal.config = arkts.Config.create(ets2pandaCmd).peer; const source = fs.readFileSync(fileInfo.filePath).toString(); + compileSingleData.record(RRCORD_COMPILE_NODE.PROGRAM_NODE, RRCORD_COMPILE_NODE.SOURCE_NODE); arktsGlobal.compilerContext = arkts.Context.createFromString(source); PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); + compileSingleData.record(RRCORD_COMPILE_NODE.PARSE_NODE, RRCORD_COMPILE_NODE.PROGRAM_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda proceedToState parsed'); let ast = arkts.EtsScript.fromContext(); + compileSingleData.record(RRCORD_COMPILE_NODE.UI1_NODE, RRCORD_COMPILE_NODE.PARSE_NODE); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); this.logger.printInfo('plugin parsed finished'); + compileSingleData.record(RRCORD_COMPILE_NODE.CHECK_NODE, RRCORD_COMPILE_NODE.UI1_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda proceedToState checked'); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.CHECK_NODE); if (this.hasMainModule && (this.byteCodeHar || this.moduleType === OHOS_MODULE_TYPE.SHARED)) { + compileSingleData.record(RRCORD_COMPILE_NODE.DECLGEN_NODE); let filePathFromModuleRoot: string = path.relative(this.moduleRootPath, fileInfo.filePath); let declEtsOutputPath: string = changeFileExtension( path.join(this.declgenV2OutPath as string, this.packageName, filePathFromModuleRoot), @@ -265,15 +286,18 @@ export abstract class BaseMode { // Generate 1.2 declaration files(a temporary solution while binary import not pushed) arkts.generateStaticDeclarationsFromContext(declEtsOutputPath); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.DECLGEN_NODE); } - + compileSingleData.record(RRCORD_COMPILE_NODE.UI2_NODE); ast = arkts.EtsScript.fromContext(); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); this.logger.printInfo('plugin checked finished'); - + compileSingleData.record(RRCORD_COMPILE_NODE.BIN_NODE, RRCORD_COMPILE_NODE.UI2_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda bin generated'); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.BIN_NODE); + compileSingleData.writeSumSingle(path.dirname(fileInfo.abcFilePath)); } catch (error) { errorStatus = true; if (error instanceof Error) { @@ -295,6 +319,7 @@ export abstract class BaseMode { } public mergeAbcFiles(): void { + RecordTimeMem.getInstance().start('mergeAbcFiles'); let linkerInputFile: string = path.join(this.cacheDir, LINKER_INPUT_FILE); let linkerInputContent: string = ''; this.abcFiles.forEach((abcFile: string) => { @@ -327,6 +352,7 @@ export abstract class BaseMode { this.logger.printError(logData); } } + RecordTimeMem.getInstance().end('mergeAbcFiles'); } private getDependentModules(moduleInfo: ModuleInfo): Map[] { @@ -377,9 +403,11 @@ export abstract class BaseMode { } protected generateArkTSConfigForModules(): void { + RecordTimeMem.getInstance().start('generateArkTSConfigForModules'); this.moduleInfos.forEach((moduleInfo: ModuleInfo, moduleRootPath: string) => { ArkTSConfigGenerator.getInstance(this.buildConfig, this.moduleInfos).writeArkTSConfigFile(moduleInfo, this.enableDeclgenEts2Ts); }); + RecordTimeMem.getInstance().end('generateArkTSConfigForModules'); } private collectDepModuleInfos(): void { @@ -398,6 +426,7 @@ export abstract class BaseMode { ); this.logger.printError(logData); } + RecordTimeMem.getInstance().start('collectModuleInfos'); let mainModuleInfo: ModuleInfo = this.getMainModuleInfo(); this.moduleInfos.set(this.packageName, mainModuleInfo); this.dependentModuleList.forEach((module: DependentModuleConfig) => { @@ -431,6 +460,7 @@ export abstract class BaseMode { this.moduleInfos.set(module.packageName, moduleInfo); }); this.collectDepModuleInfos(); + RecordTimeMem.getInstance().end('collectModuleInfos'); } protected getMainModuleInfo(): ModuleInfo { @@ -472,8 +502,10 @@ export abstract class BaseMode { } private saveHashCache(): void { + RecordTimeMem.getInstance().start('saveHashCache'); ensurePathExists(this.hashCacheFile); fs.writeFileSync(this.hashCacheFile, JSON.stringify(this.hashCache, null, 2)); + RecordTimeMem.getInstance().end('saveHashCache'); } private isFileChanged(etsFilePath: string, abcFilePath: string): boolean { @@ -502,6 +534,7 @@ export abstract class BaseMode { return; } + RecordTimeMem.getInstance().start('collectDependentCompileFiles'); const compileFiles = new Set(); const processed = new Set(); const queue: string[] = []; @@ -597,6 +630,7 @@ export abstract class BaseMode { this.logger.printError(logData); } }); + RecordTimeMem.getInstance().end('collectDependentCompileFiles'); } private shouldSkipFile(file: string, moduleInfo: ModuleInfo, filePathFromModuleRoot: string, abcFilePath: string): boolean { @@ -611,6 +645,7 @@ export abstract class BaseMode { this.collectDependentCompileFiles(); return; } + RecordTimeMem.getInstance().start('collectCompileFiles'); this.entryFiles.forEach((file: string) => { for (const [packageName, moduleInfo] of this.moduleInfos) { if (!file.startsWith(moduleInfo.moduleRootPath)) { @@ -640,6 +675,7 @@ export abstract class BaseMode { ); this.logger.printError(logData); }); + RecordTimeMem.getInstance().end('collectCompileFiles'); } protected collectAbcFileFromByteCodeHar(): void { @@ -648,6 +684,7 @@ export abstract class BaseMode { if (this.buildConfig.moduleType === OHOS_MODULE_TYPE.HAR) { return; } + RecordTimeMem.getInstance().start('collectAbcFileFromByteCodeHar'); for (const [packageName, moduleInfo] of this.moduleInfos) { if (!(moduleInfo.moduleType === OHOS_MODULE_TYPE.HAR && moduleInfo.byteCodeHar)) { continue; @@ -662,6 +699,7 @@ export abstract class BaseMode { } this.abcFiles.add(moduleInfo.abcPath); } + RecordTimeMem.getInstance().end('collectAbcFileFromByteCodeHar'); } protected generateModuleInfos(): void { @@ -675,6 +713,7 @@ export abstract class BaseMode { public async generateDeclaration(): Promise { this.generateModuleInfos(); + RecordTimeMem.getInstance().start('declgen'); const compilePromises: Promise[] = []; this.compileFiles.forEach((fileInfo: CompileFileInfo, file: string) => { compilePromises.push(new Promise((resolve) => { @@ -682,12 +721,15 @@ export abstract class BaseMode { resolve(); })); }); + RecordTimeMem.getInstance().end('declgen'); await Promise.all(compilePromises); + RecordTimeMem.getInstance().writeSum(this.cacheDir); } public async run(): Promise { this.generateModuleInfos(); + RecordTimeMem.getInstance().start('compile'); const compilePromises: Promise[] = []; this.compileFiles.forEach((fileInfo: CompileFileInfo, file: string) => { compilePromises.push(new Promise((resolve) => { @@ -696,8 +738,9 @@ export abstract class BaseMode { })); }); await Promise.all(compilePromises); - + RecordTimeMem.getInstance().end('compile'); this.mergeAbcFiles(); + RecordTimeMem.getInstance().writeSum(this.cacheDir); } // -- runParallell code begins -- @@ -711,6 +754,7 @@ export abstract class BaseMode { if (this.enableDeclgenEts2Ts) { return; } + RecordTimeMem.getInstance().start('generatedependencyFileMap'); let dependencyInputFile: string = path.join(this.cacheDir, DEPENDENCY_INPUT_FILE); let dependencyInputContent: string = ''; this.entryFiles.forEach((entryFile: string) => { @@ -768,6 +812,7 @@ export abstract class BaseMode { this.logger.printError(logData); } } + RecordTimeMem.getInstance().end('generatedependencyFileMap'); } public async runParallell(): Promise { @@ -782,7 +827,9 @@ export abstract class BaseMode { clearExitListeners: true, execPath: path.resolve(__dirname, 'compile_worker.js'), }); + RecordTimeMem.getInstance().start('compiles in tasks'); await this.dispatchTasks(); + RecordTimeMem.getInstance().end('compiles in tasks'); this.logger.printInfo('All tasks complete, merging...'); this.mergeAbcFiles(); } catch (error) { @@ -792,6 +839,7 @@ export abstract class BaseMode { )); } finally { this.terminateAllWorkers(); + RecordTimeMem.getInstance().writeSum(this.cacheDir); } } @@ -808,7 +856,9 @@ export abstract class BaseMode { clearExitListeners: true, execPath: path.resolve(__dirname, 'declgen_worker.js'), }); + RecordTimeMem.getInstance().start('declaration in tasks'); await this.dispatchTasks(); + RecordTimeMem.getInstance().end('declaration in tasks'); this.logger.printInfo('All declaration generation tasks complete.'); } catch (error) { this.logger.printError(LogDataFactory.newInstance( @@ -817,6 +867,7 @@ export abstract class BaseMode { )); } finally { this.terminateAllWorkers(); + RecordTimeMem.getInstance().writeSum(this.cacheDir); } } @@ -1362,7 +1413,10 @@ export abstract class BaseMode { const processingJobs = new Set(); const workers: ThreadWorker[] = []; + RecordTimeMem.getInstance().start('compile and merge in workers'); await this.invokeWorkers(jobs, queues, processingJobs, workers); + RecordTimeMem.getInstance().end('compile and merge in workers'); + RecordTimeMem.getInstance().writeSum(this.cacheDir); } } diff --git a/ets2panda/driver/build_system/src/build/build_mode.ts b/ets2panda/driver/build_system/src/build/build_mode.ts index b1643a8d9c..ccd53cb3a2 100644 --- a/ets2panda/driver/build_system/src/build/build_mode.ts +++ b/ets2panda/driver/build_system/src/build/build_mode.ts @@ -15,6 +15,8 @@ import { BaseMode } from './base_mode'; import { BuildConfig } from '../types'; +import { RecordTimeMem } from '../record_time_mem' +import { RECORD_COMPILE_TYPE } from '../pre_define' export class BuildMode extends BaseMode { constructor(buildConfig: BuildConfig) { @@ -22,10 +24,12 @@ export class BuildMode extends BaseMode { } public async generateDeclaration(): Promise { + RecordTimeMem.getInstance().setCompileType(RECORD_COMPILE_TYPE.DELC_TYPE); await super.generateDeclarationParallell(); } public async run(): Promise { + RecordTimeMem.getInstance().setCompileType(RECORD_COMPILE_TYPE.RUN_TYPE); await super.run(); } } \ No newline at end of file diff --git a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts index 8eb6212e58..e409e449b0 100644 --- a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts +++ b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts @@ -23,7 +23,8 @@ import { } from '../utils'; import { DECL_ETS_SUFFIX, - KOALA_WRAPPER_PATH_FROM_SDK + KOALA_WRAPPER_PATH_FROM_SDK, + RRCORD_COMPILE_NODE } from '../pre_define'; import { PluginDriver, PluginHook } from '../plugins/plugins_driver'; import { @@ -37,6 +38,7 @@ import { Logger } from '../logger'; import { ErrorCode } from '../error_code'; +import { CompileSingleData } from '../record_time_mem'; const { workerId } = workerData; @@ -51,6 +53,7 @@ function compileAbc(jobInfo: JobInfo): void { let errorStatus = false; try { let fileInfo = jobInfo.compileFileInfo; + let compileSingleData = new CompileSingleData(fileInfo.filePath, config.recordType!); ensurePathExists(fileInfo.abcFilePath); const ets2pandaCmd = [ @@ -70,14 +73,16 @@ function compileAbc(jobInfo: JobInfo): void { let context = arkts.Context.createCacheContextFromFile(arkConfig, fileInfo.filePath, jobInfo.globalContextPtr, false).peer; PluginDriver.getInstance().getPluginContext().setContextPtr(context); - + compileSingleData.record(RRCORD_COMPILE_NODE.PARSE_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, context); - + compileSingleData.record(RRCORD_COMPILE_NODE.UI1_NODE, RRCORD_COMPILE_NODE.PARSE_NODE); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + compileSingleData.record(RRCORD_COMPILE_NODE.CHECK_NODE, RRCORD_COMPILE_NODE.UI1_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, context); - + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.CHECK_NODE); if (config.hasMainModule && (config.byteCodeHar || config.moduleType === OHOS_MODULE_TYPE.SHARED)) { + compileSingleData.record(RRCORD_COMPILE_NODE.DECLGEN_NODE); let filePathFromModuleRoot: string = path.relative(config.moduleRootPath, fileInfo.filePath); let declEtsOutputPath: string = changeFileExtension( path.join(config.declgenV2OutPath as string, config.packageName, filePathFromModuleRoot), @@ -87,11 +92,15 @@ function compileAbc(jobInfo: JobInfo): void { // Generate 1.2 declaration files(a temporary solution while binary import not pushed) arkts.generateStaticDeclarationsFromContext(declEtsOutputPath); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.DECLGEN_NODE); } + compileSingleData.record(RRCORD_COMPILE_NODE.UI2_NODE); PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); - + compileSingleData.record(RRCORD_COMPILE_NODE.BIN_NODE, RRCORD_COMPILE_NODE.UI2_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, context); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.BIN_NODE); + compileSingleData.writeSumSingle(path.dirname(fileInfo.abcFilePath)); } catch (error) { errorStatus = true; if (error instanceof Error) { @@ -123,6 +132,7 @@ function compileExternalProgram(jobInfo: JobInfo): void { let errorStatus = false; try { let fileInfo = jobInfo.compileFileInfo; + let compileSingleData = new CompileSingleData(fileInfo.filePath, config.recordType!); const ets2pandaCmd = ['-', '--extension', 'ets', '--arktsconfig', fileInfo.arktsConfigFile]; if (isDebug) { @@ -137,15 +147,22 @@ function compileExternalProgram(jobInfo: JobInfo): void { PluginDriver.getInstance().getPluginContext().setContextPtr(context); + compileSingleData.record(RRCORD_COMPILE_NODE.PARSE_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, context); - + compileSingleData.record(RRCORD_COMPILE_NODE.UI1_NODE, RRCORD_COMPILE_NODE.PARSE_NODE); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + compileSingleData.record(RRCORD_COMPILE_NODE.CHECK_NODE, RRCORD_COMPILE_NODE.UI1_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, context); + compileSingleData.record(RRCORD_COMPILE_NODE.UI2_NODE, RRCORD_COMPILE_NODE.CHECK_NODE); PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); + compileSingleData.record(RRCORD_COMPILE_NODE.LOWER_NODE, RRCORD_COMPILE_NODE.UI2_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_LOWERED, context); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.LOWER_NODE); + let filePath = path.join(config.cachePath, fileInfo.packageName) + compileSingleData.writeSumSingle(filePath, '_external'); } catch (error) { errorStatus = true; if (error instanceof Error) { diff --git a/ets2panda/driver/build_system/src/build/compile_worker.ts b/ets2panda/driver/build_system/src/build/compile_worker.ts index c98142c648..2f73b8bc35 100644 --- a/ets2panda/driver/build_system/src/build/compile_worker.ts +++ b/ets2panda/driver/build_system/src/build/compile_worker.ts @@ -22,7 +22,8 @@ import { } from '../utils'; import { DECL_ETS_SUFFIX, - KOALA_WRAPPER_PATH_FROM_SDK + KOALA_WRAPPER_PATH_FROM_SDK, + RRCORD_COMPILE_NODE } from '../pre_define'; import { PluginDriver, PluginHook } from '../plugins/plugins_driver'; import { @@ -36,6 +37,7 @@ import { Logger } from '../logger'; import { ErrorCode } from '../error_code'; +import { CompileSingleData } from '../record_time_mem'; process.on('message', (message: { taskList: CompileFileInfo[]; @@ -56,6 +58,8 @@ process.on('message', (message: { for (const fileInfo of taskList) { let errorStatus = false; try { + let compileSingleData = new CompileSingleData(fileInfo.filePath, buildConfig.recordType!); + compileSingleData.record(RRCORD_COMPILE_NODE.SOURCE_NODE); ensurePathExists(fileInfo.abcFilePath); const source = fs.readFileSync(fileInfo.filePath).toString(); @@ -71,16 +75,19 @@ process.on('message', (message: { arktsGlobal.filePath = fileInfo.filePath; arktsGlobal.config = arkts.Config.create(ets2pandaCmd).peer; + compileSingleData.record(RRCORD_COMPILE_NODE.PROGRAM_NODE, RRCORD_COMPILE_NODE.SOURCE_NODE); arktsGlobal.compilerContext = arkts.Context.createFromString(source); PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); + compileSingleData.record(RRCORD_COMPILE_NODE.PARSE_NODE, RRCORD_COMPILE_NODE.PROGRAM_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); - + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.PARSE_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer); if (buildConfig.hasMainModule && (buildConfig.byteCodeHar || buildConfig.moduleType === OHOS_MODULE_TYPE.SHARED)) { + compileSingleData.record(RRCORD_COMPILE_NODE.DECLGEN_NODE); let filePathFromModuleRoot: string = path.relative(buildConfig.moduleRootPath, fileInfo.filePath); let declEtsOutputPath: string = changeFileExtension( path.join(buildConfig.declgenV2OutPath as string, buildConfig.packageName, filePathFromModuleRoot), @@ -90,11 +97,15 @@ process.on('message', (message: { // Generate 1.2 declaration files(a temporary solution while binary import not pushed) arkts.generateStaticDeclarationsFromContext(declEtsOutputPath); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.DECLGEN_NODE); } + compileSingleData.record(RRCORD_COMPILE_NODE.CHECK_NODE); PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); - + compileSingleData.record(RRCORD_COMPILE_NODE.BIN_NODE, RRCORD_COMPILE_NODE.CHECK_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, arktsGlobal.compilerContext.peer); + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.BIN_NODE); + compileSingleData.writeSumSingle(buildConfig.moduleRootPath); } catch (error) { errorStatus = true; if (error instanceof Error) { diff --git a/ets2panda/driver/build_system/src/build/declgen_worker.ts b/ets2panda/driver/build_system/src/build/declgen_worker.ts index d73fb6c3d9..f788cd20f1 100644 --- a/ets2panda/driver/build_system/src/build/declgen_worker.ts +++ b/ets2panda/driver/build_system/src/build/declgen_worker.ts @@ -23,9 +23,11 @@ import { changeFileExtension, ensurePathExists } from '../utils'; import { DECL_ETS_SUFFIX, TS_SUFFIX, - KOALA_WRAPPER_PATH_FROM_SDK + KOALA_WRAPPER_PATH_FROM_SDK, + RRCORD_COMPILE_NODE } from '../pre_define'; import { PluginDriver, PluginHook } from '../plugins/plugins_driver'; +import { CompileSingleData } from '../record_time_mem'; process.on('message', (message: { taskList: CompileFileInfo[]; @@ -49,6 +51,8 @@ process.on('message', (message: { for (const fileInfo of taskList) { let errorStatus = false; try { + let compileSingleData = new CompileSingleData(fileInfo.filePath, buildConfig.recordType!); + compileSingleData.record(RRCORD_COMPILE_NODE.SOURCE_NODE); const source = fs.readFileSync(fileInfo.filePath, 'utf8'); let moduleInfo = moduleInfosMap.get(fileInfo.packageName)!; let filePathFromModuleRoot: string = path.relative(moduleInfo.moduleRootPath, fileInfo.filePath); @@ -77,20 +81,26 @@ process.on('message', (message: { fileInfo.arktsConfigFile, fileInfo.filePath ]).peer; + compileSingleData.record(RRCORD_COMPILE_NODE.PROGRAM_NODE, RRCORD_COMPILE_NODE.SOURCE_NODE); arktsGlobal.compilerContext = arkts.Context.createFromString(source); pluginDriver.getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); + compileSingleData.record(RRCORD_COMPILE_NODE.PARSE_NODE, RRCORD_COMPILE_NODE.PROGRAM_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer, true); let ast = arkts.EtsScript.fromContext(); + compileSingleData.record(RRCORD_COMPILE_NODE.UI1_NODE, RRCORD_COMPILE_NODE.PARSE_NODE); pluginDriver.getPluginContext().setArkTSAst(ast); pluginDriver.runPluginHook(PluginHook.PARSED); + compileSingleData.record(RRCORD_COMPILE_NODE.CHECK_NODE, RRCORD_COMPILE_NODE.UI1_NODE); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer, true); + compileSingleData.record(RRCORD_COMPILE_NODE.UI2_NODE, RRCORD_COMPILE_NODE.CHECK_NODE); ast = arkts.EtsScript.fromContext(); pluginDriver.getPluginContext().setArkTSAst(ast); pluginDriver.runPluginHook(PluginHook.CHECKED); + compileSingleData.record(RRCORD_COMPILE_NODE.DECLGEN_NODE, RRCORD_COMPILE_NODE.UI2_NODE); arkts.generateTsDeclarationsFromContext( declEtsOutputPath, @@ -98,7 +108,9 @@ process.on('message', (message: { false ); // Generate 1.0 declaration files & 1.0 glue code logger.printInfo('declaration files generated'); - + compileSingleData.record(RRCORD_COMPILE_NODE.END_NODE, RRCORD_COMPILE_NODE.DECLGEN_NODE); + let filePath = path.join(buildConfig.cachePath, fileInfo.packageName) + compileSingleData.writeSumSingle(filePath, '_decl'); process.send({ success: true, filePath: fileInfo.filePath }); } catch (error) { errorStatus = true; diff --git a/ets2panda/driver/build_system/src/init/process_build_config.ts b/ets2panda/driver/build_system/src/init/process_build_config.ts index 40285b662b..6be809c151 100644 --- a/ets2panda/driver/build_system/src/init/process_build_config.ts +++ b/ets2panda/driver/build_system/src/init/process_build_config.ts @@ -36,8 +36,10 @@ import { ErrorCode } from '../error_code'; import { BuildConfig, BUILD_MODE, + RECORD_TYPE, AliasConfig } from '../types'; +import { RecordTimeMem } from '../record_time_mem'; export function processBuildConfig(projectConfig: BuildConfig): BuildConfig { let buildConfig: BuildConfig = { @@ -56,6 +58,9 @@ export function processBuildConfig(projectConfig: BuildConfig): BuildConfig { initBuildEnv(buildConfig); initKoalaWrapper(buildConfig); PluginDriver.getInstance().initPlugins(buildConfig); + buildConfig.recordType = RECORD_TYPE.DEFAULT_TYPE; + RecordTimeMem.getInstance().initRecordType(buildConfig.recordType); + initAliasConfig(buildConfig); initInteropSDKInfo(buildConfig); return buildConfig; diff --git a/ets2panda/driver/build_system/src/pre_define.ts b/ets2panda/driver/build_system/src/pre_define.ts index fa357a9e53..5017f8dac2 100644 --- a/ets2panda/driver/build_system/src/pre_define.ts +++ b/ets2panda/driver/build_system/src/pre_define.ts @@ -40,6 +40,23 @@ export const DEFAULT_WOKER_NUMS: number = 4; export const ETS_1_1 = 'ets1.1'; export const ETS_1_1_INTEROP = 'ets1.1interop'; +export enum RECORD_COMPILE_TYPE { + RUN_TYPE = 'run', + DELC_TYPE = 'Declaration', +} + +export enum RRCORD_COMPILE_NODE { + SOURCE_NODE = 'source', + PARSE_NODE = 'parse', + PROGRAM_NODE= 'program', + UI1_NODE = 'ui1', + CHECK_NODE = 'checker', + UI2_NODE = 'ui2', + BIN_NODE = 'bin', + DECLGEN_NODE = 'declgen', + LOWER_NODE = 'lower', + END_NODE = '', +} export const sdkConfigPrefix = 'ohos|system|kit|arkts'; export const NATIVE_MODULE: Set = new Set( ['system.app', 'ohos.app', 'system.router', 'system.curves', 'ohos.curves', 'system.matrix4', 'ohos.matrix4']); diff --git a/ets2panda/driver/build_system/src/record_time_mem.ts b/ets2panda/driver/build_system/src/record_time_mem.ts new file mode 100644 index 0000000000..63ef9ba387 --- /dev/null +++ b/ets2panda/driver/build_system/src/record_time_mem.ts @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as fs from 'fs'; +import path from 'path'; +import { RECORD_TYPE } from './types' + +export class TimeMemData { + public startTime: number = 0; + public endtime: number = 0; + public time: number = 0; + public startMem: number = 0; + public endMem:number = 0; + public mem: number = 0; +} + +export class SingleData { + public time: number = 0; + public mem: number = 0; +} + +export class CompileSingleData { + private timeMemMap: Map; + private totalTime: number = 0; + private startTime: number = 0; + private startMem: number = 0; + private file: string = ''; + private recordType: RECORD_TYPE; + + constructor(file: string, recordType: RECORD_TYPE) { + this.file = file; + this.timeMemMap = new Map(); + this.recordType = recordType; + } + + public record(startKey: string, lastEndKey: string = '') { + if (this.recordType == RECORD_TYPE.DEFAULT_TYPE) { + return; + } + let currentTime = new Date().getTime(); + let currentMem = process.memoryUsage.rss(); + let tmp: SingleData | undefined = this.timeMemMap.get(lastEndKey); + if (tmp) { + tmp.time = currentTime - this.startTime; + tmp.mem = (currentMem > this.startMem) ? (currentMem- this.startMem) : 0; ; + this.timeMemMap.set(lastEndKey, tmp); + } + + if (startKey == '') { + return; + } + + let tmp1: SingleData | undefined = this.timeMemMap.get(startKey); + if (tmp1 == undefined) { + this.startTime = currentTime; + this.startMem = currentMem; + let data: SingleData = new SingleData(); + data.time = 0; + data.mem = 0; + this.timeMemMap.set(startKey, data); + } + } + + writeSumSingle(cachePath: string, deputyName: string = '') { + if (this.recordType == RECORD_TYPE.DEFAULT_TYPE) { + return; + } + const csvData: string[] = [ + "timeKey, time(ms), mem(M)" + ]; + this.timeMemMap.forEach((v: SingleData, k: string) => { + let element = `${k}` +', ' + `${v.time}` + 'ms' + ', ' + `${Math.round(v.mem / 1024 / 1024)}` + 'M' ; + csvData.push(element); + }); + let name = path.basename(this.file) + let currentExt = path.extname(name) + let fileWithoutExt = name.substring(0, name.lastIndexOf(currentExt)); + let fileName = `${fileWithoutExt}`+ deputyName +'_time_mem.csv'; + let filePath = path.join(cachePath, fileName); + csvData.forEach(row => { + fs.appendFileSync(filePath, `${row}\n`); + }); + } +} + + +export class RecordTimeMem { + private static instance: RecordTimeMem | undefined; + private compileType: string = ''; + private memLow: number = 0; + private memHigh: number = 0; + private timeMemMap: Map; + private recordType: RECORD_TYPE = RECORD_TYPE.DEFAULT_TYPE;; + + public static getInstance(): RecordTimeMem { + if (!RecordTimeMem.instance) { + RecordTimeMem.instance = new RecordTimeMem(); + } + return RecordTimeMem.instance; + } + + private constructor() { + this.memLow = process.memoryUsage.rss(); + this.timeMemMap = new Map(); + } + + public setCompileType(type: string) { + this.compileType = type; + } + + public initRecordType(recordType: RECORD_TYPE) { + this.recordType = recordType; + } + + public start(timeKey: string) { + if (this.recordType == RECORD_TYPE.DEFAULT_TYPE) { + return; + } + let currentTime = new Date().getTime(); + let currentMem = process.memoryUsage.rss(); + let tmp: TimeMemData | undefined = this.timeMemMap.get(timeKey); + if (tmp) { + tmp.startTime = currentTime; + tmp.startMem = currentMem; + this.timeMemMap.set(timeKey, tmp); + } else { + let data: TimeMemData = new TimeMemData(); + data.startTime = currentTime; + data.endMem = currentMem; + this.timeMemMap.set(timeKey, data); + } + this.recordMem(); + } + + public end(timeKey: string) { + if (this.recordType == RECORD_TYPE.DEFAULT_TYPE) { + return; + } + let currentTime = new Date().getTime(); + let currentMem = process.memoryUsage.rss(); + let tmp: TimeMemData | undefined = this.timeMemMap.get(timeKey); + if (tmp) { + tmp.endtime = currentTime; + tmp.endMem = currentMem; + tmp.time = tmp.endtime - tmp.startTime; + tmp.mem = (tmp.endMem > tmp.startMem) ? (tmp.endMem - tmp.startMem) : 0; + this.timeMemMap.set(timeKey, tmp); + } + this.recordMem(); + } + + + private recordMem() { + let rss: number = process.memoryUsage.rss(); + if (rss < this.memLow) { + this.memLow = rss; + } + if (rss > this.memHigh) { + this.memHigh = rss; + } + } + + writeDataCsv(filePath: string, data: any[]) { + const content = data.map(row => { + return Object.values(row).join(','); + }).join('\n'); + fs.writeFile(filePath, content, (err) => { + if (err) { + console.error('Error writing file:', err); + } + }); + } + + writeSum(cachePath: string) { + if (this.recordType == RECORD_TYPE.DEFAULT_TYPE) { + return; + } + const csvData: any[] = []; + csvData.push({ timeKey: `memory low`, time: 'undefined', mem: `${Math.round(this.memLow / 1024 / 1024)}` + 'M' }); + csvData.push({ timeKey: `memory high`, time: 'undefined', mem: `${Math.round(this.memHigh / 1024 / 1024)}` + 'M' }); + csvData.push({ timeKey: `timeKey`, time: `time` + '(ms)', mem: `mem` + '(M)' }); + this.timeMemMap.forEach((v: TimeMemData, k: string) => { + let element = { timeKey: `${k}`, time: `${v.time}` + 'ms', mem: `${Math.round(v.mem / 1024 / 1024)}` + 'M' }; + csvData.push(element); + }) + let fileName = `${this.compileType}`+'_time_mem.csv'; + let filePath = path.join(cachePath, fileName); + this.writeDataCsv(filePath, csvData); + } +} diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index 84dd9b5082..ed10e7a0b6 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -12,6 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export enum RECORD_TYPE { + DEFAULT_TYPE = 'OFF', + ON_TYPE = 'ON', +} export enum BUILD_MODE { DEBUG = 'Debug', @@ -43,6 +47,7 @@ export interface BuildBaseConfig { arktsGlobal: ArkTSGlobal; maxWorkers?: number; isBuildConfigModified?: boolean; + recordType?: RECORD_TYPE; } export interface ArkTSGlobal { -- Gitee