Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,30 @@ reader = lcs.TraceReader(
)

# Step 2: Initialize cache
# Note: cache_size as float (0.1) means 10% of the reader's total working set size in bytes.
# To specify an absolute size, pass an integer (e.g., 1024*1024 for 1MB).
cache = lcs.S3FIFO(
Comment thread
haochengxia marked this conversation as resolved.
cache_size=1024*1024,
cache_size=0.1, # 0.1 = 10% of trace's working set size (requires reader parameter)
# Cache specific parameters
small_size_ratio=0.2,
ghost_size_ratio=0.8,
move_to_main_threshold=2,
reader=reader, # Required when cache_size is a float ratio
)

# Step 3: Process entire trace efficiently (C++ backend)
req_miss_ratio, byte_miss_ratio = cache.process_trace(reader)
print(f"Request miss ratio: {req_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}")

# Step 3.1: Process the first 1000 requests
# Note: cache_size as float means a ratio of the working set size (requires reader parameter)
cache = lcs.S3FIFO(
cache_size=1024 * 1024,
cache_size=0.1, # 10% of trace's working set size
# Cache specific parameters
small_size_ratio=0.2,
ghost_size_ratio=0.8,
move_to_main_threshold=2,
reader=reader, # Required when cache_size is a float ratio
)
req_miss_ratio, byte_miss_ratio = cache.process_trace(reader, start_req=0, max_req=1000)
print(f"Request miss ratio: {req_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}")
Expand Down
216 changes: 190 additions & 26 deletions libcachesim/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import annotations
from typing import bool, int, str, tuple
from typing import Optional, Callable, Any
from collections.abc import Iterator

from .libcachesim_python import ReqOp, TraceType, SamplerType
Expand Down Expand Up @@ -38,6 +38,85 @@ class CommonCacheParams:
hashpower: int
consider_obj_metadata: bool

class ReaderInitParam:
ignore_obj_size: bool
ignore_size_zero_req: bool
obj_id_is_num: bool
obj_id_is_num_set: bool
cap_at_n_req: int
time_field: int
obj_id_field: int
obj_size_field: int
op_field: int
ttl_field: int
cnt_field: int
tenant_field: int
next_access_vtime_field: int
n_feature_fields: int
block_size: int
has_header: bool
has_header_set: bool
delimiter: str
trace_start_offset: int
binary_fmt_str: str
def __init__(
self,
binary_fmt_str: str = "",
ignore_obj_size: bool = False,
ignore_size_zero_req: bool = True,
obj_id_is_num: bool = True,
obj_id_is_num_set: bool = False,
cap_at_n_req: int = -1,
block_size: int = -1,
has_header: bool = False,
has_header_set: bool = False,
delimiter: str = ",",
trace_start_offset: int = 0,
sampler: Optional[Any] = None,
): ...

class AnalysisParam:
access_pattern_sample_ratio_inv: int
track_n_popular: int
track_n_hit: int
time_window: int
warmup_time: int
def __init__(
self,
access_pattern_sample_ratio_inv: int = 10,
track_n_popular: int = 10,
track_n_hit: int = 5,
time_window: int = 60,
warmup_time: int = 0,
): ...

class AnalysisOption:
req_rate: bool
access_pattern: bool
size: bool
reuse: bool
popularity: bool
ttl: bool
popularity_decay: bool
lifetime: bool
create_future_reuse_ccdf: bool
prob_at_age: bool
size_change: bool
def __init__(
self,
req_rate: bool = True,
access_pattern: bool = True,
size: bool = True,
reuse: bool = True,
popularity: bool = True,
ttl: bool = False,
popularity_decay: bool = False,
lifetime: bool = False,
create_future_reuse_ccdf: bool = False,
prob_at_age: bool = False,
size_change: bool = False,
): ...

class Cache:
cache_size: int
default_ttl: int
Expand Down Expand Up @@ -80,113 +159,164 @@ class CacheBase:
def cache_name(self) -> str: ...

