@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
292 lines • 26.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SourceFileMetaData = exports.AggregatedSourceNodeMetaData = void 0;
const BaseModel_1 = require("./BaseModel");
const ModelMap_1 = require("./ModelMap");
const SourceNodeMetaData_1 = require("./SourceNodeMetaData");
const SensorValues_1 = require("./SensorValues");
const SourceNodeRegex_1 = require("../constants/SourceNodeRegex");
const BufferHelper_1 = require("../helper/BufferHelper");
// Types
const types_1 = require("../types");
class AggregatedSourceNodeMetaData extends BaseModel_1.BaseModel {
constructor(total, max) {
super();
this.total = total;
this.max = max;
}
toBuffer() {
throw new Error('ModelMap.toBuffer: not yet implemented');
}
toJSON() {
return {
total: this.total.toJSON(),
max: this.max.toJSON()
};
}
static join(...args) {
return new AggregatedSourceNodeMetaData(SourceNodeMetaData_1.SourceNodeMetaData.sum(...args.map((x) => x.total)), SourceNodeMetaData_1.SourceNodeMetaData.max(...args.map((x) => x.max)));
}
static fromJSON(json) {
let data;
if (typeof json === 'string') {
data = JSON.parse(json);
}
else {
data = json;
}
return new AggregatedSourceNodeMetaData(SourceNodeMetaData_1.SourceNodeMetaData.fromJSON(data.total, undefined), SourceNodeMetaData_1.SourceNodeMetaData.fromJSON(data.max, undefined));
}
}
exports.AggregatedSourceNodeMetaData = AggregatedSourceNodeMetaData;
class SourceFileMetaData extends BaseModel_1.BaseModel {
constructor(path, pathIndex) {
super();
this.path = path;
this.pathIndex = pathIndex;
}
get containsUncommittedChanges() {
if (this.pathIndex === undefined) {
return false;
}
return this.pathIndex.containsUncommittedChanges;
}
set containsUncommittedChanges(v) {
if (this.pathIndex !== undefined) {
this.pathIndex.containsUncommittedChanges = v;
}
}
normalize(newGlobalIndex) {
const newPathIndex = this.pathIndex.insertToOtherIndex(newGlobalIndex);
const newFunctions = new ModelMap_1.ModelMap('number');
for (const sourceNodeID of Array.from(this.functions.keys()).sort()) {
const sourceNodeMetaData = this.functions.get(sourceNodeID);
sourceNodeMetaData.normalize(newGlobalIndex);
newFunctions.set(sourceNodeMetaData.id, sourceNodeMetaData);
}
this.pathIndex = newPathIndex;
this._functions = newFunctions;
}
static merge(pathIndex, ...args) {
if (args.length === 0) {
throw new Error('SourceFileMetaData.merge: no SourceFileMetaDatas were given');
}
const path = args[0].path;
const containsUncommittedChanges = args.map((x) => x.containsUncommittedChanges).reduce((prevValue, currValue) => prevValue || currValue);
const valuesToMerge = {
functions: {}
};
for (const currentSourceFileMetaData of args) {
if (path !== currentSourceFileMetaData.path) {
throw new Error('SourceFileMetaData.merge: all SourceFileMetaDatas should be from the same file.');
}
for (const [sourceNodeID, sourceNodeMetaData] of currentSourceFileMetaData.functions) {
const sourceNodeIndex = currentSourceFileMetaData.getSourceNodeIndexByID(sourceNodeID);
if (sourceNodeIndex === undefined) {
throw new Error('SourceFileMetaData.merge: could not resolve sourceNode from id');
}
const identifier = sourceNodeIndex.identifier;
if (!valuesToMerge.functions[identifier]) {
valuesToMerge.functions[identifier] = [];
}
valuesToMerge.functions[identifier].push(sourceNodeMetaData);
}
}
const result = new SourceFileMetaData(path, pathIndex);
for (const [identifier, sourceNodeMetaDatas] of Object.entries(valuesToMerge.functions)) {
const sourceNodeIndex = result.getSourceNodeIndex('upsert', identifier);
const sourceNodeID = sourceNodeIndex.id;
result.functions.set(sourceNodeID, SourceNodeMetaData_1.SourceNodeMetaData.merge(sourceNodeID, sourceNodeIndex, ...sourceNodeMetaDatas));
}
result.containsUncommittedChanges = containsUncommittedChanges;
return result;
}
get functions() {
if (!this._functions) {
this._functions = new ModelMap_1.ModelMap('number');
}
return this._functions;
}
getSourceNodeIndexByID(id) {
return this.pathIndex.moduleIndex.globalIndex.getSourceNodeIndexByID(id);
}
getSourceNodeIndex(indexRequestType, sourceNodeIdentifier) {
return this.
pathIndex.getSourceNodeIndex(indexRequestType, sourceNodeIdentifier);
}
removeFromIntern(filePath) {
let filePaths = [];
if (typeof filePath === 'string') {
filePaths = [filePath];
}
else {
filePaths = filePath;
}
for (const sourceNodeMetaData of this.functions.values()) {
sourceNodeMetaData.removeFromIntern(filePaths);
}
}
validate() {
for (const [sourceNodeID, sourceNodeMetaData] of this.functions.entries()) {
const sourceNodeIndex = this.getSourceNodeIndexByID(sourceNodeID);
if (sourceNodeIndex === undefined) {
throw new Error('SourceFileMetaData.validate: could not resolve source node index');
}
const identifier = sourceNodeIndex === null || sourceNodeIndex === void 0 ? void 0 : sourceNodeIndex.identifier;
if (sourceNodeMetaData.type === types_1.SourceNodeMetaDataType.LangInternalSourceNode) {
if (!SourceNodeRegex_1.LangInternalSourceNodeIdentifierRegex.test(identifier)) {
throw new Error('SourceFileMetaData.validate: invalid LangInternalSourceNodeIdentifier_string:'
+ identifier + '\n' +
SourceNodeRegex_1.LangInternalSourceNodeIdentifierRegexString);
}
}
else {
if (!SourceNodeRegex_1.SourceNodeIdentifierRegex.test(identifier)) {
throw new Error(`SourceFileMetaData.validate: invalid sourceNodeIdentifier: ${identifier}\n` +
SourceNodeRegex_1.SourceNodeIdentifierRegexString);
}
}
sourceNodeMetaData.validate(this.path, identifier);
}
}
toJSON() {
if (process.env.NODE_ENV === 'test') {
this.validate();
}
return {
path: this.path,
functions: this.functions.toJSON()
};
}
static fromJSON(json, pathIndex) {
let data;
if (typeof json === 'string') {
data = JSON.parse(json);
}
else {
data = json;
}
const result = new SourceFileMetaData(data.path, pathIndex);
if (data.functions) {
for (const [sourceNodeID_string, nodeMetaData] of Object.entries(data.functions)) {
const sourceNodeID = parseInt(sourceNodeID_string);
result.functions.set(sourceNodeID, SourceNodeMetaData_1.SourceNodeMetaData.fromJSON(nodeMetaData, pathIndex.moduleIndex.globalIndex));
}
}
return result;
}
createOrGetSourceNodeMetaData(identifier, type) {
const sourceNodeIndex = this.getSourceNodeIndex('upsert', identifier);
const sourceNodeID = sourceNodeIndex.id;
let node = this.functions.get(sourceNodeID);
if (!node) {
node = new SourceNodeMetaData_1.SourceNodeMetaData(type, sourceNodeID, new SensorValues_1.SensorValues({}), sourceNodeIndex);
this.functions.set(sourceNodeID, node);
}
return node;
}
/**
* Calculates the total SourceNodeMetaData for the SourceFile
*
* hits, selfTime, aggregatedTime, langInternalTime, externTime and internTime are added up
*
* intern self references are removed
*
* @returns number
*/
totalSourceNodeMetaData() {
const listToSum = [];
const intern = new ModelMap_1.ModelMap('number');
const extern = new ModelMap_1.ModelMap('number');
const langInternal = new ModelMap_1.ModelMap('number');
for (const sourceNodeMetaData of this.functions.values()) {
listToSum.push(sourceNodeMetaData);
for (const sourceNodeMetaDataReferences of [
sourceNodeMetaData.lang_internal,
sourceNodeMetaData.intern,
sourceNodeMetaData.extern
]) {
for (const sourceNodeMetaDataReference of sourceNodeMetaDataReferences.values()) {
const pathID = sourceNodeMetaDataReference.sourceNodeIndex.pathIndex.id;
if (pathID === undefined) {
throw new Error('totalSourceNodeMetaData: expected pathID');
}
switch (sourceNodeMetaDataReferences) {
case sourceNodeMetaData.lang_internal:
{
const sensorValuesOfFile = langInternal.get(pathID);
langInternal.set(pathID, SensorValues_1.SensorValues.sum(sourceNodeMetaDataReference.sensorValues, ...(sensorValuesOfFile ? [sensorValuesOfFile] : [])));
}
break;
case sourceNodeMetaData.intern:
{
const sensorValuesOfFile = intern.get(pathID);
intern.set(pathID, SensorValues_1.SensorValues.sum(sourceNodeMetaDataReference.sensorValues, ...(sensorValuesOfFile ? [sensorValuesOfFile] : [])));
}
break;
case sourceNodeMetaData.extern:
{
const sensorValuesOfFile = extern.get(pathID);
extern.set(pathID, SensorValues_1.SensorValues.sum(sourceNodeMetaDataReference.sensorValues, ...(sensorValuesOfFile ? [sensorValuesOfFile] : [])));
}
break;
}
}
}
}
if (this.pathIndex.id === undefined) {
throw new Error('totalSourceNodeMetaData: expected pathIndex.id');
}
const selfReference = intern.get(this.pathIndex.id);
const result = SourceNodeMetaData_1.SourceNodeMetaData.sum(...listToSum);
if (selfReference !== undefined) {
// remove self references
result.sensorValues.addToIntern(selfReference, -1);
result.sensorValues.addToAggregated(selfReference, -1);
// remove self references
intern.delete(this.pathIndex.id);
}
return {
sum: result,
intern,
extern,
langInternal
};
}
maxSourceNodeMetaData() {
return SourceNodeMetaData_1.SourceNodeMetaData.max(...this.functions.values());
}
toBuffer() {
const id = this.pathIndex.id;
if (id === undefined) {
throw new Error('SourceFileMetaData.toBuffer: expected id');
}
const buffers = [
BufferHelper_1.BufferHelper.UIntToBuffer(id),
this.functions.toBuffer()
];
return Buffer.concat(buffers);
}
static consumeFromBuffer(buffer, globalIndex) {
let remainingBuffer = buffer;
const { instance: pathID, remainingBuffer: newRemainingBuffer1 } = BufferHelper_1.BufferHelper.UIntFromBuffer(remainingBuffer);
remainingBuffer = newRemainingBuffer1;
const pathIndex = globalIndex.getPathIndexByID(pathID);
if (pathIndex === undefined) {
throw new Error('SourceFileMetaData.consumeFromBuffer: could not resolve pathIndex');
}
const instance = new SourceFileMetaData(pathIndex.identifier, pathIndex);
const consumeFromBufferWithModuleIndex = (buffer) => {
return SourceNodeMetaData_1.SourceNodeMetaData.consumeFromBuffer(buffer, globalIndex);
};
const { instance: functions, remainingBuffer: newRemainingBuffer2 } = ModelMap_1.ModelMap.consumeFromBuffer(remainingBuffer, 'number', consumeFromBufferWithModuleIndex);
instance._functions = functions;
remainingBuffer = newRemainingBuffer2;
return {
instance,
remainingBuffer
};
}
}
exports.SourceFileMetaData = SourceFileMetaData;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU291cmNlRmlsZU1ldGFEYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZGVsL1NvdXJjZUZpbGVNZXRhRGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQ0FBdUM7QUFDdkMseUNBQXFDO0FBQ3JDLDZEQUU2QjtBQUM3QixpREFBNkM7QUFLN0Msa0VBS3FDO0FBQ3JDLHlEQUFxRDtBQUNyRCxRQUFRO0FBQ1Isb0NBWWlCO0FBRWpCLE1BQWEsNEJBQTZCLFNBQVEscUJBQVM7SUFJMUQsWUFDQyxLQUEyRCxFQUMzRCxHQUF5RDtRQUV6RCxLQUFLLEVBQUUsQ0FBQTtRQUNQLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1FBQ2xCLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFBO0lBQ2YsQ0FBQztJQUVELFFBQVE7UUFDUCxNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxDQUFDLENBQUE7SUFDMUQsQ0FBQztJQUVELE1BQU07UUFDTCxPQUFPO1lBQ04sS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFO1lBQzFCLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUN0QixDQUFBO0lBQ0YsQ0FBQztJQUVELE1BQU0sQ0FBQyxJQUFJLENBQ1YsR0FBRyxJQUFvQztRQUV2QyxPQUFPLElBQUksNEJBQTRCLENBQ3RDLHVDQUFrQixDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUNuRCx1Q0FBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FDakQsQ0FBQTtJQUNGLENBQUM7SUFFRCxNQUFNLENBQUMsUUFB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