diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/fast-arktsc/src/main.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/fast-arktsc/src/main.ts index b4267d85d63c1ab1f77f80058e809cfc2feaed89..86fc31ad0d1ab0107f8ef86ec52d12a93e907cdd 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/fast-arktsc/src/main.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/fast-arktsc/src/main.ts @@ -37,6 +37,7 @@ export const options = program .option('--aot-libs ', 'Comma-separated AOT libraries to include') .option('--only-aot ', 'AOT an .abc taking --aot-libs into account') .option('--aot-target ', 'Compilation target for AOT') + .option('--enable-report', 'Enable profiler report') .parse() .opts() @@ -70,6 +71,7 @@ function produceNinjafile( let basename = path.basename(compiler) let linker = compiler.replace(basename, 'arklink') const stages = intermediateOutDirs.length + const enableReport = options.enableReport ? "--enable-report" : "" for (var i = 0; i < stages; i++) { all.push([]) @@ -78,7 +80,7 @@ function produceNinjafile( let compilerPrefix = [...Array(stages).keys()].map((i) => ` rule arkts_compiler_stage${i} command = ${tools_prefix}${compiler} --ets-module --arktsconfig ${path.resolve(config)} --output $out ${options.restartStages ? `--restart-stages` : ``} ${stages > 1 ? `--stage ${i}` : ``} $in - description = "Compiling ARKTS ${stages > 1 ? `(stage ${i})` : ``} $in" + description = "Compiling ARKTS ${stages > 1 ? `(stage ${i})` : ``} ${enableReport} $in" `).join('') let linker_prefix = ` diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src-host/es2panda.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src-host/es2panda.ts index c4157b21476d0da82d4af88f8cfb255cbc2c3661..08dd190a09c87ce678f4aee6998731d56ad988d2 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src-host/es2panda.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src-host/es2panda.ts @@ -15,7 +15,7 @@ import * as fs from "node:fs" import * as path from "node:path" -import { checkSDK, arktsGlobal as global, ImportStorage, ETSModule, ProgramProvider, metaDatabase, runTransformer, RunTransformerContext } from "@koalaui/libarkts" +import { checkSDK, arktsGlobal as global, ImportStorage, ETSModule, ProgramProvider, metaDatabase, runTransformer, RunTransformerContext, Profiler } from "@koalaui/libarkts" import { CheckedBackFilter, ChainExpressionFilter, PluginContext, PluginContextImpl } from "@koalaui/libarkts" import { Command } from "commander" import { filterSource, isNumber, throwError, withWarning } from "@koalaui/libarkts" @@ -32,6 +32,7 @@ function parseCommandLineArgs() { .option('--dump-plugin-ast', 'Dump ast before and after each plugin') .option('--restart-stages', 'Restart the compiler to proceed to next stage') .option('--stage ', 'Stage of multistage compilation (from 0 to number of plugins in arktsconfig + 1)') + .option('--enable-report', 'Enable profiler report') .parse(process.argv) const cliOptions = commander.opts() @@ -53,8 +54,9 @@ function parseCommandLineArgs() { const dumpAst = cliOptions.dumpPluginAst ?? false const restartStages = cliOptions.restartStages ?? false const stage = cliOptions.stage ?? 0 + const enableReport = cliOptions.enableReport ?? false - return { filePath, configPath, outputPath, dumpAst, restartStages, stage } + return { filePath, configPath, outputPath, dumpAst, restartStages, stage, enableReport } } function insertPlugin( @@ -65,9 +67,10 @@ function insertPlugin( dumpAst: boolean, restart: boolean, context: PluginContext, + profiler?: Profiler, updateWith?: (node: AstNode) => void ): AstNode { - proceedToState(state) + proceedToState(state, profiler) const script = createETSModuleFromContext() // Or this: const script = createETSModuleFromSource(source) if (script === undefined) { @@ -79,24 +82,17 @@ function insertPlugin( console.log(filterSource(script.dumpSrc())) } - - global.profiler.curPlugin = pluginName - global.profiler.transformStarted() - runTransformer(global.compilerContext.program, state, transform, context, { onProgramTransformStart(ctx: RunTransformerContext) { - if (!ctx.isMainProgram) global.profiler.transformDepStarted() + profiler?.transformStarted(state, pluginName) + if (!ctx.isMainProgram) profiler?.transformDepStarted() }, onProgramTransformEnd(ctx: RunTransformerContext) { - if (!ctx.isMainProgram) { - global.profiler.transformDepEnded(state, pluginName) - } + profiler?.transformEnded(state, pluginName) + if (!ctx.isMainProgram) profiler?.transformDepEnded(state, pluginName) return !restart } }) - - global.profiler.transformEnded(state, pluginName) - global.profiler.curPlugin = "" if (dumpAst) { console.log(`AFTER ${stateName(state)}:`) @@ -168,7 +164,10 @@ function invokeWithPlugins( restart: boolean, stage: number, pluginNames: string[], + profiler?: Profiler ): void { + profiler?.compilationStarted(filePath) + const source = fs.readFileSync(filePath).toString() const sdk = process.env.PANDA_SDK_PATH ?? withWarning( defaultPandaSdk, @@ -220,7 +219,7 @@ function invokeWithPlugins( if (pluginsApplied == stage) { // uncomment if switch to dets generator // restartCompiler(configPath, filePath, stdlib, outputPath, false) - generateDeclFromCurrentContext(newFilePath) + generateDeclFromCurrentContext(newFilePath, profiler) } pluginsApplied++ const before = Date.now() @@ -228,7 +227,7 @@ function invokeWithPlugins( const after = Date.now() configPath = newConfigPath filePath = newFilePath - global.profiler.restarted(after - before) + profiler?.restarted(after - before) } } @@ -236,31 +235,31 @@ function invokeWithPlugins( context.setParameter("restart", restart) - global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_PARSED pluginsByState.get(Es2pandaContextState.ES2PANDA_STATE_PARSED)?.forEach(plugin => { - insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_PARSED, pluginNames[pluginsApplied], dumpAst, restart, context) + insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_PARSED, pluginNames[pluginsApplied], dumpAst, restart, context, profiler) restartProcedure(Es2pandaContextState.ES2PANDA_STATE_PARSED) }) - global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_BOUND pluginsByState.get(Es2pandaContextState.ES2PANDA_STATE_BOUND)?.forEach(plugin => { - insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_BOUND, pluginNames[pluginsApplied], dumpAst, restart, context, rebindSubtree) + insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_BOUND, pluginNames[pluginsApplied], dumpAst, restart, context, profiler, rebindSubtree) restartProcedure(Es2pandaContextState.ES2PANDA_STATE_BOUND) }) - global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_CHECKED pluginsByState.get(Es2pandaContextState.ES2PANDA_STATE_CHECKED)?.forEach(plugin => { - insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_CHECKED, pluginNames[pluginsApplied], dumpAst, restart, context, recheckSubtree) + insertPlugin(source, plugin, Es2pandaContextState.ES2PANDA_STATE_CHECKED, pluginNames[pluginsApplied], dumpAst, restart, context, profiler, recheckSubtree) restartProcedure(Es2pandaContextState.ES2PANDA_STATE_CHECKED) }) - global.profiler.curContextState = Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED - proceedToState(Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED) + proceedToState(Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, profiler) + + profiler?.compilationEnded() + profiler?.report() + profiler?.reportToFile(true) } const exportsFromInitialFile: string[] = [] -function generateDeclFromCurrentContext(filePath: string): never { - proceedToState(Es2pandaContextState.ES2PANDA_STATE_PARSED) +function generateDeclFromCurrentContext(filePath: string, profiler?: Profiler): never { + proceedToState(Es2pandaContextState.ES2PANDA_STATE_PARSED, profiler) console.log(`Emitting to ${filePath}`) let out = [ filterSource( @@ -272,9 +271,6 @@ function generateDeclFromCurrentContext(filePath: string): never { ].join('\n') fs.mkdirSync(path.dirname(filePath), { recursive: true }) fs.writeFileSync(filePath, out) - global.profiler.compilationEnded() - global.profiler.report() - global.profiler.reportToFile() process.exit(0) } @@ -322,7 +318,7 @@ function readAndSortPlugins(configDir: string, plugins: any[]) { export function main() { checkSDK() - const { filePath, configPath, outputPath, dumpAst, restartStages, stage } = parseCommandLineArgs() + const { filePath, configPath, outputPath, dumpAst, restartStages, stage, enableReport } = parseCommandLineArgs() const arktsconfig = JSON.parse(fs.readFileSync(configPath).toString()) const configDir = path.dirname(configPath) const compilerOptions = arktsconfig.compilerOptions ?? throwError(`arktsconfig should specify compilerOptions`) @@ -334,11 +330,7 @@ export function main() { const pluginsByState = readAndSortPlugins(configDir, plugins) - global.profiler.compilationStarted(filePath) - invokeWithPlugins(configPath, packageName, baseUrl, outDir, filePath, outputPath, pluginsByState, dumpAst, restartStages, stage, pluginNames) - global.profiler.compilationEnded() - global.profiler.report() - global.profiler.reportToFile(true) + invokeWithPlugins(configPath, packageName, baseUrl, outDir, filePath, outputPath, pluginsByState, dumpAst, restartStages, stage, pluginNames, enableReport ? new Profiler() : undefined) } function reportErrorAndExit(message: string): never { diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts index 55fbcf5a0bf6046a026cdc1f29e35ff879572011..6413ecee85a80a0cac4a18c4628da9d7d6368d27 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/peers/AstNode.ts @@ -22,7 +22,6 @@ import { ArktsObject } from "./ArktsObject" export abstract class AstNode extends ArktsObject { protected constructor(peer: KNativePointer) { - global.profiler.nodeCreated() if (isNullPtr(peer)) { throwError(`attempted to create AstNode from nullptr`) } diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/global.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/global.ts index d1e747f2bd09903cb048b23dbdf4a1aca2b2faaf..b094f9b6159c86d8e2d3449726f38c8220e2ac0a 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/global.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/global.ts @@ -19,7 +19,6 @@ import { initEs2panda, Es2pandaNativeModule, initGeneratedEs2panda } from "../.. import { Es2pandaNativeModule as GeneratedEs2pandaNativeModule } from "../../generated/Es2pandaNativeModule" import { initInterop, InteropNativeModule } from "../../InteropNativeModule" import { Context } from "../peers/Context" -import { Profiler } from "./profiler" export class global { public static filePath: string = "./plugins/input/main.ets" @@ -73,6 +72,4 @@ export class global { return this._interop } - - public static profiler = new Profiler() } diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/profiler.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/profiler.ts index 7ceee45fd15ba84d317a91424581153c93b7a955..106c84b12096896fa7efba2796a219d2da225192 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/profiler.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/static/profiler.ts @@ -54,11 +54,16 @@ interface PerformanceDataFile { } function parseFile(performanceFile: string): PerformanceDataFile | undefined { + performanceFile = path.resolve(performanceFile) if (!fs.existsSync(performanceFile)) return undefined - const data = fs.readFileSync(path.resolve(performanceFile)).toString() - if (!data.length) return undefined - return JSON.parse(data) as PerformanceDataFile + const fileData = fs.readFileSync(performanceFile).toString() + if (!fileData.length) return undefined + try { + return JSON.parse(fileData) as PerformanceDataFile + } catch (error) { + return undefined + } } export class Profiler implements PerformanceData { @@ -70,8 +75,8 @@ export class Profiler implements PerformanceData { totalTime: number = 0 pluginsByName: Record = {} - curPlugin: string = "" - curContextState?: Es2pandaContextState + private curPlugin: string = "" + private curContextState?: Es2pandaContextState private getPluginData(pluginName: string, contextState?: Es2pandaContextState): PluginData { if (!(pluginName in this.pluginsByName)) { @@ -80,8 +85,6 @@ export class Profiler implements PerformanceData { return this.pluginsByName[pluginName] } - disableReport = false - nodeCreated() { this.createdNodes++ if (this.curPlugin) this.getPluginData(this.curPlugin, this.curContextState).createdNodes++ @@ -93,7 +96,9 @@ export class Profiler implements PerformanceData { } private transformStartTime = 0 - transformStarted() { + transformStarted(state: Es2pandaContextState, pluginName: string) { + this.curPlugin = pluginName + this.curContextState = state this.transformStartTime = Date.now() } private transformDepStartTime = 0 @@ -105,6 +110,8 @@ export class Profiler implements PerformanceData { const transformEndTime = Date.now() const consumedTime = transformEndTime - this.transformStartTime this.getPluginData(pluginName, state).transformTime += consumedTime + this.curPlugin = "" + this.curContextState = undefined } transformDepEnded(state: Es2pandaContextState, pluginName: string) { @@ -133,23 +140,22 @@ export class Profiler implements PerformanceData { } report() { - Object.entries(this.pluginsByName).forEach((data, key) => { - console.log(data[0], "totalTransformTime =", data[1].transformTime, "ms") - console.log(data[0], "totalDepsTransformTime =", data[1].transformTimeDeps, "ms") + Object.entries(this.pluginsByName).forEach(([pluginName, data], key) => { + console.log(pluginName, "totalTransformTime =", data.transformTime, "ms") + console.log(pluginName, "totalDepsTransformTime =", data.transformTimeDeps, "ms") }) } reportToFile(withSummary: boolean = false) { - if (this.disableReport) return const outDir = path.resolve(global.outDir, "./performance-results/") if (!fs.existsSync(outDir)) fs.mkdirSync(outDir) const outFilePath = path.resolve(outDir, path.basename(this.filePath)) + ".json" - const data: PerformanceDataFile = { data: [this as PerformanceData] } + const curData: PerformanceDataFile = { data: [this as PerformanceData] } if (!fs.existsSync(outFilePath)) { - fs.writeFileSync(outFilePath, JSON.stringify(data)) + fs.writeFileSync(outFilePath, JSON.stringify(curData)) } else { - const savedData: PerformanceDataFile | undefined = parseFile(outFilePath) ?? data + const savedData: PerformanceDataFile | undefined = parseFile(outFilePath) ?? curData savedData.data.push(this as PerformanceData) if (withSummary) { diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/utilities/public.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/utilities/public.ts index d32656ada3cd0f7b3cdee948e37728399f68951b..c5499826719b6ae65eb106d0568529beab2582f8 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/utilities/public.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/utilities/public.ts @@ -37,6 +37,7 @@ import { import { Config } from "../peers/Config" import { Context } from "../peers/Context" import { NodeCache } from "../node-cache" +import { Profiler } from "../static/profiler" export function createETSModuleFromContext(): ETSModule { let program = global.es2panda._ContextProgram(global.context) @@ -91,14 +92,14 @@ export function checkErrors() { } } -export function proceedToState(state: Es2pandaContextState): void { +export function proceedToState(state: Es2pandaContextState, profiler?: Profiler): void { if (state <= global.es2panda._ContextState(global.context)) { return } const before = Date.now() global.es2panda._ProceedToState(global.context, state) const after = Date.now() - global.profiler.proceededToState(after-before) + profiler?.proceededToState(after-before) NodeCache.clear() checkErrors() } diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/visitor.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/visitor.ts index f1fb3340f7359b14201ecbee80fa94c4c9cef06b..ca8e43c3a30f40b0a728ef49df69452aefda4d56 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/visitor.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/arkts-api/visitor.ts @@ -144,7 +144,6 @@ export function visitEachChild( node: AstNode, visitor: Visitor ): AstNode { - global.profiler.nodeVisited() if (isETSModule(node)) { return updateETSModuleByStatements( node, diff --git a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/index.ts b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/index.ts index 4b942ad8933e8dc2b9599b86704d0add949ae147..363ab0b2f30e84a2b6f8860b32a73baf91fea794 100644 --- a/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/index.ts +++ b/frameworks/bridge/arkts_frontend/koala_projects/ui2abc/libarkts/src/index.ts @@ -39,6 +39,7 @@ export * from "./arkts-api/peers/Context" export * from "./arkts-api/peers/ExternalSource" export * from "./arkts-api/peers/ImportPathManager" export { global as arktsGlobal } from "./arkts-api/static/global" +export { Profiler } from "./arkts-api/static/profiler" export * as arkts from "./arkts-api" export { runTransformer, RunTransformerContext, RunTransformerHooks } from "./plugin-utils" \ No newline at end of file