From 63602f036b12ae7e531437c640923f81fb39a206 Mon Sep 17 00:00:00 2001 From: haochengxia Date: Sat, 26 Jul 2025 03:39:51 +0000 Subject: [PATCH] Fix pluginCache --- README.md | 6 +-- examples/README.md | 6 +-- examples/demo_unified_interface.py | 2 +- examples/plugin_cache.py | 72 +++++++++++++++++++++++++++ examples/python_hook_cache_example.py | 6 +-- libcachesim/__init__.py | 6 ++- libcachesim/__init__.pyi | 2 +- libcachesim/cache.py | 28 +++-------- 8 files changed, 95 insertions(+), 33 deletions(-) create mode 100644 examples/plugin_cache.py diff --git a/README.md b/README.md index 14707c5..6a04cdb 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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): @@ -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 diff --git a/examples/README.md b/examples/README.md index 3b63b7f..9f9f2e0 100644 --- a/examples/README.md +++ b/examples/README.md @@ -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 @@ -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) @@ -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 diff --git a/examples/demo_unified_interface.py b/examples/demo_unified_interface.py index e435e58..0cb629f 100644 --- a/examples/demo_unified_interface.py +++ b/examples/demo_unified_interface.py @@ -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 diff --git a/examples/plugin_cache.py b/examples/plugin_cache.py new file mode 100644 index 0000000..fd144f6 --- /dev/null +++ b/examples/plugin_cache.py @@ -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.") + + + \ No newline at end of file diff --git a/examples/python_hook_cache_example.py b/examples/python_hook_cache_example.py index 06d06c4..fa309d4 100644 --- a/examples/python_hook_cache_example.py +++ b/examples/python_hook_cache_example.py @@ -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. """ @@ -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) @@ -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) diff --git a/libcachesim/__init__.py b/libcachesim/__init__.py index f71c6ee..137b4e9 100644 --- a/libcachesim/__init__.py +++ b/libcachesim/__init__.py @@ -10,6 +10,7 @@ SamplerType, AnalysisParam, AnalysisOption, + CommonCacheParams, __doc__, __version__, ) @@ -38,7 +39,7 @@ Belady, BeladySize, # Plugin cache - PythonHookCachePolicy, + PluginCache, ) from .trace_reader import TraceReader @@ -56,6 +57,7 @@ "SamplerType", "AnalysisParam", "AnalysisOption", + "CommonCacheParams", # Cache base class "CacheBase", # Core cache algorithms @@ -80,7 +82,7 @@ "Belady", "BeladySize", # Plugin cache - "PythonHookCachePolicy", + "PluginCache", # Readers and analyzers "TraceReader", "TraceAnalyzer", diff --git a/libcachesim/__init__.pyi b/libcachesim/__init__.pyi index 2e2a565..a855b51 100644 --- a/libcachesim/__init__.pyi +++ b/libcachesim/__init__.pyi @@ -173,7 +173,7 @@ class BeladySize(CacheBase): ): ... # Plugin cache -class PythonHookCachePolicy(CacheBase): +class PluginCache(CacheBase): def __init__( self, cache_size: int, diff --git a/libcachesim/cache.py b/libcachesim/cache.py index 3e40249..6ecfe2e 100644 --- a/libcachesim/cache.py +++ b/libcachesim/cache.py @@ -1,5 +1,5 @@ from abc import ABC -from typing import Protocol +from typing import Protocol, Callable, Optional from .libcachesim_python import ( CommonCacheParams, Request, @@ -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__( @@ -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