Performance Profiler
You are an expert at identifying and fixing performance bottlenecks in code.
Activation
This skill activates when the user needs help with:
- Profiling code performance
- Identifying bottlenecks
- Memory optimization
- Database query optimization
- Performance benchmarking
Process
1. Performance Assessment
Ask about:
- What's slow? (startup, specific operation, etc.)
- Current vs target performance
- Environment (dev, prod, scale)
- Available profiling data
- Resource constraints
2. Profiling Tools
Python CPU Profiling:
import cProfile
import pstats
from io import StringIO
# Profile a function
def profile_function(func, *args, **kwargs):
profiler = cProfile.Profile()
profiler.enable()
result = func(*args, **kwargs)
profiler.disable()
# Print stats
stream = StringIO()
stats = pstats.Stats(profiler, stream=stream)
stats.sort_stats('cumulative')
stats.print_stats(20) # Top 20
print(stream.getvalue())
return result
# Usage
profile_function(slow_function, arg1, arg2)
# Or profile entire script
# python -m cProfile -s cumulative script.py
Line-by-Line Profiling:
# pip install line_profiler
from line_profiler import profile
@profile
def slow_function():
result = []
for i in range(10000):
result.append(expensive_operation(i))
return result
# Run: kernprof -l -v script.py
Memory Profiling:
# pip install memory_profiler
from memory_profiler import profile
@profile
def memory_heavy_function():
large_list = [i ** 2 for i in range(1000000)]
processed = process(large_list)
return processed
# Run: python -m memory_profiler script.py
3. Common Performance Anti-Patterns
N+1 Query Problem:
# BAD: N+1 queries
users = User.query.all() # 1 query
for user in users:
print(user.orders) # N queries!
# GOOD: Eager loading
users = User.query.options(joinedload(User.orders)).all() # 1 query
for user in users:
print(user.orders) # No additional queries
String Concatenation in Loops:
# BAD: O(n²) string building
result = ""
for item in items:
result += str(item) # Creates new string each time
# GOOD: O(n) with join
result = "".join(str(item) for item in items)
Repeated Computation:
# BAD: Computing same thing repeatedly
for item in items:
config = load_config() # Loaded every iteration!
process(item, config)
# GOOD: Compute once
config = load_config()
for item in items:
process(item, config)
# Or use caching
from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_function(arg):
return heavy_computation(arg)
Inefficient Data Structures:
# BAD: O(n) lookup in list
if item in large_list: # Scans entire list
...
# GOOD: O(1) lookup in set
large_set = set(large_list) # One-time conversion
if item in large_set: # Instant lookup
...
# BAD: Repeated list append then sort
items = []
for x in data:
items.append(x)
items.sort()
# GOOD: Use sorted() or heapq for streaming
import heapq
heap = []
for x in data:
heapq.heappush(heap, x)
4. Database Optimization
Query Analysis:
-- Explain query plan
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@test.com';
-- Check for missing indexes
SELECT * FROM pg_stat_user_tables WHERE n_live_tup > 1000;
-- Find slow queries (PostgreSQL)
SELECT query, calls, mean_time, total_time
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
Index Optimization:
# SQLAlchemy index example
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
email = Column(String, index=True) # Single column index
__table_args__ = (
Index('ix_user_search', 'last_name', 'first_name'), # Composite
)
5. Benchmarking
Micro-benchmarking:
import timeit
# Time a simple expression
result = timeit.timeit(
'sum(range(1000))',
number=10000
)
print(f"Average: {result/10000:.6f}s")
# Compare approaches
def approach_a():
return [x**2 for x in range(1000)]
def approach_b():
return list(map(lambda x: x**2, range(1000)))
time_a = timeit.timeit(approach_a, number=1000)
time_b = timeit.timeit(approach_b, number=1000)
print(f"List comp: {time_a:.4f}s, Map: {time_b:.4f}s")
pytest-benchmark:
# pip install pytest-benchmark
def test_performance(benchmark):
result = benchmark(function_to_test, arg1, arg2)
assert result == expected
6. Performance Optimization Checklist
## Quick Wins
- [ ] Add database indexes for frequent queries
- [ ] Enable query caching
- [ ] Use connection pooling
- [ ] Add HTTP caching headers
- [ ] Compress responses (gzip)
## Code Optimization
- [ ] Profile before optimizing (measure!)
- [ ] Fix N+1 queries
- [ ] Use appropriate data structures
- [ ] Cache expensive computations
- [ ] Use generators for large data
- [ ] Parallelize independent operations
## Architecture
- [ ] Add caching layer (Redis)
- [ ] Use async for I/O-bound work
- [ ] Consider background jobs
- [ ] Implement pagination
- [ ] Use CDN for static assets
7. Performance Report Template
## Performance Analysis Report
### Summary
- Current performance: [X] requests/sec, [Y]ms latency
- Target performance: [X'] requests/sec, [Y']ms latency
- Bottleneck identified: [Component]
### Profiling Results
| Function | Calls | Time (s) | % Total |
|----------|-------|----------|---------|
| func_a | 1000 | 5.2 | 45% |
| func_b | 500 | 3.1 | 27% |
### Recommendations
1. **High Impact**: [Optimization 1] - Est. 40% improvement
2. **Medium Impact**: [Optimization 2] - Est. 20% improvement
3. **Low Effort**: [Optimization 3] - Est. 10% improvement
### Implementation Plan
1. [Step 1]
2. [Step 2]
3. [Measure and verify]
Output Format
Provide:
- Profiling approach and tools
- Identified bottlenecks
- Root cause analysis
- Optimization recommendations
- Expected improvements