or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-functions.mdcache-management.mdfunction-memoization.mdindex.mdmethod-memoization.mdprofiling.mdweakmap-memoization.md

profiling.mddocs/

0

# Performance Profiling

1

2

Built-in profiling and statistics system that provides detailed insights into cache performance, hit rates, and function call patterns. Essential for optimizing memoization strategies and identifying performance bottlenecks in applications using memoized functions.

3

4

## Capabilities

5

6

### Profile Module Initialization

7

8

Enable profiling for all memoized functions by importing the profile module before any memoization setup.

9

10

```javascript { .api }

11

/**

12

* Import profile module to enable statistics collection

13

* Must be imported BEFORE creating any memoized functions to track

14

*/

15

const memProfile = require("memoizee/profile");

16

```

17

18

**Usage Examples:**

19

20

```javascript

21

// Import profile module first (before any memoization)

22

const memProfile = require("memoizee/profile");

23

const memoize = require("memoizee");

24

25

// Now create memoized functions - they will be automatically tracked

26

function expensiveCalculation(x, y) {

27

return Math.pow(x, y) + Math.random();

28

}

29

30

const memoized1 = memoize(expensiveCalculation);

31

const memoized2 = memoize(expensiveCalculation, { profileName: "Power Calculation" });

32

33

// Use the functions

34

memoized1(2, 10); // Initial execution

35

memoized1(2, 10); // Cache hit

36

memoized1(3, 5); // Initial execution

37

38

memoized2(2, 8); // Initial execution

39

memoized2(2, 8); // Cache hit

40

41

// Access statistics

42

console.log(memProfile.statistics);

43

console.log(memProfile.log());

44

```

45

46

### Statistics Data Structure

47

48

Access raw performance statistics programmatically for custom analysis.

49

50

```javascript { .api }

51

/**

52

* Raw statistics object containing performance data

53

* @type {Object<string, {initial: number, cached: number}>}

54

*/

55

memProfile.statistics = {

56

// Key format: "profileName, sourceLocation" or just "sourceLocation"

57

"profile-name, at /path/to/file.js:line:column": {

58

initial: number, // Number of initial function executions

59

cached: number // Number of cache hits

60

}

61

};

62

```

63

64

**Usage Examples:**

65

66

```javascript

67

const memProfile = require("memoizee/profile");

68

const memoize = require("memoizee");

69

70

const memoizedFn = memoize(someFunction, { profileName: "MyFunction" });

71

72

// Generate some activity

73

memoizedFn("arg1"); // initial: 1, cached: 0

74

memoizedFn("arg1"); // initial: 1, cached: 1

75

memoizedFn("arg2"); // initial: 2, cached: 1

76

memoizedFn("arg1"); // initial: 2, cached: 2

77

78

// Access raw statistics

79

const stats = memProfile.statistics;

80

Object.keys(stats).forEach(key => {

81

const { initial, cached } = stats[key];

82

const total = initial + cached;

83

const hitRate = total > 0 ? (cached / total * 100).toFixed(2) : 0;

84

console.log(`${key}: ${hitRate}% hit rate (${cached}/${total})`);

85

});

86

```

87

88

### Formatted Statistics Report

89

90

Generate human-readable statistics reports for performance analysis and debugging.

91

92

```javascript { .api }

93

/**

94

* Generate formatted statistics report

95

* @returns {string} Formatted table with performance statistics

96

*/

97

memProfile.log();

98

```

99

100

**Usage Examples:**

101

102

```javascript

103

const memProfile = require("memoizee/profile");

104

const memoize = require("memoizee");

105

106

// Create multiple memoized functions with different profiles

107

const fibonacci = memoize(function fib(n) {

108

if (n < 2) return n;

109

return fib(n - 1) + fib(n - 2);

110

}, { profileName: "Fibonacci" });

111

112

const factorial = memoize(function fact(n) {

113

if (n <= 1) return 1;

114

return n * fact(n - 1);

115

}, { profileName: "Factorial" });

116

117

const dataProcessor = memoize(function processData(data) {

118

return data.map(x => x * 2).filter(x => x > 10);

119

});

120

121

// Generate some activity

122

fibonacci(10); // Creates many cache entries due to recursion

123

factorial(5); // Creates some cache entries

124

dataProcessor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

125

126

// Print formatted report

127

console.log(memProfile.log());

128

129

/* Example output:

130

------------------------------------------------------------

131

Memoize statistics:

132

133

Init Cache %Cache Source location

134

67 78 53.79 (all)

135

11 55 83.33 Fibonacci, at /path/to/script.js:15:32

136

5 4 44.44 Factorial, at /path/to/script.js:20:29

137

1 0 0.00 at /path/to/script.js:25:45

138

------------------------------------------------------------

139

*/

140

```

