Files
bun.sh/src/js/node/perf_hooks.ts
2024-06-28 18:17:32 -07:00

176 lines
5.2 KiB
TypeScript

// Hardcoded module "node:perf_hooks"
const { throwNotImplemented } = require("internal/shared");
var {
Performance,
PerformanceEntry,
PerformanceMark,
PerformanceMeasure,
PerformanceObserver,
PerformanceObserverEntryList,
} = globalThis;
var constants = {
NODE_PERFORMANCE_GC_MAJOR: 4,
NODE_PERFORMANCE_GC_MINOR: 1,
NODE_PERFORMANCE_GC_INCREMENTAL: 8,
NODE_PERFORMANCE_GC_WEAKCB: 16,
NODE_PERFORMANCE_GC_FLAGS_NO: 0,
NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: 2,
NODE_PERFORMANCE_GC_FLAGS_FORCED: 4,
NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: 8,
NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: 16,
NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: 32,
NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: 64,
};
// PerformanceEntry is not a valid constructor, so we have to fake it.
class PerformanceNodeTiming {
bootstrapComplete: number = 0;
environment: number = 0;
idleTime: number = 0;
loopExit: number = 0;
loopStart: number = 0;
nodeStart: number = 0;
v8Start: number = 0;
// we have to fake the properties since it's not real
get name() {
return "node";
}
get entryType() {
return "node";
}
get startTime() {
return this.nodeStart;
}
get duration() {
return performance.now();
}
toJSON() {
return {
name: this.name,
entryType: this.entryType,
startTime: this.startTime,
duration: this.duration,
bootstrapComplete: this.bootstrapComplete,
environment: this.environment,
idleTime: this.idleTime,
loopExit: this.loopExit,
loopStart: this.loopStart,
nodeStart: this.nodeStart,
v8Start: this.v8Start,
};
}
}
Object.setPrototypeOf(PerformanceNodeTiming.prototype, PerformanceEntry.prototype);
Object.setPrototypeOf(PerformanceNodeTiming, PerformanceEntry);
function createPerformanceNodeTiming() {
const object = Object.create(PerformanceNodeTiming.prototype);
object.bootstrapComplete = object.environment = object.nodeStart = object.v8Start = performance.timeOrigin;
object.loopStart = object.idleTime = 1;
object.loopExit = -1;
return object;
}
function eventLoopUtilization(utilization1, utilization2) {
return {
idle: 0,
active: 0,
utilization: 0,
};
}
// PerformanceEntry is not a valid constructor, so we have to fake it.
class PerformanceResourceTiming {
constructor() {
throwNotImplemented("PerformanceResourceTiming");
}
}
Object.setPrototypeOf(PerformanceResourceTiming.prototype, PerformanceEntry.prototype);
Object.setPrototypeOf(PerformanceResourceTiming, PerformanceEntry);
export default {
performance: {
// perf_hooks is a builtin global, so JSC is aware of it through C++ bindings
// see JSPerformance.cpp HashTableValue for more details
// perf_hooks has a performance module with these exported functions,
// most implemented in C++ but I decide to do timerify in JS
mark(f) {
return performance.mark(...arguments);
},
measure(f) {
return performance.measure(...arguments);
},
timerify(f) {
// in this case, we want it to go back to JS function since we're passing a JS function
// go to JSPerformance.cpp HashTableValue to see how this is handled differently from the rest
return performance.timerify(...arguments); // this routes to JSPerformance.cpp
},
clearMarks(f) {
return performance.clearMarks(...arguments);
},
clearMeasures(f) {
return performance.clearMeasures(...arguments);
},
getEntries(f) {
return performance.getEntries(...arguments);
},
getEntriesByName(f) {
return performance.getEntriesByName(...arguments);
},
getEntriesByType(f) {
return performance.getEntriesByType(...arguments);
},
setResourceTimingBufferSize(f) {
return performance.setResourceTimingBufferSize(...arguments);
},
timeOrigin: performance.timeOrigin,
toJSON(f) {
return performance.toJSON(...arguments);
},
onresourcetimingbufferfull: performance.onresourcetimingbufferfull,
nodeTiming: createPerformanceNodeTiming(),
now: () => performance.now(),
eventLoopUtilization: eventLoopUtilization,
clearResourceTimings: function () {},
},
// performance: {
// clearMarks: [Function: clearMarks],
// clearMeasures: [Function: clearMeasures],
// clearResourceTimings: [Function: clearResourceTimings],
// getEntries: [Function: getEntries],
// getEntriesByName: [Function: getEntriesByName],
// getEntriesByType: [Function: getEntriesByType],
// mark: [Function: mark],
// measure: [Function: measure],
// now: performance.now,
// setResourceTimingBufferSize: [Function: setResourceTimingBufferSize],
// timeOrigin: performance.timeOrigin,
// toJSON: [Function: toJSON],
// onresourcetimingbufferfull: [Getter/Setter]
// },
constants,
Performance,
PerformanceEntry,
PerformanceMark,
PerformanceMeasure,
PerformanceObserver,
PerformanceObserverEntryList,
PerformanceNodeTiming,
monitorEventLoopDelay() {
throwNotImplemented("perf_hooks.monitorEventLoopDelay");
},
createHistogram() {
const { createHistogram } = $zig("node_perf_hooks_histogram_binding.zig", "createPerfHooksHistogramBinding");
return createHistogram();
},
PerformanceResourceTiming,
};