0
# Statistics and Profiling
1
2
Methods for collecting, analyzing, and managing memoization performance statistics to monitor cache effectiveness and optimize function performance.
3
4
## Capabilities
5
6
### Statistics Collection Control
7
8
Enable or disable global statistics collection for all memoized functions.
9
10
```typescript { .api }
11
/**
12
* Enable or disable statistics collection globally
13
* @param isCollectingStats Whether to collect statistics (default: true)
14
*/
15
collectStats(isCollectingStats?: boolean): void;
16
17
/**
18
* Check if statistics are currently being collected
19
* @returns Whether statistics collection is enabled
20
*/
21
isCollectingStats(): boolean;
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import moize from "moize";
28
29
// Enable statistics collection
30
moize.collectStats(true);
31
console.log(moize.isCollectingStats()); // true
32
33
// Create memoized functions (stats will be collected)
34
const add = (a: number, b: number) => a + b;
35
const memoizedAdd = moize(add);
36
37
// Disable statistics collection
38
moize.collectStats(false);
39
console.log(moize.isCollectingStats()); // false
40
41
// Re-enable with explicit call
42
moize.collectStats();
43
console.log(moize.isCollectingStats()); // true
44
```
45
46
### Statistics Retrieval
47
48
Get performance statistics for specific profiles or global statistics.
49
50
```typescript { .api }
51
/**
52
* Get statistics for a specific profile or global statistics
53
* @param profileName Optional profile name to get specific stats
54
* @returns Statistics object with calls, hits, and usage percentage
55
*/
56
getStats(profileName?: string): StatsObject;
57
58
type StatsObject = {
59
calls: number; // Total number of function calls
60
hits: number; // Number of cache hits
61
usage: string; // Hit rate as percentage string
62
};
63
64
type GlobalStatsObject = StatsObject & {
65
profiles?: Record<string, StatsProfile>; // Individual profile statistics
66
};
67
68
type StatsProfile = {
69
calls: number;
70
hits: number;
71
};
72
```
73
74
**Usage Examples:**
75
76
```typescript
77
import moize from "moize";
78
79
moize.collectStats(true);
80
81
// Create profiled memoized functions
82
const fibonacci = (n: number): number => {
83
if (n < 2) return n;
84
return fibonacci(n - 1) + fibonacci(n - 2);
85
};
86
87
const memoizedFib = moize.profile('fibonacci')(fibonacci);
88
89
const factorial = (n: number): number => {
90
if (n <= 1) return 1;
91
return n * factorial(n - 1);
92
};
93
94
const memoizedFactorial = moize.profile('factorial').maxSize(20)(factorial);
95
96
// Use the functions to generate stats
97
memoizedFib(10);
98
memoizedFib(10); // Cache hit
99
memoizedFib(15);
100
memoizedFactorial(5);
101
memoizedFactorial(5); // Cache hit
102
103
// Get global statistics
104
const globalStats = moize.getStats();
105
console.log(globalStats);
106
// {
107
// calls: 6,
108
// hits: 2,
109
// usage: "33.33%",
110
// profiles: {
111
// fibonacci: { calls: 3, hits: 1 },
112
// factorial: { calls: 2, hits: 1 }
113
// }
114
// }
115
116
// Get specific profile statistics
117
const fibStats = moize.getStats('fibonacci');
118
console.log(fibStats);
119
// { calls: 3, hits: 1, usage: "33.33%" }
120
121
const factorialStats = moize.getStats('factorial');
122
console.log(factorialStats);
123
// { calls: 2, hits: 1, usage: "50.00%" }
124
```
125
126
### Statistics Clearing
127
128
Clear statistics for specific profiles or all statistics.
129
130
```typescript { .api }
131
/**
132
* Clear statistics for a specific profile or all statistics
133
* @param profileName Optional profile name to clear specific stats
134
*/
135
clearStats(profileName?: string): void;
136
```
137
138
**Usage Examples:**
139
140
```typescript
141
import moize from "moize";
142
143
moize.collectStats(true);
144
145
const processData = (data: any[]) => data.map(x => x * 2);
146
const memoizedProcess = moize.profile('data-processing')(processData);
147
148
// Generate some statistics
149
memoizedProcess([1, 2, 3]);
150
memoizedProcess([1, 2, 3]); // Hit
151
memoizedProcess([4, 5, 6]);
152
153
console.log(moize.getStats('data-processing'));
154
// { calls: 3, hits: 1, usage: "33.33%" }
155
156
// Clear specific profile stats
157
moize.clearStats('data-processing');
158
console.log(moize.getStats('data-processing'));
159
// { calls: 0, hits: 0, usage: "0.00%" }
160
161
// Clear all statistics
162
moize.clearStats();
163
console.log(moize.getStats());
164
// { calls: 0, hits: 0, usage: "0.00%", profiles: {} }
165
```
166
167
### Profile Assignment
168
169
Assign profile names to memoized functions for organized statistics tracking.
170
171
```typescript { .api }
172
/**
173
* Create a moizer with a specific profile name for statistics tracking
174
* @param profileName Name to identify this group of memoized functions
175
* @returns Moizer with profile name configuration
176
*/
177
profile<ProfileName extends string>(
178
profileName: ProfileName
179
): Moizer<{ profileName: ProfileName }>;
180
```
181
182
**Usage Examples:**
183
184
```typescript
185
import moize from "moize";
186
187
moize.collectStats(true);
188
189
// API-related functions
190
const fetchUser = async (id: string) => {
191
const response = await fetch(`/api/users/${id}`);
192
return response.json();
193
};
194
195
const fetchPosts = async (userId: string) => {
196
const response = await fetch(`/api/posts?userId=${userId}`);
197
return response.json();
198
};
199
200
// Group under 'api-calls' profile
201
const memoizedFetchUser = moize.promise.profile('api-calls')(fetchUser);
202
const memoizedFetchPosts = moize.promise.profile('api-calls')(fetchPosts);
203
204
// Math operations
205
const isPrime = (n: number): boolean => {
206
if (n < 2) return false;
207
for (let i = 2; i <= Math.sqrt(n); i++) {
208
if (n % i === 0) return false;
209
}
210
return true;
211
};
212
213
const fibonacci = (n: number): number => {
214
if (n < 2) return n;
215
return fibonacci(n - 1) + fibonacci(n - 2);
216
};
217
218
// Group under 'math' profile
219
const memoizedIsPrime = moize.profile('math')(isPrime);
220
const memoizedFibonacci = moize.profile('math')(fibonacci);
221
222
// Use functions to generate statistics
223
await memoizedFetchUser('123');
224
await memoizedFetchPosts('123');
225
memoizedIsPrime(17);
226
memoizedFibonacci(10);
227
228
// Check profile-specific statistics
229
console.log(moize.getStats('api-calls'));
230
console.log(moize.getStats('math'));
231
console.log(moize.getStats()); // Global stats with all profiles
232
```
233
234
### Instance-Level Statistics
235
236
Individual memoized functions also provide their own statistics methods.
237
238
```typescript { .api }
239
interface Moized {
240
/**
241
* Clear statistics for this specific memoized function
242
*/
243
clearStats(): void;
244
245
/**
246
* Get statistics for this specific memoized function
247
* @returns Profile statistics for this function
248
*/
249
getStats(): StatsProfile;
250
251
/**
252
* Check if this function is collecting statistics
253
* @returns Whether this function collects statistics
254
*/
255
isCollectingStats(): boolean;
256
}
257
```
258
259
**Usage Examples:**
260
261
```typescript
262
import moize from "moize";
263
264
moize.collectStats(true);
265
266
const expensiveCalculation = (n: number) => {
267
// Simulate expensive computation
268
let result = 0;
269
for (let i = 0; i < n * 1000; i++) {
270
result += Math.sqrt(i);
271
}
272
return result;
273
};
274
275
const memoized = moize.maxSize(10).profile('expensive-calc')(expensiveCalculation);
276
277
// Use the function multiple times
278
memoized(100); // Computed
279
memoized(100); // Hit
280
memoized(200); // Computed
281
memoized(100); // Hit
282
283
// Get instance-specific statistics
284
console.log(memoized.getStats());
285
// { calls: 4, hits: 2 }
286
287
console.log(memoized.isCollectingStats()); // true
288
289
// Clear instance statistics
290
memoized.clearStats();
291
console.log(memoized.getStats());
292
// { calls: 0, hits: 0 }
293
294
// This also affects the global profile stats
295
console.log(moize.getStats('expensive-calc'));
296
// { calls: 0, hits: 0, usage: "0.00%" }
297
```
298
299
### Monitoring Cache Effectiveness
300
301
Use statistics to monitor and optimize cache performance.
302
303
```typescript
304
import moize from "moize";
305
306
// Helper function to analyze cache effectiveness
307
function analyzeCachePerformance(profileName: string) {
308
const stats = moize.getStats(profileName);
309
310
if (stats.calls === 0) {
311
console.log(`${profileName}: No function calls recorded`);
312
return;
313
}
314
315
const hitRate = (stats.hits / stats.calls) * 100;
316
317
console.log(`${profileName} Performance:`);
318
console.log(` Total calls: ${stats.calls}`);
319
console.log(` Cache hits: ${stats.hits}`);
320
console.log(` Hit rate: ${hitRate.toFixed(2)}%`);
321
322
if (hitRate < 20) {
323
console.log(` โ ๏ธ Low hit rate - consider adjusting cache size or TTL`);
324
} else if (hitRate > 80) {
325
console.log(` โ Excellent hit rate - cache is very effective`);
326
} else {
327
console.log(` ๐ Moderate hit rate - cache is working but could be optimized`);
328
}
329
}
330
331
moize.collectStats(true);
332
333
// Set up monitored functions
334
const apiCall = moize.promise.profile('api').maxAge(30000)(async (endpoint: string) => {
335
const response = await fetch(endpoint);
336
return response.json();
337
});
338
339
const computation = moize.profile('computation').maxSize(50)(
340
(data: number[]) => data.reduce((sum, val) => sum + Math.pow(val, 2), 0)
341
);
342
343
// After using the functions, analyze performance
344
setTimeout(() => {
345
analyzeCachePerformance('api');
346
analyzeCachePerformance('computation');
347
}, 10000);
348
```