cmpstr
Version:
CmpStr is a lightweight, fast and well performing package for calculating string similarity
230 lines (227 loc) • 7.56 kB
JavaScript
// CmpStr v3.0.1 dev-052fa0c-250614 by Paul Köhler @komed3 / MIT License
'use strict';
/**
* Profiler Utility
* src/utils/profiler.ts
*
* @see https://en.wikipedia.org/wiki/Profiling_(computer_programming)
*
* This class provides methods to run synchronous and asynchronous functions, capturing
* their execution time and memory usage, and storing the results in a set of profiler
* entries. It supports both Node.js and browser environments, detecting the environment
* automatically.
*
* The class is optimized for minimal overhead and can be used for fine-grained
* performance profiling.
*
* @module Utils/Profiler
* @author Paul Köhler (komed3)
* @license MIT
*/
/**
* Profiler class for measuring execution time and memory usage of functions.
*/
class Profiler {
// Environment detection
static ENV;
// Singleton instance
static instance;
// Store for profiler entries
store = new Set();
// Total time and memory consumption
totalTime = 0;
totalMem = 0;
// The Profiler active state
active;
/**
* Sets the environment based on the available global objects.
* Detects if running in Node.js or browser and sets the ENV property accordingly.
*/
static detectEnv() {
// Check for Node.js environment
if (typeof process !== 'undefined') Profiler.ENV = 'nodejs';
// Check for browser environment
else if (typeof performance !== 'undefined') Profiler.ENV = 'browser';
// If neither, set ENV to unknown
else Profiler.ENV = 'unknown';
}
/**
* Returns the singleton instance of the Perf class.
* If the instance does not exist, it creates a new one.
*
* @param {boolean} [enable=false] - Optional parameter to enable the profiler upon instantiation
* @returns {Profiler} - Singleton Profiler instance
*/
static getInstance(enable) {
// Ensure the environment is detected
if (!Profiler.ENV) Profiler.detectEnv();
// If instance does not exist, create a new one
if (!Profiler.instance) Profiler.instance = new Profiler(enable);
// Return singleton instance
return Profiler.instance;
}
/**
* Private constructor to enforce singleton pattern.
* Initializes the store for profiler entries.
*
* @param {boolean} [enable=false] - Optional parameter to enable the profiler
*/
constructor(enable) {
this.active = enable ?? false;
}
/**
* Gets the current time based on the environment.
*
* Uses process.hrtime.bigint() for Node.js, performance.now() for browsers,
* and Date.now() as a fallback.
*
* @returns {number} - Current time in milliseconds
*/
now() {
switch (Profiler.ENV) {
// Node.js environment
case 'nodejs':
return Number(process.hrtime.bigint()) / 1e6;
// Browser environment
case 'browser':
return performance.now();
// Fallback
default:
return Date.now();
}
}
/**
* Gets the current memory usage based on the environment.
*
* Uses process.memoryUsage().heapUsed for Node.js, performance.memory.usedJSHeapSize
* for browsers, and returns 0 as a fallback.
*
* @returns {number} - Current memory usage in bytes
*/
mem() {
switch (Profiler.ENV) {
// Node.js environment
case 'nodejs':
return process.memoryUsage().heapUsed;
// Browser environment
case 'browser':
return performance.memory?.usedJSHeapSize ?? 0;
// Fallback
default:
return 0;
}
}
/**
* Enables the profiler.
* Sets the active state to true, allowing profiling to occur.
*/
enable() {
this.active = true;
}
/**
* Disables the profiler.
* Sets the active state to false, preventing further profiling.
*/
disable() {
this.active = false;
}
/**
* Resets the profiler by clearing the store, total time and memory consumption.
* This method is useful for starting a new profiling session.
*/
clear() {
this.store.clear();
this.totalTime = 0;
this.totalMem = 0;
}
/**
* Runs a synchronous function and profiles its execution time and memory usage.
* If the profiler is not active, it simply executes the function without profiling.
*
* @param {() => T} fn - Function to be executed and profiled
* @param {Record<string, any>} meta - Metadata to be associated with the profiling entry
* @returns {T} - The result of the executed function
*/
run(fn, meta = {}) {
// If the profiler is not active, simply execute the function without profiling
if (!this.active) return fn();
// Capture the start time and memory usage
const startTime = this.now(),
startMem = this.mem();
// Execute the function and capture the result
const res = fn();
// Calculate the time and memory consumption
const deltaTime = this.now() - startTime;
const deltaMem = this.mem() - startMem;
// Add the profiling entry to the store
this.store.add({ time: deltaTime, mem: deltaMem, res, meta });
(this.totalTime += deltaTime), (this.totalMem += deltaMem);
// Return the result of the function
return res;
}
/**
* Runs an asynchronous function and profiles its execution time and memory usage.
* If the profiler is not active, it simply executes the function without profiling.
*
* @param {() => Promise<T>} fn - Asynchronous function to be executed and profiled
* @param {Record<string, any>} meta - Metadata to be associated with the profiling entry
* @returns {Promise<T>} - A promise that resolves to the result of the executed function
*/
async runAsync(fn, meta = {}) {
// If the profiler is not active, simply execute the function without profiling
if (!this.active) return await fn();
// Capture the start time and memory usage
const startTime = this.now(),
startMem = this.mem();
// Execute the asynchronous function and wait for its result
const res = await fn();
// Calculate the time and memory consumption
const deltaTime = this.now() - startTime;
const deltaMem = this.mem() - startMem;
// Add the profiling entry to the store
this.store.add({ time: deltaTime, mem: deltaMem, res, meta });
(this.totalTime += deltaTime), (this.totalMem += deltaMem);
// Return the result of the function
return res;
}
/**
* Retrieves all profiler entries stored in the profiler.
*
* @returns {ProfilerEntry<any>[]} - An array of profiler entries
*/
getAll() {
return [...this.store];
}
/**
* Retrieves the last profiler entry stored in the profiler.
*
* @returns {ProfilerEntry<any> | undefined} - The last profiler entry or undefined if no entries exist
*/
getLast() {
return this.getAll().pop();
}
/**
* Retrieves the total time and memory consumption recorded by the profiler.
*
* @returns {{ time: number, mem: number }} - An object containing total time and memory usage
*/
getTotal() {
return { time: this.totalTime, mem: this.totalMem };
}
/**
* Returns the services provided by the Profiler class.
* This allows for easy access to the profiler's methods.
*
* @returns {ProfilerService<any>} - An object containing methods to control the profiler
*/
services = {
enable: this.enable.bind(this),
disable: this.disable.bind(this),
clear: this.clear.bind(this),
report: this.getAll.bind(this),
last: this.getLast.bind(this),
total: this.getTotal.bind(this)
};
}
exports.Profiler = Profiler;
//# sourceMappingURL=Profiler.cjs.map