UNPKG

cmpstr

Version:

CmpStr is a lightweight, fast and well performing package for calculating string similarity

228 lines (226 loc) 7.53 kB
// CmpStr v3.0.1 dev-052fa0c-250614 by Paul Köhler @komed3 / MIT License /** * 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) }; } export { Profiler }; //# sourceMappingURL=Profiler.js.map