# Core cache algorithms
class LHD(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class LRU(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class FIFO(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class LFU(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class ARC(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class Clock(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, init_freq: int = 0, n_bit_counter: int = 1, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class Random(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Advanced algorithms
class S3FIFO(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, small_size_ratio: float = 0.1, ghost_size_ratio: float = 0.9, move_to_main_threshold: int = 2, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class Sieve(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class LIRS(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class TwoQ(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, a_in_size_ratio: float = 0.25, a_out_size_ratio: float = 0.5, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class SLRU(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class WTinyLFU(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, main_cache: str = "SLRU", window_size: float = 0.01, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class LeCaR(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, update_weight: bool = True, lru_weight: float = 0.5, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class LFUDA(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class ClockPro(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, init_ref: int = 0, init_ratio_cold: float = 0.5, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class Cacheus(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Optimal algorithms
class Belady(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class BeladySize(CacheBase):
def __init__(
self, cache_size: int, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, n_samples: int = 128, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Probabilistic algorithms
class LRUProb(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, prob: float = 0.5, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class FlashProb(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, ram_size_ratio: float = 0.05, disk_admit_prob: float = 0.2, ram_cache: str = "LRU", disk_cache: str = "FIFO", admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Size-based algorithms
class Size(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class GDSF(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Hyperbolic algorithms
class Hyperbolic(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Extra deps
class ThreeLCache(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, objective: str = "byte-miss-ratio", admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class GLCache(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, segment_size: int = 100, n_merge: int = 2, type: str = "learned", rank_intvl: float = 0.02, merge_consecutive_segs: bool = True, train_source_y: str = "online", retrain_intvl: int = 86400, admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

class LRB(CacheBase):
def __init__(
self, cache_size: int | float, default_ttl: int = 25920000, hashpower: int = 24, consider_obj_metadata: bool = False, objective: str = "byte-miss-ratio", admissioner: Optional["AdmissionerBase"] = None, reader: Optional[ReaderProtocol] = None
): ...

# Plugin cache
class PluginCache(CacheBase):
def __init__(
self,
cache_size: int,
cache_size: int | float,
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 = 25920000,
hashpower: int = 24,
consider_obj_metadata: bool = False,
cache_init_hook=None,
cache_hit_hook=None,
cache_miss_hook=None,
cache_eviction_hook=None,
cache_remove_hook=None,
cache_free_hook=None,
admissioner: Optional["AdmissionerBase"] = None,
reader: Optional[ReaderProtocol] = None,
): ...
def set_hooks(self, init_hook, hit_hook, miss_hook, eviction_hook, remove_hook, free_hook=None): ...

Expand Down Expand Up @@ -246,3 +376,37 @@ class Util:
def process_trace(
cache: CacheBase, reader: ReaderProtocol, start_req: int = 0, max_req: int = -1
) -> tuple[float, float]: ...

# Admissioners
class AdmissionerBase:
def __init__(self, _admissioner): ...
def clone(self): ...
def update(self, req: Request, cache_size: int): ...
def admit(self, req: Request) -> bool: ...
def free(self): ...

class BloomFilterAdmissioner(AdmissionerBase):
def __init__(self): ...

class ProbAdmissioner(AdmissionerBase):
def __init__(self, prob: Optional[float] = None): ...

class SizeAdmissioner(AdmissionerBase):
def __init__(self, size_threshold: Optional[int] = None): ...

class SizeProbabilisticAdmissioner(AdmissionerBase):
def __init__(self, exponent: Optional[float] = None): ...

class AdaptSizeAdmissioner(AdmissionerBase):
def __init__(self, max_iteration: Optional[int] = None, reconf_interval: Optional[int] = None): ...

class PluginAdmissioner(AdmissionerBase):
def __init__(
self,
admissioner_name: str,
admissioner_init_hook: Callable,
admissioner_admit_hook: Callable,
admissioner_clone_hook: Callable,
admissioner_update_hook: Callable,
admissioner_free_hook: Callable,
): ...
Loading
Loading