@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
JavaScript
;
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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