feat: Add 8 domain papers and RULEBOOK.md
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>
This commit is contained in:
102
papers/memory-slots.md
Normal file
102
papers/memory-slots.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 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*
|
||||
Reference in New Issue
Block a user