home / skills / aj-geddes / useful-ai-prompts / memory-optimization

memory-optimization skill

/skills/memory-optimization

This skill profiles and optimizes application memory usage to detect leaks, reduce footprint, and boost performance.

npx playbooks add skill aj-geddes/useful-ai-prompts --skill memory-optimization

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.8 KB
---
name: memory-optimization
description: Profile and optimize application memory usage. Identify memory leaks, reduce memory footprint, and improve efficiency for better performance and reliability.
---

# Memory Optimization

## Overview

Memory optimization improves application performance, stability, and reduces infrastructure costs. Efficient memory usage is critical for scalability.

## When to Use

- High memory usage
- Memory leaks suspected
- Slow performance
- Out of memory crashes
- Scaling challenges

## Instructions

### 1. **Memory Profiling**

```javascript
// Browser memory profiling

// Check memory usage
performance.memory: {
  jsHeapSizeLimit: 2190000000,    // Max available
  totalJSHeapSize: 1300000000,    // Total allocated
  usedJSHeapSize: 950000000       // Currently used
}

// React DevTools Profiler
- Open React DevTools → Profiler
- Record interaction
- See component renders and time
- Identify unnecessary renders

// Chrome DevTools
1. Open DevTools → Memory
2. Take heap snapshot
3. Compare before/after
4. Look for retained objects
5. Check retained sizes

// Node.js profiling
node --inspect app.js
// Open chrome://inspect
// Take heap snapshots
// Compare growth over time
```

### 2. **Memory Leak Detection**

```python
# Identify and fix memory leaks

class MemoryLeakDebug:
    def identify_leaks(self):
        """Common patterns"""
        return {
            'circular_references': {
                'problem': 'Objects reference each other, prevent GC',
                'example': 'parent.child = child; child.parent = parent',
                'solution': 'Use weak references or cleaner code'
            },
            'event_listeners': {
                'problem': 'Listeners not removed',
                'example': 'element.addEventListener(...) without removeEventListener',
                'solution': 'Always remove listeners on cleanup'
            },
            'timers': {
                'problem': 'setInterval/setTimeout not cleared',
                'example': 'setInterval(() => {}, 1000) never clearInterval',
                'solution': 'Store ID and clear on unmount'
            },
            'cache_unbounded': {
                'problem': 'Cache grows without bounds',
                'example': 'cache[key] = value (never deleted)',
                'solution': 'Implement TTL or size limits'
            },
            'dom_references': {
                'problem': 'Removed DOM elements still referenced',
                'example': 'var x = document.getElementById("removed")',
                'solution': 'Clear references after removal'
            }
        }

    def detect_in_browser(self):
        """JavaScript detection"""
        return """
// Monitor memory growth
setInterval(() => {
  const mem = performance.memory;
  const used = mem.usedJSHeapSize / 1000000;
  console.log(`Memory: ${used.toFixed(1)} MB`);
}, 1000);

// If grows over time without plateau = leak
"""
```

### 3. **Optimization Techniques**

```yaml
Memory Optimization:

Object Pooling:
  Pattern: Reuse objects instead of creating new
  Example: GameObject pool in games
  Benefits: Reduce GC, stable memory
  Trade-off: Complexity

Lazy Loading:
  Pattern: Load data only when needed
  Example: Infinite scroll
  Benefits: Lower peak memory
  Trade-off: Complexity

Pagination:
  Pattern: Process data in chunks
  Example: 1M records → 1K per page
  Benefits: Constant memory
  Trade-off: More requests

Stream Processing:
  Pattern: Process one item at a time
  Example: fs.createReadStream()
  Benefits: Constant memory for large data
  Trade-off: Slower if cached

Memoization:
  Pattern: Cache expensive calculations
  Benefits: Faster, reuse results
  Trade-off: Memory for speed

---

Framework-Specific:

React:
  - useMemo for expensive calculations
  - useCallback to avoid creating functions
  - Code splitting / lazy loading
  - Windowing for long lists (react-window)

Node.js:
  - Stream instead of loadFile
  - Limit cluster workers
  - Set heap size: --max-old-space-size=4096
  - Monitor with clinic.js

---

GC (Garbage Collection):

Minimize:
  - Object creation
  - Large allocations
  - Frequent new objects
  - String concatenation

Example (Bad):
let result = "";
for (let i = 0; i < 1000000; i++) {
  result += i.toString() + ",";
  // Creates new string each iteration
}

Example (Good):
const result = Array.from(
  {length: 1000000},
  (_, i) => i.toString()
).join(",");
// Single allocation
```

