UNPKG

@oaklean/cli

Version:

A command-line interface that provides utilities for parsing, inspecting, and converting the .oak file format, as well as interfaces used in the @oaklean suite.

293 lines 29.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const cli_color_1 = __importDefault(require("cli-color")); const profiler_core_1 = require("@oaklean/profiler-core"); const commander_1 = require("commander"); var TraceColors; (function (TraceColors) { TraceColors[TraceColors["LangInternal"] = 9] = "LangInternal"; TraceColors[TraceColors["External"] = 11] = "External"; TraceColors[TraceColors["WebAssembly"] = 57] = "WebAssembly"; TraceColors[TraceColors["Webpack"] = 39] = "Webpack"; })(TraceColors || (TraceColors = {})); class CPUProfileCommands { constructor() { const baseCommand = commander_1.program .command('profile') .description("commands to convert or inspect the cpu profile's format"); baseCommand .command('toCPUModel') .description('Converts a cpu profile format that is given to a cpu model format') .argument('<input>', 'input file path') .argument('<output>', 'output file path') .action(this.convertToCPUModel.bind(this)); baseCommand .command('inspect') .description('Displays an overview of the cpu profile stats') .argument('<input>', 'input file path') .action(this.inspect.bind(this)); baseCommand .command('trace') .description('Displays the trace of the cpu profile') .argument('<input>', 'input file path') .option('-r, --root-dir <rootdir>', 'specify which root dir should be used, if not set it will be determined by the config file', undefined) .option('-e, --external-resources [external-resources]', 'external resources file path - When provided, this improves file resolution accuracy and ensures source maps are taken into account.', undefined) .action(this.trace.bind(this)); baseCommand .command('anonymize') .description('Converts all paths in the cpu profile to relative paths ' + `(relative to the rootDir mentioned in the ${profiler_core_1.STATIC_CONFIG_FILENAME} config)` + ' to remove all user related paths') .argument('<input>', 'input file path') .option('-o, --output <output>', 'output file path (default: input file path)') .action(this.anonymize.bind(this)); } static init() { return new CPUProfileCommands(); } convertToCPUModel(input, output) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } let outputPath = new profiler_core_1.UnifiedPath(output); if (outputPath.isRelative()) { outputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(outputPath); } const cpuProfile = yield profiler_core_1.CPUProfileHelper.loadFromFile(inputPath); if (cpuProfile === undefined) { profiler_core_1.LoggerHelper.error(`CPU profile could not be loaded from ${inputPath.toPlatformString()}. ` + 'Please make sure the file exists and is a valid CPU profile.'); return; } const cpuModel = new profiler_core_1.CPUModel(new profiler_core_1.UnifiedPath(__dirname).join('..'), cpuProfile, BigInt(0)); yield cpuModel.storeToFile(outputPath); }); } inspect(input) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } const cpuProfile = yield profiler_core_1.CPUProfileHelper.loadFromFile(inputPath); if (cpuProfile === undefined) { profiler_core_1.LoggerHelper.error(`CPU profile could not be loaded from ${inputPath.toPlatformString()}. ` + 'Please make sure the file exists and is a valid CPU profile.'); return; } const cpuModel = new profiler_core_1.CPUModel(new profiler_core_1.UnifiedPath(__dirname).join('..'), cpuProfile, BigInt(0)); const nodeCount = cpuModel.INodes.length; const sourceNodeLocationCount = cpuModel.CPUProfileSourceLocations.length; const sampleCount = cpuModel.samples.length; let totalHits = 0; let totalCPUTime = 0; function traverse(cpuNode) { for (const child of cpuNode.children()) { totalCPUTime += child.cpuTime.selfCPUTime || 0; totalHits += child.profilerHits; traverse(child); } } traverse(cpuModel.getNode(0)); profiler_core_1.LoggerHelper.table([ { type: 'Node Count', value: nodeCount }, { type: 'Source Node Location Count', value: sourceNodeLocationCount }, { type: 'Sample Count', value: sampleCount }, { type: 'Total Hits', value: totalHits }, { type: 'Total CPU Time', value: totalCPUTime, unit: 'µs' } ], ['type', 'value', 'unit']); }); } trace(input, options) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } let externalResourcesInput = options.externalResources; if (externalResourcesInput === true) { externalResourcesInput = new profiler_core_1.ExportAssetHelper(inputPath.dirName()) .outputExternalResourceHelperPath(inputPath.filename()) .toPlatformString(); profiler_core_1.LoggerHelper.log('No external resources file provided, attempting to determine one automatically.', `Using: ${externalResourcesInput}`); } const cpuProfile = yield profiler_core_1.CPUProfileHelper.loadFromFile(inputPath); if (cpuProfile === undefined) { profiler_core_1.LoggerHelper.error(`CPU profile could not be loaded from ${inputPath.toPlatformString()}. ` + 'Please make sure the file exists and is a valid CPU profile.'); return; } let rootDir; if (options.rootDir !== undefined) { rootDir = new profiler_core_1.UnifiedPath(options.rootDir); } else { const profilerConfig = profiler_core_1.ProfilerConfig.autoResolveFromPath(inputPath.dirName()); rootDir = profilerConfig.getRootDir(); } let resolveFunctionIdentifierHelper; let externalResourceHelper; if (externalResourcesInput !== undefined) { let resourcesHelperPath = new profiler_core_1.UnifiedPath(externalResourcesInput); if (resourcesHelperPath.isRelative()) { resourcesHelperPath = new profiler_core_1.UnifiedPath(process.cwd()).join(resourcesHelperPath); } externalResourceHelper = profiler_core_1.ExternalResourceHelper.loadFromFile(rootDir, resourcesHelperPath); if (externalResourceHelper === undefined) { profiler_core_1.LoggerHelper.warn('Failed to load external resources file. Check if the file exists and is valid.'); } else { resolveFunctionIdentifierHelper = new profiler_core_1.ResolveFunctionIdentifierHelper(rootDir, externalResourceHelper); } } function colorByType(cpuNode, resolvedAsExternal) { if (cpuNode.sourceLocation.isLangInternal) { return cli_color_1.default.xterm(TraceColors.LangInternal); } else if (cpuNode.sourceLocation.isWASM) { return cli_color_1.default.xterm(TraceColors.WebAssembly); } else if (cpuNode.sourceLocation.isWebpack) { return cli_color_1.default.xterm(TraceColors.Webpack); } else if (resolvedAsExternal || cpuNode.sourceLocation.relativeUrl.toString().includes('/node_modules/')) { return cli_color_1.default.xterm(TraceColors.External); } return (arg) => arg; } const cpuModel = new profiler_core_1.CPUModel(rootDir, cpuProfile, BigInt(0)); function traverse(cpuNode_1) { return __awaiter(this, arguments, void 0, function* (cpuNode, parentsPaint = [], last = [] // specifies wether the parents are the last children ) { let selfPaint = colorByType(cpuNode, false); if (cpuNode.index === 0) { const resolvedPrefix = resolveFunctionIdentifierHelper !== undefined ? cli_color_1.default.xterm(TraceColors.LangInternal)('■ ') : ''; profiler_core_1.LoggerHelper.log(resolvedPrefix + cli_color_1.default.xterm(TraceColors.LangInternal)('■ ') + cli_color_1.default.green('({root})')); } else { let indent = ''; for (let i = 0; i < last.length - 1; i++) { if (last[i]) { indent += ' '; } else { indent += parentsPaint[i]('│ '); } } const originalPrefix = selfPaint('■ '); let resolvedPrefix = ''; let relativeFilePath = cpuNode.sourceLocation.relativeUrl.toString(); let resolvedFunctionName = ''; if (resolveFunctionIdentifierHelper !== undefined) { if (!cpuNode.sourceLocation.isLangInternal && !cpuNode.sourceLocation.isWASM) { const { sourceNodeLocation, nodeModule, relativeNodeModulePath } = yield resolveFunctionIdentifierHelper.resolveFunctionIdentifier(cpuNode.sourceLocation); relativeFilePath = sourceNodeLocation.relativeFilePath.toString(); const functionIdentifierParts = sourceNodeLocation.functionIdentifier.split('.'); resolvedFunctionName = functionIdentifierParts[functionIdentifierParts.length - 1]; if (relativeNodeModulePath !== null && nodeModule !== null) { // change color to node module selfPaint = colorByType(cpuNode, true); } } resolvedPrefix = selfPaint('■ '); } const lastIndent = parentsPaint[parentsPaint.length - 1](last[last.length - 1] ? '└' : '├') + selfPaint('─ '); console.log(originalPrefix + resolvedPrefix + indent + lastIndent + relativeFilePath + (resolvedFunctionName !== '' ? cli_color_1.default.green(` ${resolvedFunctionName}`) : '') + cli_color_1.default.green(` (${cpuNode.sourceLocation.rawFunctionName})`) + `[CM_ID: ${cpuNode.index}]`, `[LOC_ID: ${cpuNode.sourceLocation.index}]`, `[SCRIPT_ID: ${cpuNode.sourceLocation.scriptID} | ${cpuNode.sourceLocation.isLangInternal}]`, `- ${cpuNode.cpuTime.selfCPUTime} µs | ${cpuNode.cpuTime.aggregatedCPUTime} µs`); } const nodes = Array.from(cpuNode.children()); for (let i = 0; i < nodes.length; i++) { yield traverse(nodes[i], [...parentsPaint, selfPaint], [...last, i === nodes.length - 1]); } }); } // vertical legend profiler_core_1.LoggerHelper.log('\nLegend:\n' + ' ■ ' + ' Node (own code)\n' + cli_color_1.default.xterm(TraceColors.LangInternal)(' ■ ') + ' Node (node internal)\n' + cli_color_1.default.xterm(TraceColors.External)(' ■ ') + ' Node (node module)\n' + cli_color_1.default.xterm(TraceColors.WebAssembly)(' ■ ') + ' Node (WebAssembly)\n' + cli_color_1.default.xterm(TraceColors.Webpack)(' ■ ') + ' Node (Webpack)\n'); if (resolveFunctionIdentifierHelper !== undefined) { profiler_core_1.LoggerHelper.log('┌───' + ' originally from the cpu profile\n' + '│ ┌─' + ' resolved via the external resource (using sourcemaps)\n' + '│ │ '); } yield traverse(cpuModel.getNode(0)); }); } anonymize(input, options) { return __awaiter(this, void 0, void 0, function* () { let inputPath = new profiler_core_1.UnifiedPath(input); if (inputPath.isRelative()) { inputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(inputPath); } let outputPath; if (options.output === undefined) { outputPath = inputPath.copy(); } else { outputPath = new profiler_core_1.UnifiedPath(options.output); if (outputPath.isRelative()) { outputPath = new profiler_core_1.UnifiedPath(process.cwd()).join(outputPath); } } const profilerConfig = profiler_core_1.ProfilerConfig.autoResolveFromPath(inputPath.dirName()); yield profiler_core_1.CPUProfileHelper.anonymize(profilerConfig.getRootDir(), inputPath, outputPath); }); } } exports.default = CPUProfileCommands; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ1BVUHJvZmlsZUNvbW1hbmRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL0NQVVByb2ZpbGVDb21tYW5kcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUFBLDBEQUEyQjtBQUMzQiwwREFZK0I7QUFDL0IseUNBQW1DO0FBR25DLElBQUssV0FLSjtBQUxELFdBQUssV0FBVztJQUNmLDZEQUFnQixDQUFBO0lBQ2hCLHNEQUFhLENBQUE7SUFDYiw0REFBZ0IsQ0FBQTtJQUNoQixvREFBWSxDQUFBO0FBQ2IsQ0FBQyxFQUxJLFdBQVcsS0FBWCxXQUFXLFFBS2Y7QUFFRCxNQUFxQixrQkFBa0I7SUFDdEM7UUFDQyxNQUFNLFdBQVcsR0FBRyxtQkFBTzthQUN6QixPQUFPLENBQUMsU0FBUyxDQUFDO2FBQ2xCLFdBQVcsQ0FBQyx5REFBeUQsQ0FBQyxDQUFBO1FBRXhFLFdBQVc7YUFDVCxPQUFPLENBQUMsWUFBWSxDQUFDO2FBQ3JCLFdBQVcsQ0FDWCxtRUFBbUUsQ0FDbkU7YUFDQSxRQUFRLENBQUMsU0FBUyxFQUFFLGlCQUFpQixDQUFDO2FBQ3RDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsa0JBQWtCLENBQUM7YUFDeEMsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUUzQyxXQUFXO2FBQ1QsT0FBTyxDQUFDLFNBQVMsQ0FBQzthQUNsQixXQUFXLENBQUMsK0NBQStDLENBQUM7YUFDNUQsUUFBUSxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQzthQUN0QyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUVqQyxXQUFXO2FBQ1QsT0FBTyxDQUFDLE9BQU8sQ0FBQzthQUNoQixXQUFXLENBQUMsdUNBQXVDLENBQUM7YUFDcEQsUUFBUSxDQUFDLFNBQVMsRUFBRSxp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