A lightweight performance observer using native Node.js performance APIs for debugging and benchmarking.
npm install @neabyte/perf-observerimport perf from '@neabyte/perf-observer'
// Track a function automatically
const trackedFunction = perf.track(() => {
// Your code here
return 'result'
})
// Manual timing
perf.start('my-process')
// ... do work ...
const duration = perf.end('my-process')
// Run benchmarks
const result = perf.benchmark(() => {
// Function to benchmark
}, { iterations: 1000 })| Method | Description | Returns |
|---|---|---|
start(name) |
Start timing a process | void |
end(name) |
End timing and get duration | number (ms) |
track(fn, name?) |
Wrap function with automatic timing | Function |
getStats(name?) |
Get performance statistics | ProcessStats |
findSlowProcesses(threshold?) |
Find processes exceeding threshold | ProcessEntry[] |
benchmark(fn, options?) |
Run benchmark test | BenchmarkResult |
| Property | Type | Description |
|---|---|---|
count |
number |
Number of processes |
avgDuration |
number |
Average duration (ms) |
minDuration |
number |
Minimum duration (ms) |
maxDuration |
number |
Maximum duration (ms) |
p95Duration |
number |
95th percentile (ms) |
p99Duration |
number |
99th percentile (ms) |
| Property | Type | Default | Description |
|---|---|---|---|
iterations |
number |
1000 |
Number of test iterations |
warmup |
number |
min(100, iterations/10) |
Warmup iterations |
maxDuration |
number |
60000 |
Max test duration (ms) |
outlierThreshold |
number |
3 |
Outlier detection threshold |
trackMemory |
boolean |
false |
Track memory usage |
name |
string |
fn.name |
Custom benchmark name |
| Property | Type | Description |
|---|---|---|
name |
string |
Benchmark name |
iterations |
number |
Actual iterations completed |
warmupIterations |
number |
Warmup iterations performed |
totalTime |
number |
Total time (ms) |
avgTime |
number |
Average time per iteration (ms) |
minTime |
number |
Minimum iteration time (ms) |
maxTime |
number |
Maximum iteration time (ms) |
p95Time |
number |
95th percentile time (ms) |
p99Time |
number |
99th percentile time (ms) |
stdDev |
number |
Standard deviation |
outliers |
number |
Number of outliers removed |
memoryDelta |
number? |
Memory usage change (bytes) |
// Manual timing
perf.start('database-query')
// Simulate database operation
await new Promise(resolve => setTimeout(resolve, 50))
const duration = perf.end('database-query')
console.log(`Query took ${duration}ms`)// Automatic timing
const expensiveOperation = perf.track(async () => {
await new Promise(resolve => setTimeout(resolve, 100))
return 'completed'
})
const result = await expensiveOperation()Duplicate Name Behavior: Multiple functions with the same name will overwrite each other's performance data. Only the last function's data will be preserved in statistics. To avoid data loss:
- Use unique names:
perf.track(fn, 'unique-name')- Add hash suffixes:
perf.track(fn, 'operation-' + crypto.randomBytes(4).toString('hex'))- Use function names:
function myOperation() {}thenperf.track(myOperation)Anonymous functions all use 'anonymous' name and will overwrite each other.
// Get stats for all processes
const allStats = perf.getStats()
console.log(`Average: ${allStats.avgDuration}ms`)
// Get stats for specific process
const queryStats = perf.getStats('database-query')
console.log(`95th percentile: ${queryStats.p95Duration}ms`)// Simple benchmark
const result = perf.benchmark(() => {
return Math.random() * 1000
}, 10000)
console.log(`Average: ${result.avgTime}ms`)
console.log(`Standard deviation: ${result.stdDev}ms`)
// Advanced benchmark with options
const advancedResult = perf.benchmark(
() => {
// Simulate data processing
return Array.from({ length: 1000 }, (_, i) => i * 2)
},
{
iterations: 5000,
warmup: 100,
trackMemory: true,
outlierThreshold: 2,
name: 'data-processing'
}
)// Find processes taking longer than 1 second
const slowProcesses = perf.findSlowProcesses(1000)
slowProcesses.forEach(process => {
console.log(`${process.name}: ${process.duration}ms`)
})- Node.js >= 22.0.0
- TypeScript (optional, for type definitions)
Issues and pull requests are welcome on GitHub.
This project is licensed under the MIT license. See the LICENSE file for more info.