-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbenchmarks.py
More file actions
68 lines (50 loc) · 2.34 KB
/
Copy pathbenchmarks.py
File metadata and controls
68 lines (50 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""
Chapter 11: Benchmarks — The Memory Savings of __slots__
========================================================
Measures the RAM footprint of 1,000,000 objects with and without __slots__.
Run: python benchmarks.py
"""
import sys
import tracemalloc
sys.stdout.reconfigure(encoding="utf-8")
def section(title: str) -> None:
print(f"\n{'=' * 55}\n {title}\n{'=' * 55}")
# ── Setup Classes ────────────────────────────────────────────────────────────
class DictPoint:
def __init__(self, x: float, y: float, z: float):
self.x = x
self.y = y
self.z = z
class SlotPoint:
__slots__ = ('x', 'y', 'z')
def __init__(self, x: float, y: float, z: float):
self.x = x
self.y = y
self.z = z
# ── Benchmarks ───────────────────────────────────────────────────────────────
def measure_memory(cls, num_instances: int) -> float:
tracemalloc.start()
# Store in a list so they aren't garbage collected
instances = [cls(1.0, 2.0, 3.0) for _ in range(num_instances)]
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
# Return memory used in Megabytes
return peak / (1024 * 1024)
def run_benchmarks():
section("Benchmark 1: __dict__ vs __slots__ Memory Footprint")
N = 1_000_000
print(f" (Allocating {N:,} instances of a 3-dimensional Point)\n")
mem_dict = measure_memory(DictPoint, N)
mem_slots = measure_memory(SlotPoint, N)
print(f" {'Architecture':<35} {'Memory Used (MB)':>16}")
print(" " + "-" * 52)
print(f" {'Standard class (uses __dict__)':<35} {mem_dict:>16.2f}")
print(f" {'Optimized class (uses __slots__)':<35} {mem_slots:>16.2f}")
savings = mem_dict - mem_slots
ratio = mem_dict / mem_slots if mem_slots > 0 else 0
print(f"\n Conclusion: __slots__ saved ~{savings:.1f} MB.")
print(f" The standard class uses roughly {ratio:.1f}x more memory because")
print(f" every single instance must allocate a dynamic hash table")
print(f" (dictionary) to store its attributes.")
if __name__ == "__main__":
run_benchmarks()