-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathpython_hook_cache_example.py
More file actions
178 lines (131 loc) · 5.11 KB
/
python_hook_cache_example.py
File metadata and controls
178 lines (131 loc) · 5.11 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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/env python3
"""
Example demonstrating how to create custom cache policies using Python hooks.
This example shows how to implement LRU and FIFO cache policies using the
PluginCache class, which allows users to define cache behavior using
pure Python functions instead of C/C++ plugins.
"""
import libcachesim as lcs
from collections import OrderedDict, deque
from contextlib import suppress
class LRUPolicy:
"""LRU (Least Recently Used) cache policy implementation."""
def __init__(self, cache_size):
self.cache_size = cache_size
self.access_order = OrderedDict() # obj_id -> True (for ordering)
def on_hit(self, obj_id, obj_size):
"""Move accessed object to end (most recent)."""
if obj_id in self.access_order:
# Move to end (most recent)
self.access_order.move_to_end(obj_id)
def on_miss(self, obj_id, obj_size):
"""Add new object to end (most recent)."""
self.access_order[obj_id] = True
def evict(self, obj_id, obj_size):
"""Return the least recently used object ID."""
if self.access_order:
# Return first item (least recent)
victim_id = next(iter(self.access_order))
return victim_id
raise RuntimeError("No objects to evict")
def on_remove(self, obj_id):
"""Remove object from tracking."""
self.access_order.pop(obj_id, None)
class FIFOPolicy:
"""FIFO (First In First Out) cache policy implementation."""
def __init__(self, cache_size):
self.cache_size = cache_size
self.insertion_order = deque() # obj_id queue
def on_hit(self, obj_id, obj_size):
"""FIFO doesn't change order on hits."""
pass
def on_miss(self, obj_id, obj_size):
"""Add new object to end of queue."""
self.insertion_order.append(obj_id)
def evict(self, obj_id, obj_size):
"""Return the first inserted object ID."""
if self.insertion_order:
victim_id = self.insertion_order.popleft()
return victim_id
raise RuntimeError("No objects to evict")
def on_remove(self, obj_id):
"""Remove object from tracking."""
with suppress(ValueError):
self.insertion_order.remove(obj_id)
def create_lru_cache(cache_size):
"""Create an LRU cache using Python hooks."""
cache = lcs.PluginCache(cache_size, "PythonLRU")
def init_hook(cache_size):
return LRUPolicy(cache_size)
def hit_hook(policy, obj_id, obj_size):
policy.on_hit(obj_id, obj_size)
def miss_hook(policy, obj_id, obj_size):
policy.on_miss(obj_id, obj_size)
def eviction_hook(policy, obj_id, obj_size):
return policy.evict(obj_id, obj_size)
def remove_hook(policy, obj_id):
policy.on_remove(obj_id)
def free_hook(policy):
# Python garbage collection handles cleanup
pass
cache.set_hooks(init_hook, hit_hook, miss_hook, eviction_hook, remove_hook, free_hook)
return cache
def create_fifo_cache(cache_size):
"""Create a FIFO cache using Python hooks."""
cache = lcs.PluginCache(cache_size, "PythonFIFO")
def init_hook(cache_size):
return FIFOPolicy(cache_size)
def hit_hook(policy, obj_id, obj_size):
policy.on_hit(obj_id, obj_size)
def miss_hook(policy, obj_id, obj_size):
policy.on_miss(obj_id, obj_size)
def eviction_hook(policy, obj_id, obj_size):
return policy.evict(obj_id, obj_size)
def remove_hook(policy, obj_id):
policy.on_remove(obj_id)
cache.set_hooks(init_hook, hit_hook, miss_hook, eviction_hook, remove_hook)
return cache
def test_cache_policy(cache, name):
"""Test a cache policy with sample requests."""
print(f"\n=== Testing {name} Cache ===")
# Test requests: obj_id, obj_size
test_requests = [
(1, 100),
(2, 100),
(3, 100),
(4, 100),
(5, 100), # Fill cache
(1, 100), # Hit
(6, 100), # Miss, should evict something
(2, 100), # Hit or miss depending on policy
(7, 100), # Miss, should evict something
]
hits = 0
misses = 0
for obj_id, obj_size in test_requests:
req = lcs.Request()
req.obj_id = obj_id
req.obj_size = obj_size
hit = cache.get(req)
if hit:
hits += 1
print(f"Request {obj_id}: HIT")
else:
misses += 1
print(f"Request {obj_id}: MISS")
print(f"Total: {hits} hits, {misses} misses")
print(f"Cache stats: {cache.n_obj} objects, {cache.occupied_byte} bytes occupied")
def main():
"""Main example function."""
cache_size = 500 # Bytes (can hold 5 objects of size 100 each)
# Test LRU cache
lru_cache = create_lru_cache(cache_size)
test_cache_policy(lru_cache, "LRU")
# Test FIFO cache
fifo_cache = create_fifo_cache(cache_size)
test_cache_policy(fifo_cache, "FIFO")
print("\n=== Comparison ===")
print("LRU keeps recently accessed items, evicting least recently used")
print("FIFO keeps items in insertion order, evicting oldest inserted")
if __name__ == "__main__":
main()