0
# Performance Monitoring
1
2
Built-in performance metrics collection with detailed histogram statistics for runtime and wait times, including percentile calculations.
3
4
## Capabilities
5
6
### PiscinaHistogram Interface
7
8
Main interface for accessing performance metrics from the pool.
9
10
```typescript { .api }
11
/**
12
* Main histogram interface providing runtime and wait time statistics
13
*/
14
interface PiscinaHistogram {
15
/** Runtime statistics for task execution */
16
readonly runTime: PiscinaHistogramSummary;
17
18
/** Wait time statistics for task queuing */
19
readonly waitTime: PiscinaHistogramSummary;
20
21
/**
22
* Reset runtime histogram data
23
*/
24
resetRunTime(): void;
25
26
/**
27
* Reset wait time histogram data
28
*/
29
resetWaitTime(): void;
30
}
31
```
32
33
### PiscinaHistogramSummary Interface
34
35
Detailed statistical summary with percentile calculations.
36
37
```typescript { .api }
38
/**
39
* Comprehensive statistical summary of timing data
40
* All values are in milliseconds
41
*/
42
interface PiscinaHistogramSummary {
43
/** Average/mean execution time in milliseconds */
44
readonly average: number;
45
46
/** Mean execution time in milliseconds (same as average) */
47
readonly mean: number;
48
49
/** Standard deviation of execution times */
50
readonly stddev: number;
51
52
/** Minimum recorded execution time */
53
readonly min: number;
54
55
/** Maximum recorded execution time */
56
readonly max: number;
57
58
// Percentile values (all in milliseconds)
59
/** 0.1st percentile (1 in 1000 tasks faster) */
60
readonly p0_001: number;
61
62
/** 1st percentile (1 in 100 tasks faster) */
63
readonly p0_01: number;
64
65
/** 10th percentile (1 in 10 tasks faster) */
66
readonly p0_1: number;
67
68
/** 1st percentile */
69
readonly p1: number;
70
71
/** 2.5th percentile */
72
readonly p2_5: number;
73
74
/** 10th percentile */
75
readonly p10: number;
76
77
/** 25th percentile (first quartile) */
78
readonly p25: number;
79
80
/** 50th percentile (median) */
81
readonly p50: number;
82
83
/** 75th percentile (third quartile) */
84
readonly p75: number;
85
86
/** 90th percentile */
87
readonly p90: number;
88
89
/** 97.5th percentile */
90
readonly p97_5: number;
91
92
/** 99th percentile */
93
readonly p99: number;
94
95
/** 99.9th percentile */
96
readonly p99_9: number;
97
98
/** 99.99th percentile */
99
readonly p99_99: number;
100
101
/** 99.999th percentile */
102
readonly p99_999: number;
103
}
104
```
105
106
### Pool-Level Metrics
107
108
Access performance metrics through the main pool instance.
109
110
```typescript { .api }
111
class Piscina {
112
/** Performance histogram (when recordTiming is enabled) */
113
readonly histogram: PiscinaHistogram;
114
115
/** Pool utilization as percentage (0-1) */
116
readonly utilization: number;
117
118
/** Pool runtime duration in milliseconds */
119
readonly duration: number;
120
121
/** Total number of completed tasks */
122
readonly completed: number;
123
}
124
```
125
126
**Usage Examples:**
127
128
```typescript
129
import Piscina from "piscina";
130
131
// Create pool with timing enabled (default)
132
const pool = new Piscina({
133
filename: "worker.js",
134
recordTiming: true, // Default: true
135
workerHistogram: true // Enable per-worker histograms
136
});
137
138
// Run some tasks
139
await Promise.all([
140
pool.run({ task: "fast" }),
141
pool.run({ task: "medium" }),
142
pool.run({ task: "slow" })
143
]);
144
145
// Access performance metrics
146
const stats = pool.histogram;
147
148
console.log('Runtime Statistics:');
149
console.log(`Average: ${stats.runTime.average.toFixed(2)}ms`);
150
console.log(`Median (p50): ${stats.runTime.p50.toFixed(2)}ms`);
151
console.log(`97.5th percentile: ${stats.runTime.p97_5.toFixed(2)}ms`);
152
console.log(`99th percentile: ${stats.runTime.p99.toFixed(2)}ms`);
153
console.log(`Min: ${stats.runTime.min.toFixed(2)}ms`);
154
console.log(`Max: ${stats.runTime.max.toFixed(2)}ms`);
155
156
console.log('\nWait Time Statistics:');
157
console.log(`Average wait: ${stats.waitTime.average.toFixed(2)}ms`);
158
console.log(`Median wait: ${stats.waitTime.p50.toFixed(2)}ms`);
159
console.log(`99th percentile wait: ${stats.waitTime.p99.toFixed(2)}ms`);
160
161
console.log('\nPool Statistics:');
162
console.log(`Utilization: ${(pool.utilization * 100).toFixed(2)}%`);
163
console.log(`Completed tasks: ${pool.completed}`);
164
console.log(`Running for: ${pool.duration.toFixed(2)}ms`);
165
```
166
167
### Worker-Level Metrics
168
169
Individual worker performance tracking when `workerHistogram` is enabled.
170
171
```typescript { .api }
172
interface PiscinaWorker {
173
/** Worker-specific histogram (when workerHistogram is enabled) */
174
readonly histogram: PiscinaHistogramSummary | null;
175
}
176
```
177
178
**Usage Examples:**
179
180
```typescript
181
import Piscina from "piscina";
182
183
const pool = new Piscina({
184
filename: "worker.js",
185
workerHistogram: true, // Enable per-worker tracking
186
maxThreads: 4
187
});
188
189
// Run tasks and monitor per-worker performance
190
await Promise.all(
191
Array.from({ length: 100 }, (_, i) => pool.run({ taskId: i }))
192
);
193
194
// Monitor individual worker performance
195
pool.threads.forEach((thread, index) => {
196
const workerStats = thread.histogram;
197
if (workerStats) {
198
console.log(`\nWorker ${index} Performance:`);
199
console.log(`Average runtime: ${workerStats.average.toFixed(2)}ms`);
200
console.log(`Median runtime: ${workerStats.p50.toFixed(2)}ms`);
201
console.log(`97.5th percentile: ${workerStats.p97_5.toFixed(2)}ms`);
202
}
203
});
204
```
205
206
### Performance Monitoring Patterns
207
208
#### Real-time Monitoring
209
210
```typescript
211
import Piscina from "piscina";
212
213
const pool = new Piscina({
214
filename: "worker.js",
215
recordTiming: true,
216
workerHistogram: true
217
});
218
219
// Real-time performance dashboard
220
function displayPerformanceMetrics() {
221
const stats = pool.histogram;
222
223
console.clear();
224
console.log('=== Piscina Performance Dashboard ===\n');
225
226
// Pool overview
227
console.log(`Pool Utilization: ${(pool.utilization * 100).toFixed(1)}%`);
228
console.log(`Active Threads: ${pool.threads.length}`);
229
console.log(`Queue Size: ${pool.queueSize}`);
230
console.log(`Completed Tasks: ${pool.completed}`);
231
console.log(`Pool Runtime: ${(pool.duration / 1000).toFixed(1)}s\n`);
232
233
// Runtime statistics
234
console.log('Runtime Statistics:');
235
console.log(` Mean: ${stats.runTime.mean.toFixed(2)}ms`);
236
console.log(` Median: ${stats.runTime.p50.toFixed(2)}ms`);
237
console.log(` P97.5: ${stats.runTime.p97_5.toFixed(2)}ms`);
238
console.log(` P99: ${stats.runTime.p99.toFixed(2)}ms\n`);
239
240
// Wait time statistics
241
console.log('Wait Time Statistics:');
242
console.log(` Mean: ${stats.waitTime.mean.toFixed(2)}ms`);
243
console.log(` Median: ${stats.waitTime.p50.toFixed(2)}ms`);
244
console.log(` P97.5: ${stats.waitTime.p97_5.toFixed(2)}ms`);
245
console.log(` P99: ${stats.waitTime.p99.toFixed(2)}ms\n`);
246
247
// Worker breakdown
248
console.log('Worker Performance:');
249
pool.threads.forEach((thread, index) => {
250
const usage = thread.currentUsage;
251
const hist = thread.histogram;
252
const avgTime = hist ? hist.average.toFixed(1) : 'N/A';
253
console.log(` Worker ${index}: ${usage} tasks, ${avgTime}ms avg`);
254
});
255
}
256
257
// Update dashboard every 2 seconds
258
const dashboardInterval = setInterval(displayPerformanceMetrics, 2000);
259
260
// Stop monitoring
261
setTimeout(() => {
262
clearInterval(dashboardInterval);
263
pool.close();
264
}, 60000);
265
```
266
267
#### Performance Alerting
268
269
```typescript
270
import Piscina from "piscina";
271
272
const pool = new Piscina({
273
filename: "worker.js",
274
recordTiming: true
275
});
276
277
// Performance thresholds
278
const THRESHOLDS = {
279
avgRuntimeMs: 1000, // Alert if average > 1s
280
p99RuntimeMs: 5000, // Alert if P99 > 5s
281
avgWaitTimeMs: 100, // Alert if wait > 100ms
282
utilizationPercent: 90 // Alert if utilization > 90%
283
};
284
285
function checkPerformanceAlerts() {
286
const stats = pool.histogram;
287
const utilization = pool.utilization * 100;
288
289
// Runtime alerts
290
if (stats.runTime.average > THRESHOLDS.avgRuntimeMs) {
291
console.warn(`⚠️ High average runtime: ${stats.runTime.average.toFixed(2)}ms`);
292
}
293
294
if (stats.runTime.p99 > THRESHOLDS.p99RuntimeMs) {
295
console.warn(`⚠️ High P99 runtime: ${stats.runTime.p99.toFixed(2)}ms`);
296
}
297
298
// Wait time alerts
299
if (stats.waitTime.average > THRESHOLDS.avgWaitTimeMs) {
300
console.warn(`⚠️ High average wait time: ${stats.waitTime.average.toFixed(2)}ms`);
301
}
302
303
// Utilization alerts
304
if (utilization > THRESHOLDS.utilizationPercent) {
305
console.warn(`⚠️ High utilization: ${utilization.toFixed(1)}%`);
306
}
307
308
// Queue backup alert
309
if (pool.queueSize > 10) {
310
console.warn(`⚠️ Queue backup: ${pool.queueSize} tasks waiting`);
311
}
312
}
313
314
// Check for alerts every 10 seconds
315
const alertInterval = setInterval(checkPerformanceAlerts, 10000);
316
```
317
318
#### Performance Logging
319
320
```typescript
321
import Piscina from "piscina";
322
import { writeFileSync, appendFileSync } from "fs";
323
324
const pool = new Piscina({
325
filename: "worker.js",
326
recordTiming: true,
327
workerHistogram: true
328
});
329
330
// Log performance metrics to file
331
function logPerformanceMetrics() {
332
const timestamp = new Date().toISOString();
333
const stats = pool.histogram;
334
335
const logEntry = {
336
timestamp,
337
utilization: pool.utilization,
338
completed: pool.completed,
339
queueSize: pool.queueSize,
340
activeThreads: pool.threads.length,
341
runtime: {
342
mean: stats.runTime.mean,
343
median: stats.runTime.p50,
344
p97_5: stats.runTime.p97_5,
345
p99: stats.runTime.p99
346
},
347
waitTime: {
348
mean: stats.waitTime.mean,
349
median: stats.waitTime.p50,
350
p97_5: stats.waitTime.p97_5,
351
p99: stats.waitTime.p99
352
}
353
};
354
355
appendFileSync('piscina-performance.log', JSON.stringify(logEntry) + '\n');
356
}
357
358
// Log metrics every minute
359
const logInterval = setInterval(logPerformanceMetrics, 60000);
360
361
// Reset metrics periodically to avoid memory growth
362
setInterval(() => {
363
console.log('Resetting performance metrics...');
364
pool.histogram.resetRunTime();
365
pool.histogram.resetWaitTime();
366
}, 3600000); // Reset every hour
367
```
368
369
### Histogram Reset Operations
370
371
Reset performance data for fresh measurements.
372
373
```typescript { .api }
374
interface PiscinaHistogram {
375
/**
376
* Reset all runtime measurement data
377
* Useful for periodic cleanup or benchmarking specific periods
378
*/
379
resetRunTime(): void;
380
381
/**
382
* Reset all wait time measurement data
383
* Useful for periodic cleanup or benchmarking specific periods
384
*/
385
resetWaitTime(): void;
386
}
387
```
388
389
**Usage Examples:**
390
391
```typescript
392
const pool = new Piscina({ filename: "worker.js" });
393
394
// Run baseline measurements
395
await runBaselineTasks();
396
397
// Reset for clean benchmark
398
pool.histogram.resetRunTime();
399
pool.histogram.resetWaitTime();
400
401
// Run benchmark
402
await runBenchmarkTasks();
403
404
// Get clean benchmark results
405
const benchmarkStats = pool.histogram;
406
console.log(`Benchmark average: ${benchmarkStats.runTime.average}ms`);
407
```
408
409
### Configuration Options
410
411
Control performance monitoring behavior through pool options.
412
413
```typescript { .api }
414
interface Options {
415
/** Enable/disable timing collection (default: true) */
416
recordTiming?: boolean;
417
418
/** Enable per-worker histograms (default: false) */
419
workerHistogram?: boolean;
420
}
421
```
422
423
**Usage Examples:**
424
425
```typescript
426
// Disable performance monitoring for maximum performance
427
const highPerformancePool = new Piscina({
428
filename: "worker.js",
429
recordTiming: false, // Disable metrics collection
430
workerHistogram: false
431
});
432
433
// Full monitoring for development/debugging
434
const debugPool = new Piscina({
435
filename: "worker.js",
436
recordTiming: true,
437
workerHistogram: true
438
});
439
440
// Production monitoring (pool-level only)
441
const productionPool = new Piscina({
442
filename: "worker.js",
443
recordTiming: true,
444
workerHistogram: false // Reduce overhead
445
});
446
```