UNPKG

@oaklean/profiler-core

Version:

Part of the @oaklean suite. It provides all basic functions to work with the `.oak` file format. It allows parsing the `.oak` file format as well as tools for analyzing the measurement values. It also provides all necessary capabilities required for prec

194 lines 21.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StateMachineLogger = void 0; const LoggerHelper_1 = require("../LoggerHelper"); class StateMachineLogger { static logState(depth, cpuNode, currentState) { var _a; /* [STATE] moduleFunction_fileA_0 (./fileA.js) ├─ Depth : 1 ├─ CPU Node : 001 ├─ ReportID : 1 ├─ SourceNodeID : 3 ├─ Scope : module ├─ Type : intern ├─ Headless : false ├─ Profiler Hits : 2 ├─ CPU Time : self=20 µs | total=30 µs ├─ CPU Energy : self=0 mJ | total=0 mJ ├─ RAM Energy : self=0 mJ | total=0 mJ */ if (currentState.callIdentifier.sourceNode === null) { LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.successString('[STATE]'), '(root)'); return; } const sourceNodeIndex = (_a = currentState.callIdentifier.sourceNode) === null || _a === void 0 ? void 0 : _a.getIndex(); if (sourceNodeIndex === undefined) { throw new Error('InsertCPUProfileStateMachine.logState: sourceNode has no index'); } const sensorValues = currentState.callIdentifier.sourceNode.sensorValues; LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.successString('[STATE]'), `${sourceNodeIndex.functionName}`, `(${sourceNodeIndex.pathIndex.identifier})`, '\n' + StateMachineLogger.formatState({ Depth: depth.toString(), 'CPU Node': String(cpuNode.index).padStart(3, '0'), ReportID: currentState.callIdentifier.report.internID.toString(), SourceNodeID: currentState.callIdentifier.sourceNode.id.toString(), Scope: currentState.scope, Type: currentState.type, Headless: currentState.headless.toString(), 'Profiler Hits': `${sensorValues.profilerHits}`, 'CPU Time': `self=${sensorValues.selfCPUTime} µs | total=${sensorValues.aggregatedCPUTime} µs | l=${sensorValues.langInternalCPUTime} µs | i=${sensorValues.internCPUTime} µs | e=${sensorValues.externCPUTime} µs`, 'CPU Energy': `self=${sensorValues.selfCPUEnergyConsumption} mJ | total=${sensorValues.aggregatedCPUEnergyConsumption} mJ | l=${sensorValues.langInternalCPUEnergyConsumption} mJ | i=${sensorValues.internCPUEnergyConsumption} mJ | e=${sensorValues.externCPUEnergyConsumption} mJ `, 'RAM Energy': `self=${sensorValues.selfRAMEnergyConsumption} mJ | total=${sensorValues.aggregatedRAMEnergyConsumption} mJ | l=${sensorValues.langInternalRAMEnergyConsumption} mJ | i=${sensorValues.internRAMEnergyConsumption} mJ | e=${sensorValues.externRAMEnergyConsumption} mJ` })); const iterators = { LANG_INTERNAL: currentState.callIdentifier.sourceNode.lang_internal.values(), INTERN: currentState.callIdentifier.sourceNode.intern.values(), EXTERN: currentState.callIdentifier.sourceNode.extern.values() }; for (const [type, iterator] of Object.entries(iterators)) { let hasEntries = false; for (const referenceSourceNode of iterator) { if (hasEntries === false) { LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.warnString(`${type} REFERENCES`)); hasEntries = true; } StateMachineLogger.logSourceNodeReference(referenceSourceNode); } } } static logSourceNodeReference(referenceSourceNode) { LoggerHelper_1.LoggerHelper.log(`SourceNodeID: ${referenceSourceNode.id.toString()}\n` + StateMachineLogger.formatReference({ 'CPU Time': `self=${referenceSourceNode.sensorValues.selfCPUTime} µs | total=${referenceSourceNode.sensorValues.aggregatedCPUTime} µs`, 'CPU Energy': `self=${referenceSourceNode.sensorValues.selfCPUEnergyConsumption} mJ | total=${referenceSourceNode.sensorValues.aggregatedCPUEnergyConsumption} mJ`, 'RAM Energy': `self=${referenceSourceNode.sensorValues.selfRAMEnergyConsumption} mJ | total=${referenceSourceNode.sensorValues.aggregatedRAMEnergyConsumption} mJ` })); } static logLeaveTransition(currentState, nextState) { var _a, _b; const currentSourceNodeIndex = (_a = currentState.callIdentifier.sourceNode) === null || _a === void 0 ? void 0 : _a.getIndex(); const currentSourceNodeName = currentSourceNodeIndex !== undefined ? currentSourceNodeIndex.functionName : '(root)'; const nextSourceNodeIndex = (_b = nextState.callIdentifier.sourceNode) === null || _b === void 0 ? void 0 : _b.getIndex(); const nextSourceNodeName = nextSourceNodeIndex !== undefined ? nextSourceNodeIndex.functionName : '(root)'; LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.errorString('[LEAVE TRANSITION]'), `${currentSourceNodeName}`, `-> ${nextSourceNodeName}`); } static logTransition(cpuNode, transition, accountingInfo, currentState, nextState) { var _a, _b; /* [TRANSITION] (root) -> moduleFunction_fileA_0 ├─ CPU Node : 000 ├─ Transition : toModule ├─ AccountingType : accountToExtern ├─ FirstTimeVisited : true ├─ Accounted Hits : 2 ├─ Accounted CPU Time : self=20 µs | total=30 µs ├─ Accounted CPU Energy : self=0 mJ | total=0 mJ ├─ Accounted RAM Energy : self=0 mJ | total=0 mJ */ const currentSourceNodeIndex = (_a = currentState.callIdentifier.sourceNode) === null || _a === void 0 ? void 0 : _a.getIndex(); const currentSourceNodeName = currentSourceNodeIndex !== undefined ? currentSourceNodeIndex.functionName : '(root)'; const nextSourceNodeIndex = (_b = nextState.callIdentifier.sourceNode) === null || _b === void 0 ? void 0 : _b.getIndex(); const nextSourceNodeName = nextSourceNodeIndex !== undefined ? nextSourceNodeIndex.functionName : '(root)'; LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.warnString('[TRANSITION]'), `${currentSourceNodeName} -> ${nextSourceNodeName}`, '\n' + StateMachineLogger.formatTransition({ 'CPU Node': String(cpuNode.index).padStart(3, '0'), Transition: transition.transition, 'Create Link': transition.options.createLink.toString(), AccountingType: accountingInfo.type, FirstTimeVisited: accountingInfo.accountedSourceNode.firstTimeVisited.toString(), 'Accounted Hits': `${cpuNode.profilerHits}`, 'Accounted CPU Time': `self=${(accountingInfo === null || accountingInfo === void 0 ? void 0 : accountingInfo.accountedSensorValues.selfCPUTime) || 0} µs | total=${(accountingInfo === null || accountingInfo === void 0 ? void 0 : accountingInfo.accountedSensorValues.aggregatedCPUTime) || 0} µs`, 'Accounted CPU Energy': `self=${(accountingInfo === null || accountingInfo === void 0 ? void 0 : accountingInfo.accountedSensorValues.selfCPUEnergyConsumption) || 0} mJ | total=${(accountingInfo === null || accountingInfo === void 0 ? void 0 : accountingInfo.accountedSensorValues.aggregatedCPUEnergyConsumption) || 0} mJ`, 'Accounted RAM Energy': `self=${(accountingInfo === null || accountingInfo === void 0 ? void 0 : accountingInfo.accountedSensorValues.selfRAMEnergyConsumption) || 0} mJ | total=${(accountingInfo === null || accountingInfo === void 0 ? void 0 : accountingInfo.accountedSensorValues.aggregatedRAMEnergyConsumption) || 0} mJ` })); } static logCompensation(depth, cpuNode, currentState, compensation, title) { /* [CREATE COMPENSATION | APPLY COMPENSATION] 2 moduleFunction_fileA_0 (./fileA.js) ├─ Depth : 2 ├─ CPU Node : 002 ├─ ReportID : 1 ├─ SourceNodeID : 5 ├─ Scope : module ├─ Type : intern ├─ Headless : false ├─ Compensated CPU Time : self=30 µs | total=0 µs ├─ Compensated CPU Energy : self=0 mJ | total=0 mJ ├─ Compensated RAM Energy : self=0 mJ | total=0 mJ */ if (currentState.callIdentifier.sourceNode === null) { LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.errorString(`[${title}]`), compensation.id.toString(), `(${cpuNode.sourceLocation.rawFunctionName})`, '~', '(root)'); return; } const sourceNodeIndex = currentState.callIdentifier.sourceNode.getIndex(); if (sourceNodeIndex === undefined) { throw new Error('InsertCPUProfileStateMachine.logCompensation: sourceNode has no index'); } const createdComp = compensation.createdComp; const carriedComp = compensation.carriedComp; LoggerHelper_1.LoggerHelper.log(LoggerHelper_1.LoggerHelper.errorString(`[${title}]`), compensation.id.toString(), `(${cpuNode.sourceLocation.rawFunctionName})`, '~', `${sourceNodeIndex.functionName}`, `(${sourceNodeIndex.pathIndex.identifier})`, '\n' + StateMachineLogger.formatCompensation({ 'Compensation ID': compensation.id.toString(), Depth: depth.toString(), 'CPU Node': String(cpuNode.index).padStart(3, '0'), ReportID: currentState.callIdentifier.report.internID.toString(), SourceNodeID: currentState.callIdentifier.sourceNode.id.toString(), Scope: currentState.scope, Type: currentState.type, Headless: currentState.headless.toString(), 'Compensated CPU Time': `created=${createdComp === null || createdComp === void 0 ? void 0 : createdComp.aggregatedCPUTime} µs | carried=${carriedComp === null || carriedComp === void 0 ? void 0 : carriedComp.aggregatedCPUTime} µs`, 'Compensated CPU Energy': `created=${createdComp === null || createdComp === void 0 ? void 0 : createdComp.aggregatedCPUEnergyConsumption} mJ | carried=${carriedComp === null || carriedComp === void 0 ? void 0 : carriedComp.aggregatedCPUEnergyConsumption} mJ`, 'Compensated RAM Energy': `created=${createdComp === null || createdComp === void 0 ? void 0 : createdComp.aggregatedRAMEnergyConsumption} mJ | carried=${carriedComp === null || carriedComp === void 0 ? void 0 : carriedComp.aggregatedRAMEnergyConsumption} mJ` })); } } exports.StateMachineLogger = StateMachineLogger; StateMachineLogger.formatReference = LoggerHelper_1.LoggerHelper.treeStyleKeyValues(['CPU Time', 'CPU Energy', 'RAM Energy'], 29); StateMachineLogger.formatState = LoggerHelper_1.LoggerHelper.treeStyleKeyValues([ 'Depth', 'CPU Node', 'ReportID', 'SourceNodeID', 'Scope', 'Type', 'Headless', 'Profiler Hits', 'CPU Time', 'CPU Energy', 'RAM Energy' ], 29); StateMachineLogger.formatTransition = LoggerHelper_1.LoggerHelper.treeStyleKeyValues([ 'CPU Node', 'Transition', 'Create Link', 'AccountingType', 'FirstTimeVisited', 'Accounted Hits', 'Accounted CPU Time', 'Accounted CPU Energy', 'Accounted RAM Energy' ], 29); StateMachineLogger.formatCompensation = LoggerHelper_1.LoggerHelper.treeStyleKeyValues([ 'Compensation ID', 'Depth', 'CPU Node', 'ReportID', 'SourceNodeID', 'Scope', 'Type', 'Headless', 'Compensated CPU Time', 'Compensated CPU Energy', 'Compensated RAM Energy' ], 29); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3RhdGVNYWNoaW5lTG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2hlbHBlci9JbnNlcnRDUFVQcm9maWxlSGVscGVyL1N0YXRlTWFjaGluZUxvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxrREFBOEM7QUFLOUMsTUFBYSxrQkFBa0I7SUF1QjlCLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBYSxFQUFFLE9BQWdCLEVBQUUsWUFBbUI7O1FBQ25FOzs7Ozs7Ozs7Ozs7O1VBYUU7UUFDRixJQUFJLFlBQVksQ0FBQyxjQUFjLENBQUMsVUFBVSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3JELDJCQUFZLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFBO1lBQ2pFLE9BQU07UUFDUCxDQUFDO1FBRUQsTUFBTSxlQUFlLEdBQUcsTUFBQSxZQUFZLENBQUMsY0FBYyxDQUFDLFVBQVUsMENBQUUsUUFBUSxFQUFFLENBQUE7UUFDMUUsSUFBSSxlQUFlLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDbkMsTUFBTSxJQUFJLEtBQUssQ0FDZCxnRUFBZ0UsQ0FDaEUsQ0FBQTtRQUNGLENBQUM7UUFFRCxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUE7UUFFeEUsMkJBQVksQ0FBQyxHQUFHLENBQ2YsMkJBQVksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEVBQ3JDLEdBQUcsZUFBZSxDQUFDLFlBQVksRUFBRSxFQUNqQyxJQUFJLGVBQWUsQ0FBQyxTQUFTLENBQUMsVUFBVSxHQUFHLEVBQzNDLElBQUk7WUFDSCxrQkFBa0IsQ0FBQyxXQUFXLENBQUM7Z0JBQzlCLEtBQUssRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFO2dCQUN2QixVQUFVLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENB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