# JavaScript/Node.js Performance Optimization **Load this file when:** Optimizing performance in JavaScript or Node.js projects ## Profiling Tools ### Node.js Built-in Profiler ```bash # CPU profiling node --prof app.js node --prof-process isolate-0x*.log > processed.txt # Inspect with Chrome DevTools node --inspect app.js # Open chrome://inspect # Heap snapshots node --inspect --inspect-brk app.js # Take heap snapshots in DevTools ``` ### Clinic.js Suite ```bash # Install clinic npm install -g clinic # Doctor - Overall health check clinic doctor -- node app.js # Flame - Flamegraph profiling clinic flame -- node app.js # Bubbleprof - Async operations clinic bubbleprof -- node app.js # Heap profiler clinic heapprofiler -- node app.js ``` ### Performance Measurement ```bash # 0x - Flamegraph generator npx 0x app.js # autocannon - HTTP load testing npx autocannon http://localhost:3000 # lighthouse - Frontend performance npx lighthouse https://example.com ``` ## V8 Optimization Patterns ### Hidden Classes and Inline Caches ```javascript // Bad: Dynamic property addition breaks hidden class function Point(x, y) { this.x = x; this.y = y; } const p1 = new Point(1, 2); p1.z = 3; // Deoptimizes! // Good: Consistent object shape function Point(x, y, z = 0) { this.x = x; this.y = y; this.z = z; // Always present } ``` ### Avoid Polymorphism in Hot Paths ```javascript // Bad: Type changes break optimization function add(a, b) { return a + b; } add(1, 2); // Optimized for numbers add("a", "b"); // Deoptimized! Now handles strings too // Good: Separate functions for different types function addNumbers(a, b) { return a + b; // Always numbers } function concatStrings(a, b) { return a + b; // Always strings } ``` ### Array Optimization ```javascript // Bad: Mixed types in array const mixed = [1, "two", 3, "four"]; // Slow property access // Good: Homogeneous arrays const numbers = [1, 2, 3, 4]; // Fast element access const strings = ["one", "two", "three"]; // Use typed arrays for numeric data const buffer = new Float64Array(1000); // Faster than regular arrays ``` ## Event Loop Optimization ### Avoid Blocking the Event Loop ```javascript // Bad: Synchronous operations block event loop const data = fs.readFileSync('large-file.txt'); const result = heavyComputation(data); // Good: Async operations const data = await fs.promises.readFile('large-file.txt'); const result = await processAsync(data); // For CPU-intensive work, use worker threads const { Worker } = require('worker_threads'); const worker = new Worker('./cpu-intensive.js'); ``` ### Batch Async Operations ```javascript // Bad: Sequential async calls for (const item of items) { await processItem(item); // Waits for each } // Good: Parallel execution await Promise.all(items.map(item => processItem(item))); // Better: Controlled concurrency with p-limit const pLimit = require('p-limit'); const limit = pLimit(10); // Max 10 concurrent await Promise.all( items.map(item => limit(() => processItem(item))) ); ``` ## Memory Management ### Avoid Memory Leaks ```javascript // Bad: Global variables and closures retain memory let cache = {}; // Never cleared function addToCache(key, value) { cache[key] = value; // Grows indefinitely } // Good: Use WeakMap for caching const cache = new WeakMap(); function addToCache(obj, value) { cache.set(obj, value); // Auto garbage collected } // Good: Implement cache eviction const LRU = require('lru-cache'); const cache = new LRU({ max: 500 }); ``` ### Stream Large Data ```javascript // Bad: Load entire file in memory const data = await fs.promises.readFile('large-file.txt'); const processed = data.toString().split('\n').map(process); // Good: Stream processing const readline = require('readline'); const stream = fs.createReadStream('large-file.txt'); const rl = readline.createInterface({ input: stream }); for await (const line of rl) { process(line); // Process one line at a time } ``` ## Database Query Optimization ### Connection Pooling ```javascript // Bad: Create new connection per request async function query(sql) { const conn = await mysql.createConnection(config); const result = await conn.query(sql); await conn.end(); return result; } // Good: Use connection pool const pool = mysql.createPool(config); async function query(sql) { return pool.query(sql); // Reuses connections } ``` ### Batch Database Operations ```javascript // Bad: Multiple round trips for (const user of users) { await db.insert('users', user); } // Good: Single batch insert await db.batchInsert('users', users, 1000); // Chunks of 1000 ``` ## HTTP Server Optimization ### Compression ```javascript const compression = require('compression'); app.use(compression({ level: 6, // Balance between speed and compression threshold: 1024 // Only compress responses > 1KB })); ``` ### Caching Headers ```javascript app.get('/static/*', (req, res) => { res.setHeader('Cache-Control', 'public, max-age=31536000'); res.setHeader('ETag', computeETag(file)); res.sendFile(file); }); ``` ### Keep-Alive Connections ```javascript const http = require('http'); const server = http.createServer({ keepAlive: true, keepAliveTimeout: 60000 // 60 seconds }, app); ``` ## Frontend Performance ### Code Splitting ```javascript // Dynamic imports for code splitting const HeavyComponent = lazy(() => import('./HeavyComponent')); // Route-based code splitting const routes = [ { path: '/dashboard', component: lazy(() => import('./Dashboard')) } ]; ``` ### Memoization ```javascript // React.memo for expensive components const ExpensiveComponent = React.memo(({ data }) => { return