141

142

### Profile Names and Source Location

143

144

Control how functions are identified in profiling reports using profile names and automatic source location detection.

145

146

```javascript { .api }

147

/**

148

* Configure profile identification

149

* @param {string} profileName - Custom name for the memoized function

150

*/

151

const options = {

152

profileName: string

153

};

154

```

155

156

**Usage Examples:**

157

158

```javascript

159

const memProfile = require("memoizee/profile");

160

const memoize = require("memoizee");

161

162

// Functions with custom profile names

163

const userLookup = memoize(function(userId) {

164

return database.getUser(userId);

165

}, { profileName: "User Lookup" });

166

167

const configParser = memoize(function(configPath) {

168

return parseConfigFile(configPath);

169

}, { profileName: "Config Parser" });

170

171

// Function without custom name (uses source location)

172

const genericProcessor = memoize(function(data) {

173

return data.map(x => x.toUpperCase());

174

});

175

176

// Functions are identified in reports by their profile names or source location

177

console.log(memProfile.log());

178

179

/* Output shows:

180

- "User Lookup, at /path/to/file.js:line:column"

181

- "Config Parser, at /path/to/file.js:line:column"

182

- "at /path/to/file.js:line:column" (for genericProcessor)

183

*/

184

```

185

186

## Advanced Profiling Patterns

187

188

### Performance Monitoring

189

190

Set up continuous performance monitoring for production applications.

191

192

```javascript

193

const memProfile = require("memoizee/profile");

194

const memoize = require("memoizee");

195

196

// Create monitored functions

197

const criticalFunction = memoize(expensiveOperation, {

198

profileName: "Critical Path Operation"

199

});

200

201

// Monitor performance periodically

202

setInterval(() => {

203

const stats = memProfile.statistics;

204

205

Object.keys(stats).forEach(key => {

206

const { initial, cached } = stats[key];

207

const total = initial + cached;

208

const hitRate = total > 0 ? (cached / total * 100) : 0;

209

210

// Alert on poor cache performance

211

if (total > 100 && hitRate < 50) {

212

console.warn(`Low cache hit rate for ${key}: ${hitRate.toFixed(2)}%`);

213

}

214

215

// Alert on high cache usage

216

if (cached > 10000) {

217

console.info(`High cache usage for ${key}: ${cached} hits`);

218

}

219

});

220

}, 60000); // Check every minute

221

222

// Reset statistics periodically

223

setInterval(() => {

224

// Save current stats before reset

225

const currentStats = JSON.parse(JSON.stringify(memProfile.statistics));

226

227

// Clear statistics (requires recreating memoized functions)

228

Object.keys(memProfile.statistics).forEach(key => {

229

delete memProfile.statistics[key];

230

});

231

232

console.log("Statistics reset. Previous period:", currentStats);

233

}, 3600000); // Reset every hour

234

```

235

236

### A/B Testing Cache Strategies

237

238

Compare different memoization strategies using profiling data.

239

240

```javascript

241

const memProfile = require("memoizee/profile");

242

const memoize = require("memoizee");

243

244

// Strategy A: Primitive mode

245

const strategyA = memoize(dataTransform, {

246

primitive: true,

247

profileName: "Strategy A (Primitive)"

248

});

249

250

// Strategy B: Object mode with normalizer

251

const strategyB = memoize(dataTransform, {

252

normalizer: (args) => JSON.stringify(args[0]),

253

profileName: "Strategy B (Normalized)"

254

});

255

256

// Strategy C: Size-limited cache

257

const strategyC = memoize(dataTransform, {

258

max: 100,

259

profileName: "Strategy C (Limited)"

260

});

261

262

// Test each strategy

263

const testData = generateTestCases(1000);

264

265

console.time("Strategy A");

266

testData.forEach(data => strategyA(data));

267

console.timeEnd("Strategy A");

268

269

console.time("Strategy B");

270

testData.forEach(data => strategyB(data));

271

console.timeEnd("Strategy B");

272

273

console.time("Strategy C");

274

testData.forEach(data => strategyC(data));

275

console.timeEnd("Strategy C");

276

277

// Compare cache performance

278

console.log(memProfile.log());

279

```

280

281

### Custom Statistics Analysis

282

283

Build custom analytics on top of the profiling data.

284

285

