Domain papers distilled from python-numbers-everyone-should-know: - async-overhead: 1,400x sync vs async overhead - collection-membership: 200x set vs list at 1000 items - json-serialization: 8x orjson vs stdlib - exception-flow: 6.5x exception overhead (try/except free) - string-formatting: f-strings > % > .format() - memory-slots: 69% memory reduction with __slots__ - import-optimization: 100ms+ for heavy packages - database-patterns: 98% commit overhead in SQLite RULEBOOK.md: ~200 token distillation for coding subagents 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
103 lines
2.5 KiB
Markdown
103 lines
2.5 KiB
Markdown
# Memory Optimization with __slots__ in Python
|
|
|
|
**Domain Paper: Python Performance ADRs**
|
|
**Date:** 2026-01-03
|
|
**Source:** python-numbers-everyone-should-know benchmarks
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
Python's `__slots__` mechanism provides **52-70% memory reduction** when creating many instances of the same class.
|
|
|
|
**Key Finding**: For a class with 5 attributes, `__slots__` reduces instance memory from 694 bytes to 212 bytes (69% reduction).
|
|
|
|
---
|
|
|
|
## Benchmark Results: Memory Footprint
|
|
|
|
### Single Instance Memory (5 Attributes)
|
|
|
|
| Type | Memory (bytes) | vs Regular Class |
|
|
|------|----------------|------------------|
|
|
| Regular class | 694 | baseline |
|
|
| `__slots__` class | 212 | -69% |
|
|
| dataclass | 694 | same as regular |
|
|
| `@dataclass(slots=True)` | 212 | -69% |
|
|
| namedtuple | 228 | -67% |
|
|
|
|
### At Scale (1,000 Instances)
|
|
|
|
| Type | Total Memory |
|
|
|------|--------------|
|
|
| List of 1,000 regular class | 165.2 KB |
|
|
| List of 1,000 `__slots__` class | 79.1 KB |
|
|
|
|
**Memory Savings**: 52% reduction at scale
|
|
|
|
---
|
|
|
|
## Attribute Access Speed (Virtually Identical)
|
|
|
|
| Operation | Regular | `__slots__` |
|
|
|-----------|---------|-------------|
|
|
| Read attr | 14.1 ns | 14.1 ns |
|
|
| Write attr | 15.7 ns | 16.4 ns |
|
|
|
|
---
|
|
|
|
## Trade-offs
|
|
|
|
### What __slots__ Prevents
|
|
|
|
1. **No dynamic attribute assignment**
|
|
2. **No `__dict__` access** (`vars()` doesn't work)
|
|
3. **Inheritance complications**
|
|
4. **No weak references by default**
|
|
|
|
---
|
|
|
|
## Practical Rules for Coding Agents
|
|
|
|
### Rule 1: Instance Count Threshold
|
|
```
|
|
IF creating > 100 instances of the same class
|
|
AND attributes are fixed at design time
|
|
THEN consider __slots__ or @dataclass(slots=True)
|
|
```
|
|
|
|
### Rule 2: Prefer Slots Dataclass (Python 3.10+)
|
|
```python
|
|
@dataclass(slots=True)
|
|
class User:
|
|
id: int
|
|
name: str
|
|
email: str
|
|
```
|
|
|
|
### Rule 3: Don't Optimize Prematurely
|
|
For < 100 instances, use regular classes for flexibility.
|
|
|
|
### Rule 4: Document the Trade-off
|
|
```python
|
|
# Using __slots__ for memory efficiency (1000+ instances expected)
|
|
__slots__ = ['x', 'y', 'z']
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
| Aspect | Regular Class | `__slots__` Class |
|
|
|--------|---------------|-------------------|
|
|
| Memory (5 attrs) | 694 bytes | 212 bytes |
|
|
| Read speed | 14.1 ns | 14.1 ns |
|
|
| Dynamic attributes | Yes | No |
|
|
| Best for | Flexibility | Many instances |
|
|
|
|
**Bottom Line**: Use `__slots__` (or `@dataclass(slots=True)`) when creating many instances of fixed-attribute classes. For small numbers, stick with regular classes.
|
|
|
|
---
|
|
|
|
*Benchmark source: python-numbers-everyone-should-know*
|