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

177 lines 14 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CPUModel = void 0; const CPUNode_1 = require("./CPUNode"); const CPUProfileSourceLocation_1 = require("./CPUProfileSourceLocation"); const PermissionHelper_1 = require("../PermissionHelper"); const model_1 = require("../../../lib/vscode-js-profile-core/src/cpu/model"); const JSONHelper_1 = require("../JSONHelper"); // Types const types_1 = require("../../types"); class CPUModel { constructor(rootDir, profile, highResolutionBeginTime) { this.rootDir = rootDir; this._startTime = profile.startTime; this._endTime = profile.endTime; this.cpuModel = (0, model_1.buildModel)(profile); this.sourceLocations = this.cpuModel.locations.map((location) => new CPUProfileSourceLocation_1.CPUProfileSourceLocation(this.rootDir, location.id, location.callFrame)); this._cpuProfilerBeginTime = highResolutionBeginTime; this._cpuNodes = new Map(); this._profilerHitsPerNode = new Array(this.INodes.length).fill(0); for (const sampleId of this.cpuModel.samples) { this._profilerHitsPerNode[sampleId] += 1; } } get profilerHitsPerNode() { return this._profilerHitsPerNode; } set energyValuesPerNode(values) { if (!values || values.length !== this.INodes.length) { throw new Error('CPUModel.energyValuesPerNode: node size and energy value size must be the same'); } this._energyValuesPerNode = values; } /** * energyValuesPerNode is a tuple based array * * index 0 of each tuple represents the cpuEnergy * index 1 of each tuple represents the ramEnergy */ get energyValuesPerNode() { return this._energyValuesPerNode; } get CPUProfileSourceLocations() { return this.sourceLocations; } get INodes() { return this.cpuModel.nodes; } get timeDeltas() { return this.cpuModel.timeDeltas; } get samples() { return this.cpuModel.samples; } get startTime() { return this._startTime; } get endTime() { return this._endTime; } energyValuesPerNodeByMetricsData(metricsDataCollection) { /** * When the measurement begins, the sensor interface starts first, * and its starting time is stored in (sensorDataBeginTime). * After a while, the V8 CPU profiler starts, and its start time is stored in (this._highResolutionBeginTime). * * The CPU measurements are stored in multiple intervals, * and all interval lengths are stored in this.timeDeltas[]. * * this.timeDeltas[] * | - - - - - - - - - | 0 1 2 3 4 5 6 7 8 9 | * ^ ^ * | | * | this._highResolutionBeginTime * | * sensorDataBeginTime * * The measurements of the sensor interface are also stored as intervals in (metricsDataCollection.items) * * metricsDataCollection.items * | ----- ----- ----- ----- ----- ----- ----| * * Each line segment represents the duration of a metricsData object (of metricsDataCollection.items) * */ /** * energyValuesPerNode is a tuple based array * * index 0 of each tuple represents the cpuEnergy * index 1 of each tuple represents the ramEnergy */ const energyValuesPerNode = new Array(this.INodes.length).fill([0, 0]); const sensorDataBeginTime = metricsDataCollection.items[0].startTime; let offset = (this._cpuProfilerBeginTime - sensorDataBeginTime + BigInt(this.timeDeltas[0] * 1000)); if (offset < BigInt(0)) { throw new Error('V8 Profile was measured before the sensor interface began to measure'); } let currentItemNumber = 0; let currentMetricsData = metricsDataCollection.items[currentItemNumber]; let energyOfMeasuredProcess = undefined; for (let i = 1; i < this.timeDeltas.length; i++) { if (offset > currentMetricsData.duration) { if (currentItemNumber >= metricsDataCollection.items.length) { throw new Error('The sensor interface did not measure the whole time the V8 Profiler was running'); } offset = (offset - currentMetricsData.duration); currentMetricsData = metricsDataCollection.items[++currentItemNumber]; if (currentMetricsData === undefined) { break; } energyOfMeasuredProcess = undefined; i--; // move one step back to begin at the same timeDelta again but with the next metricsData profile continue; } if (energyOfMeasuredProcess === undefined) { if (currentMetricsData.processIsPresent(metricsDataCollection.pid)) { const factor = currentMetricsData.energyPortionOfProcess(metricsDataCollection.pid); energyOfMeasuredProcess = [ (factor * currentMetricsData.cpuEnergy()), (factor * currentMetricsData.ramEnergy()) ]; } else { // sometimes outputs of a sensor interface do not include the measured process (e.g. powermetrics) // It's not clear why this happens, as the PID is present in later reports again. // one reason could be that the energy usage of the process was negligible and therefore not present energyOfMeasuredProcess = [ 0, 0 ]; } } energyValuesPerNode[this.samples[i - 1]] = [ (energyOfMeasuredProcess[types_1.EnergyValuesType.CPU] * (this.timeDeltas[i] / Number(currentMetricsData.duration))), (energyOfMeasuredProcess[types_1.EnergyValuesType.RAM] * (this.timeDeltas[i] / Number(currentMetricsData.duration))) ]; offset = (offset + BigInt(this.timeDeltas[i] * 1000)); } return energyValuesPerNode; } getNode(index) { let node = this._cpuNodes.get(index); if (node === undefined) { node = new CPUNode_1.CPUNode(index, this, this.cpuModel.nodes[index]); this._cpuNodes.set(index, node); } return node; } storeToFile(filePath) { return __awaiter(this, void 0, void 0, function* () { yield PermissionHelper_1.PermissionHelper.writeFileWithStorageFunctionWithUserPermissionAsync(filePath, () => __awaiter(this, void 0, void 0, function* () { yield JSONHelper_1.JSONHelper.storeBigJSON(filePath, this, // eslint-disable-next-line (key, value) => typeof value === 'bigint' ? value.toString() : value, // return everything else unchanged 2); })); }); } } exports.CPUModel = CPUModel; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ1BVTW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaGVscGVyL0NQVVByb2ZpbGUvQ1BVTW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQW1DO0FBQ25DLHlFQUFxRTtBQUVyRSwwREFBc0Q7QUFDdEQsNkVBSTBEO0FBSTFELDhDQUEwQztBQUMxQyxRQUFRO0FBQ1IsdUNBS29CO0FBRXBCLE1BQWEsUUFBUTtJQWVwQixZQUNDLE9BQW9CLEVBQ3BCLE9BQXVCLEVBQ3ZCLHVCQUEyQztRQUUzQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtRQUN0QixJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUE7UUFDbkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFBO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBQSxrQkFBVSxFQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ25DLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUNqRCxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQ1osSUFBSSxtREFBd0IsQ0FDM0IsSUFBSSxDQUFDLE9BQU8sRUFDWixRQUFRLENBQUMsRUFBRSxFQUNYLFFBQVEsQ0FBQyxTQUFTLENBQ2xCLENBQ0YsQ0FBQTtRQUVELElBQUksQ0FBQyxxQkFBcUIsR0FBRyx1QkFBdUIsQ0FBQTtRQUNwRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksR0FBRyxFQUFtQixDQUFBO1FBQzNDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNqRSxLQUFLLE1BQU0sUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFF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