```javascript

286

const memProfile = require("memoizee/profile");

287

288

function analyzePerformance() {

289

const stats = memProfile.statistics;

290

const analysis = {

291

totalFunctions: Object.keys(stats).length,

292

totalCalls: 0,

293

totalHits: 0,

294

functions: []

295

};

296

297

Object.entries(stats).forEach(([name, data]) => {

298

const total = data.initial + data.cached;

299

const hitRate = total > 0 ? (data.cached / total) : 0;

300

301

analysis.totalCalls += total;

302

analysis.totalHits += data.cached;

303

304

analysis.functions.push({

305

name,

306

calls: total,

307

hits: data.cached,

308

hitRate,

309

efficiency: hitRate * Math.log(total + 1) // Weighted by usage

310

});

311

});

312

313

// Sort by efficiency

314

analysis.functions.sort((a, b) => b.efficiency - a.efficiency);

315

316

analysis.overallHitRate = analysis.totalCalls > 0

317

? (analysis.totalHits / analysis.totalCalls)

318

: 0;

319

320

return analysis;

321

}

322

323

// Generate detailed performance report

324

function generatePerformanceReport() {

325

const analysis = analyzePerformance();

326

327

console.log("=== Performance Analysis ===");

328

console.log(`Total Functions: ${analysis.totalFunctions}`);

329

console.log(`Total Calls: ${analysis.totalCalls}`);

330

console.log(`Overall Hit Rate: ${(analysis.overallHitRate * 100).toFixed(2)}%`);

331

console.log("\nTop Performing Functions:");

332

333

analysis.functions.slice(0, 5).forEach((fn, i) => {

334

console.log(`${i + 1}. ${fn.name}`);

335

console.log(` Hit Rate: ${(fn.hitRate * 100).toFixed(2)}%`);

336

console.log(` Calls: ${fn.calls}, Hits: ${fn.hits}`);

337

console.log(` Efficiency Score: ${fn.efficiency.toFixed(2)}`);

338

});

339

}

340

341

// Run analysis periodically

342

setInterval(generatePerformanceReport, 300000); // Every 5 minutes

343

```

344

345

## Production Considerations

346

347

### Performance Impact

348

349

The profiling module adds overhead to memoized functions:

350

351

```javascript

352

// ⚠️ Profiling overhead considerations

353

const memProfile = require("memoizee/profile");

354

355

// Profiling adds:

356

// - Stack trace analysis for source location detection

357

// - Event listener overhead for cache operations

358

// - Statistics object maintenance

359

// - Memory usage for storing statistics

360

361

// Recommendations:

362

// ✅ Use in development and testing

363

// ✅ Use in production with monitoring systems

364

// ❌ Avoid in high-performance critical paths unless necessary

365

```

366

367

### Production Setup

368

369

Best practices for using profiling in production environments:

370

371

```javascript

372

// Conditional profiling based on environment

373

if (process.env.NODE_ENV !== 'production' || process.env.ENABLE_MEMOIZE_PROFILING) {

374

require("memoizee/profile");

375

}

376

377

const memoize = require("memoizee");

378

379

// Profile only critical functions in production

380

const criticalMemoized = memoize(criticalFunction, {

381

profileName: process.env.NODE_ENV === 'production'

382

? "Critical Function"

383

: undefined // Use source location in development

384

});

385

386

// Export statistics for monitoring systems

387

if (typeof require("memoizee/profile") !== 'undefined') {

388

setInterval(() => {

389

const stats = require("memoizee/profile").statistics;

390

// Send stats to monitoring service

391

monitoringService.sendMetrics('memoize_stats', stats);

392

}, 60000);

393

}

394

```

395

396

### Memory Management

397

398

Profiling statistics accumulate over time and may need periodic cleanup:

399

400

```javascript

401

const memProfile = require("memoizee/profile");

402

403

// Monitor statistics memory usage

404

function getStatsMemoryUsage() {

405

const stats = memProfile.statistics;

406

const entryCount = Object.keys(stats).length;

407

const estimatedBytes = entryCount * 200; // Rough estimate

408

return { entryCount, estimatedBytes };

409

}

410

411

// Periodic cleanup (if needed)

412

setInterval(() => {

413

const usage = getStatsMemoryUsage();

414

console.log(`Stats memory: ${usage.entryCount} entries, ~${usage.estimatedBytes} bytes`);

415

416

// Reset if too large (requires application restart or recreation of memoized functions)

417

if (usage.entryCount > 10000) {

418

console.log("Consider resetting memoization statistics");

419

}

420

}, 600000); // Check every 10 minutes

421

```