Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Implement custom cache replacement algorithms using pure Python functions - **no

### Python Hook Cache Overview

The `PythonHookCachePolicy` allows you to define custom caching behavior through Python callback functions. This is perfect for:
The `PluginCache` allows you to define custom caching behavior through Python callback functions. This is perfect for:
- Prototyping new cache algorithms
- Educational purposes and learning
- Research and experimentation
Expand All @@ -124,7 +124,7 @@ import libcachesim as lcs
from collections import OrderedDict

# Create a Python hook-based cache
cache = lcs.PythonHookCachePolicy(cache_size=1024*1024, cache_name="MyLRU")
cache = lcs.PluginCache(cache_size=1024*1024, cache_name="MyLRU")

# Define LRU policy hooks
def init_hook(cache_size):
Expand Down Expand Up @@ -160,7 +160,7 @@ import libcachesim as lcs
from collections import deque
from contextlib import suppress

cache = lcs.PythonHookCachePolicy(cache_size=1024, cache_name="CustomFIFO")
cache = lcs.PluginCache(cache_size=1024, cache_name="CustomFIFO")

def init_hook(cache_size):
return deque() # Use deque for FIFO order
Expand Down
6 changes: 3 additions & 3 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ caches = {
}

# Create Python hook cache
python_cache = lcs.PythonHookCachePolicy(cache_size, "CustomLRU")
python_cache = lcs.PluginCache(cache_size, "CustomLRU")
# Set hook functions...
caches["Custom Python LRU"] = python_cache

Expand Down Expand Up @@ -101,7 +101,7 @@ class LRUPolicy:
return next(iter(self.access_order))

def create_lru_cache(cache_size):
cache = lcs.PythonHookCachePolicy(cache_size, "PythonLRU")
cache = lcs.PluginCache(cache_size, "PythonLRU")

def init_hook(cache_size):
return LRUPolicy(cache_size)
Expand Down Expand Up @@ -166,7 +166,7 @@ for alpha in alphas:
### Cache Algorithms
- **Classic algorithms**: `LRU()`, `FIFO()`, `ARC()`, `Clock()`
- **Modern algorithms**: `S3FIFO()`, `Sieve()`, `TinyLFU()`
- **Custom policies**: `PythonHookCachePolicy()`
- **Custom policies**: `PluginCache()`

### Trace Processing
- `open_trace()`: Open real trace files
Expand Down
2 changes: 1 addition & 1 deletion examples/demo_unified_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def demo_unified_interface():
}

# Create Python hook-based LRU
python_cache = lcs.PythonHookCachePolicy(cache_size, "CustomLRU")
python_cache = lcs.PluginCache(cache_size, "CustomLRU")
init_hook, hit_hook, miss_hook, eviction_hook, remove_hook = create_demo_lru_hooks()
python_cache.set_hooks(init_hook, hit_hook, miss_hook, eviction_hook, remove_hook)
caches["Custom Python LRU"] = python_cache
Expand Down
72 changes: 72 additions & 0 deletions examples/plugin_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from collections import OrderedDict
from libcachesim import PluginCache, CommonCacheParams, Request, SyntheticReader, LRU

class StandaloneLRU:
def __init__(self):
self.cache_data = OrderedDict()

def cache_hit(self, obj_id):
if obj_id in self.cache_data:
obj_size = self.cache_data.pop(obj_id)
self.cache_data[obj_id] = obj_size

def cache_miss(self, obj_id, obj_size):
self.cache_data[obj_id] = obj_size

def cache_eviction(self):
evicted_id, _ = self.cache_data.popitem(last=False)
return evicted_id

def cache_remove(self, obj_id):
if obj_id in self.cache_data:
del self.cache_data[obj_id]


def cache_init_hook(common_cache_params: CommonCacheParams):
return StandaloneLRU()

def cache_hit_hook(cache, obj_id):
cache.cache_hit(obj_id)

def cache_miss_hook(cache, request: Request):
cache.cache_miss(request.obj_id, request.obj_size)

def cache_eviction_hook(cache):
return cache.cache_eviction()

def cache_remove_hook(cache, obj_id):
cache.cache_remove(obj_id)

def cache_free_hook(cache):
cache.cache_data.clear()

plugin_lru_cache = PluginCache(
cache_size=1024*1024,
cache_init_hook=cache_init_hook,
cache_hit_hook=cache_hit_hook,
cache_miss_hook=cache_miss_hook,
cache_eviction_hook=cache_eviction_hook,
cache_remove_hook=cache_remove_hook,
cache_free_hook=cache_free_hook,
cache_name="CustomizedLRU")

