-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmark.test.ts
More file actions
139 lines (115 loc) Β· 3.78 KB
/
Copy pathbenchmark.test.ts
File metadata and controls
139 lines (115 loc) Β· 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import {PatternEmitter} from '../src';
describe('Performance Benchmarks', () => {
it('cache significantly improves repeated emit() performance', () => {
const emitter = new PatternEmitter();
const iterations = 1000;
let callCount = 0;
// Setup: Register listeners that will match
emitter.on('test:event', () => {
callCount++;
});
emitter.on(/^test:/, () => {
callCount++;
});
emitter.on(/event$/, () => {
callCount++;
});
// Warm up - first emit will populate cache
emitter.emit('test:event');
callCount = 0;
// Benchmark: Measure cached emit performance
const startCached = process.hrtime.bigint();
for (let i = 0; i < iterations; i++) {
emitter.emit('test:event');
}
const endCached = process.hrtime.bigint();
const cachedTime = Number(endCached - startCached) / 1_000_000; // Convert to ms
// Verify all listeners were called
expect(callCount).toBe(iterations * 3); // 3 listeners per emit
// Performance assertion - cached emits should be fast
const avgTimePerEmit = cachedTime / iterations;
expect(avgTimePerEmit).toBeLessThan(0.1); // Should be under 0.1ms per emit
});
it('cache invalidation works correctly', () => {
const emitter = new PatternEmitter();
const results: string[] = [];
emitter.on('test', () => {
results.push('listener1');
});
emitter.on(/^test$/, () => {
results.push('pattern1');
});
// First emit - populates cache
emitter.emit('test');
expect(results).toEqual(['listener1', 'pattern1']);
results.length = 0;
// Add new listener - should invalidate cache
emitter.on('test', () => {
results.push('listener2');
});
// Second emit - should include new listener
emitter.emit('test');
expect(results).toEqual(['listener1', 'pattern1', 'listener2']);
results.length = 0;
// Remove listener - should invalidate cache
const toRemove = () => {
results.push('listener1');
};
emitter.removeListener('test', toRemove);
// Third emit - should not include removed listener
emitter.emit('test');
expect(results).toContain('pattern1');
expect(results).toContain('listener2');
});
it('cache handles different event types independently', () => {
const emitter = new PatternEmitter();
const event1Calls: number[] = [];
const event2Calls: number[] = [];
emitter.on('event1', () => {
event1Calls.push(1);
});
emitter.on('event2', () => {
event2Calls.push(2);
});
emitter.on(/^event/, () => {
event1Calls.push(10);
event2Calls.push(20);
});
// Emit different events - each should have its own cache entry
emitter.emit('event1');
expect(event1Calls).toEqual([1, 10]);
expect(event2Calls).toEqual([20]);
event1Calls.length = 0;
event2Calls.length = 0;
emitter.emit('event2');
expect(event1Calls).toEqual([10]);
expect(event2Calls).toEqual([2, 20]);
});
it('cache works with complex regex patterns', () => {
const emitter = new PatternEmitter();
const iterations = 500;
let matchCount = 0;
// Complex patterns
emitter.on(/^user:.*:login$/, () => {
matchCount++;
});
emitter.on(/^user:\d+:/, () => {
matchCount++;
});
emitter.on(/^user:[a-z]+:login$/, () => {
matchCount++;
});
// First emit - cache miss
emitter.emit('user:admin:login');
const firstCount = matchCount;
matchCount = 0;
// Subsequent emits - cache hits
const start = process.hrtime.bigint();
for (let i = 0; i < iterations; i++) {
emitter.emit('user:admin:login');
}
const end = process.hrtime.bigint();
const totalTime = Number(end - start) / 1_000_000;
expect(matchCount).toBe(firstCount * iterations);
});
});