# Python Performance

> When to activate: Python profiling, cProfile, memory profiling, optimization, numba, Cython, bottlenecks

- Skill: `mattakushi432/python-performance` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mattakushi432/python-performance`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mattakushi432/python-performance/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Mattakushi432 (https://skillmd.com/u/mattakushi432)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mattakushi432/python-performance

---


# Python Performance Patterns

## Profiling Tools
```bash
# CPU profiling
python -m cProfile -s cumtime -o profile.out script.py
python -m pstats profile.out  # interactive viewer
snakeviz profile.out          # visual flamegraph (pip install snakeviz)

# Line profiler (most useful for identifying hot lines)
pip install line_profiler
kernprof -l -v script.py  # requires @profile decorator

# Memory profiler
pip install memory_profiler
python -m memory_profiler script.py  # requires @profile decorator
mprof run script.py && mprof plot    # memory over time
```

## Profiling in Code
```python
import cProfile
import pstats
import io
from contextlib import contextmanager

@contextmanager
def profile_block(n_top: int = 20):
    pr = cProfile.Profile()
    pr.enable()
    yield
    pr.disable()
    s = io.StringIO()
    ps = pstats.Stats(pr, stream=s).sort_stats("cumulative")
    ps.print_stats(n_top)
    print(s.getvalue())

with profile_block():
    result = expensive_computation()
```

## Key Optimizations

### Use `__slots__` for hot objects
```python
@dataclass
class Point:
    __slots__ = ("x", "y")  # 3x less memory, faster attribute access
    x: float
    y: float
```

### Avoid global lookups in tight loops
```python
# Bad: each iteration looks up `math.sqrt` in global namespace
import math
for x in big_list:
    result = math.sqrt(x)

# Good: local binding
from math import sqrt
for x in big_list:
    result = sqrt(x)
```

### Use built-ins and stdlib over hand-rolled code
```python
# Sorting
sorted_items = sorted(items, key=lambda x: x.score, reverse=True)

# Grouping
from itertools import groupby
for key, group in groupby(sorted(items, key=attrgetter("category")), key=attrgetter("category")):
    ...

# Counting
from collections import Counter
counts = Counter(item.category for item in items)
```

### Numpy for numeric work
```python
import numpy as np

# Bad: Python loop for numeric computation
result = [x * 2 + 1 for x in large_list]  # slow

# Good: vectorized numpy
arr = np.array(large_list)
result = arr * 2 + 1  # 100x faster for large arrays
```

### Numba for JIT compilation
```python
from numba import jit, njit

@njit  # no-python mode: compiles to machine code
def compute_distances(points: np.ndarray) -> np.ndarray:
    n = len(points)
    distances = np.zeros((n, n))
    for i in range(n):
        for j in range(i + 1, n):
            d = np.sqrt(((points[i] - points[j]) ** 2).sum())
            distances[i, j] = distances[j, i] = d
    return distances
```

## Common Bottlenecks
- String concatenation in loops → use `"".join(parts)`
- `in` on lists with large sets → convert to `set` first
- Repeated `dict.get()` / attribute access → local binding
- JSON parsing in loops → batch or cache
- Missing database indexes → check EXPLAIN ANALYZE