ref_lru_cache = LRU(cache_size=1024*1024)

reader = SyntheticReader(
num_of_req=100000,
num_objects=100,
obj_size=100,
seed=42,
alpha=0.8,
dist="zipf",
)

for req in reader:
plugin_hit = plugin_lru_cache.get(req)
ref_hit = ref_lru_cache.get(req)
assert plugin_hit == ref_hit, f"Cache hit mismatch: {plugin_hit} != {ref_hit}"

print("All requests processed successfully. Plugin cache matches reference LRU cache.")



6 changes: 3 additions & 3 deletions examples/python_hook_cache_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Example demonstrating how to create custom cache policies using Python hooks.

This example shows how to implement LRU and FIFO cache policies using the
PythonHookCachePolicy class, which allows users to define cache behavior using
PluginCache class, which allows users to define cache behavior using
pure Python functions instead of C/C++ plugins.
"""

Expand Down Expand Up @@ -72,7 +72,7 @@ def on_remove(self, obj_id):

def create_lru_cache(cache_size):
"""Create an LRU cache using Python hooks."""
cache = lcs.PythonHookCachePolicy(cache_size, "PythonLRU")
cache = lcs.PluginCache(cache_size, "PythonLRU")

def init_hook(cache_size):
return LRUPolicy(cache_size)
Expand All @@ -99,7 +99,7 @@ def free_hook(policy):

def create_fifo_cache(cache_size):
"""Create a FIFO cache using Python hooks."""
cache = lcs.PythonHookCachePolicy(cache_size, "PythonFIFO")
cache = lcs.PluginCache(cache_size, "PythonFIFO")

def init_hook(cache_size):
return FIFOPolicy(cache_size)
Expand Down
6 changes: 4 additions & 2 deletions libcachesim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
SamplerType,
AnalysisParam,
AnalysisOption,
CommonCacheParams,
__doc__,
__version__,
)
Expand Down Expand Up @@ -38,7 +39,7 @@
Belady,
BeladySize,
# Plugin cache
PythonHookCachePolicy,
PluginCache,
)

from .trace_reader import TraceReader
Expand All @@ -56,6 +57,7 @@
"SamplerType",
"AnalysisParam",
"AnalysisOption",
"CommonCacheParams",
# Cache base class
"CacheBase",
# Core cache algorithms
Expand All @@ -80,7 +82,7 @@
"Belady",
"BeladySize",
# Plugin cache
"PythonHookCachePolicy",
"PluginCache",
# Readers and analyzers
"TraceReader",
"TraceAnalyzer",
Expand Down
2 changes: 1 addition & 1 deletion libcachesim/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class BeladySize(CacheBase):
): ...

# Plugin cache
class PythonHookCachePolicy(CacheBase):
class PluginCache(CacheBase):
def __init__(
self,
cache_size: int,
Expand Down
28 changes: 8 additions & 20 deletions libcachesim/cache.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC
from typing import Protocol
from typing import Protocol, Callable, Optional
from .libcachesim_python import (
CommonCacheParams,
Request,
Expand Down Expand Up @@ -351,29 +351,23 @@ def __init__(


# Plugin cache for custom Python implementations
def nop_method(*args, **kwargs):
"""No-operation method for default hooks"""
pass


class PythonHookCachePolicy(CacheBase):
class PluginCache(CacheBase):
"""Python plugin cache for custom implementations"""

def __init__(
self,
cache_size: int,
cache_init_hook: Callable,
cache_hit_hook: Callable,
cache_miss_hook: Callable,
cache_eviction_hook: Callable,
cache_remove_hook: Callable,
cache_free_hook: Optional[Callable] = None,
cache_name: str = "PythonHookCache",
default_ttl: int = 86400 * 300,
hashpower: int = 24,
consider_obj_metadata: bool = False,
cache_init_hook=nop_method,
cache_hit_hook=nop_method,
cache_miss_hook=nop_method,
cache_eviction_hook=nop_method,
cache_remove_hook=nop_method,
cache_free_hook=nop_method,
):
self.cache_name = cache_name
self.common_cache_params = _create_common_params(cache_size, default_ttl, hashpower, consider_obj_metadata)

super().__init__(
Expand All @@ -388,9 +382,3 @@ def __init__(
cache_free_hook,
)
)

def set_hooks(self, init_hook, hit_hook, miss_hook, eviction_hook, remove_hook, free_hook=nop_method):
"""Set the cache hooks after initialization"""
# Note: This would require C++ side support to change hooks after creation
# For now, hooks should be set during initialization
pass
Loading