### 4. **Monitoring & Targets**

```yaml
Memory Targets:

Web App:
  Initial: <10MB
  After use: <50MB
  Peak: <100MB
  Leak check: Should plateau

Node.js API:
  Per-process: 100-500MB
  Cluster total: 1-4GB
  Heap size: Monitor vs available RAM

Mobile:
  Initial: <20MB
  Working: <50MB
  Peak: <100MB (device dependent)

---

Tools:

Browser:
  - Chrome DevTools Memory
  - Firefox DevTools Memory
  - React DevTools Profiler
  - Redux DevTools

Node.js:
  - node --inspect
  - clinic.js
  - nodemon --exec with monitoring
  - New Relic / DataDog

Monitoring:
  - Application Performance Monitoring (APM)
  - Prometheus + Grafana
  - CloudWatch
  - New Relic

---

Checklist:

[ ] Profile baseline memory
[ ] Identify heavy components
[ ] Remove event listeners on cleanup
[ ] Clear timers on cleanup
[ ] Implement lazy loading
[ ] Use pagination for large lists
[ ] Monitor memory trends
[ ] Set up GC monitoring
[ ] Test with production data volume
[ ] Stress test for leaks
[ ] Establish memory budget
[ ] Set up alerts
```

## Key Points

- Take baseline memory measurements
- Use profilers to identify issues
- Remove listeners and timers on cleanup
- Implement streaming for large data
- Use lazy loading and pagination
- Monitor GC pause times
- Set heap size appropriate for workload
- Object pooling for frequent allocations
- Regular memory testing with real data
- Alert on memory growth trends

Overview

This skill profiles and optimizes application memory usage to identify leaks, lower memory footprint, and improve runtime efficiency. It combines profiling techniques, leak detection patterns, and practical optimization patterns to make apps more stable and cost-effective. Use it to reduce crashes, improve latency, and scale reliably.

How this skill works

The skill runs targeted memory profiling in browsers and Node.js to collect heap snapshots, allocation trends, and retained sizes. It highlights common leak sources—event listeners, timers, caches, DOM references, and circular references—and maps them to concrete fixes. It also recommends optimization patterns like streaming, pagination, lazy loading, object pooling, and GC-friendly coding, plus monitoring and alerting targets.

When to use it

  • When observed memory grows over time without plateauing (suspected leak).
  • When apps hit out-of-memory crashes or frequent GC pauses.
  • When scaling increases infrastructure cost due to per-process memory.
  • When slow performance correlates with high memory or large allocations.
  • Before production rollouts to validate memory budgets and stability.

Best practices

  • Take baseline measurements and compare before/after heap snapshots.
  • Remove event listeners and clear timers during component teardown.
  • Prefer streams and pagination for large data sets to keep constant memory.
  • Use lazy loading and code-splitting to reduce peak memory usage.
  • Limit caches with TTL or size bounds; use weak refs where appropriate.

Example use cases

  • Detect a browser memory leak by recording DevTools heap snapshots and inspecting retained object graphs.
  • Reduce Node.js API memory by switching file processing to streams and limiting concurrency.
  • Lower SPA peak memory via code splitting, windowing long lists, and useMemo/useCallback for React.
  • Implement object pooling in a high-frequency allocation system (games, real-time processing).
  • Set heap size and monitor processes with clinic.js, APM, or Prometheus/Grafana for production alerts.

FAQ

How do I know if memory growth is a leak or normal usage?

Track memory over time under realistic load; leaks show unbounded growth without plateauing. Use heap snapshots to locate objects that keep getting retained.

What quick fixes reduce GC pressure?

Avoid frequent small allocations and string concatenation in hot loops, reuse objects where feasible, and prefer single large allocations (e.g., join arrays) over repeated concatenation.