Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ include_directories(${MAIN_PROJECT_SOURCE_DIR}/libCacheSim/bin)
set(PYTHON_MODULE_SOURCES
src/export.cpp
src/export_cache.cpp
src/export_admissioner.cpp
src/export_reader.cpp
src/export_analyzer.cpp
src/export_misc.cpp
Expand Down
31 changes: 31 additions & 0 deletions examples/admission/bloomfilter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from libcachesim import BloomFilterAdmissioner, SyntheticReader, LRU

BloomFilter = BloomFilterAdmissioner()
lru_without_admission = LRU(
cache_size=1024,
# admissioner=BloomFilter
)
lru_with_admission = LRU(
cache_size=1024,
admissioner=BloomFilter
)

reader = SyntheticReader(
num_of_req=100_000,
num_objects=10_000,
obj_size=100,
alpha=0.8,
dist="zipf",
)

without_admission_hits = 0
with_admission_hits = 0

for req in reader:
if lru_without_admission.get(req):
without_admission_hits += 1
if lru_with_admission.get(req):
with_admission_hits += 1

print(f'Obtained {without_admission_hits} without using cache admission')
print(f'Obtained {with_admission_hits} using cache admission')
65 changes: 65 additions & 0 deletions examples/admission/plugin_admissioner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from libcachesim import PluginAdmissioner, SyntheticReader, LRU
import random

'''
A toy example where we admit ten percent of all requests
at random. The admit rate is tracked and printed in the
free hook to serve as a final sanity check.
'''


class AdmissionerStats:
admitted_requests: int = 0
total_requests: int = 0


def init_hook():
return AdmissionerStats()


def admit_hook(data, request):
admit = random.randint(1, 10) == 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using random.randint(1, 10) == 5 to achieve a 10% probability is functionally correct but can be a bit obscure. A more idiomatic and clearer way to express this probability is by using random.random() < 0.1.

Suggested change
admit = random.randint(1, 10) == 5
admit = random.random() < 0.1

if admit:
data.admitted_requests += 1
data.total_requests += 1
return admit


def clone_hook():
pass


def update_hook(data, request, cs):
pass


def free_hook(data):
print(f'Admit rate: {100 * data.admitted_requests / data.total_requests}%')


custom_admissioner = PluginAdmissioner(
"AdmitTenPercent",
init_hook,
admit_hook,
clone_hook,
update_hook,
free_hook,
)
lru_cache = LRU(
cache_size=1024,
admissioner=custom_admissioner
)

reader = SyntheticReader(
num_of_req=100_000,
num_objects=10_000,
obj_size=100,
alpha=0.8,
dist="zipf",
)

for req in reader:
lru_cache.get(req)

# Invokes free_hook, percentage should be ~10%
del lru_cache
16 changes: 16 additions & 0 deletions libcachesim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@
PluginCache,
)

from .admissioner import (
BloomFilterAdmissioner,
ProbAdmissioner,
SizeAdmissioner,
SizeProbabilisticAdmissioner,
AdaptSizeAdmissioner,
PluginAdmissioner,
)

from .trace_reader import TraceReader
from .trace_analyzer import TraceAnalyzer
from .synthetic_reader import SyntheticReader, create_zipf_requests, create_uniform_requests
Expand Down Expand Up @@ -110,6 +119,13 @@
"LRB",
# Plugin cache
"PluginCache",
# Admission algorithms
"BloomFilterAdmissioner",
"ProbAdmissioner",
"SizeAdmissioner",
"SizeProbabilisticAdmissioner",
"AdaptSizeAdmissioner",
"PluginAdmissioner",
# Readers and analyzers
"TraceReader",
"TraceAnalyzer",
Expand Down
88 changes: 88 additions & 0 deletions libcachesim/admissioner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from abc import ABC
from .libcachesim_python import (
Admissioner,
Request,
create_bloomfilter_admissioner,
create_prob_admissioner,
create_size_admissioner,
create_size_probabilistic_admissioner,
create_adaptsize_admissioner,
create_plugin_admissioner,
)


class AdmissionerBase(ABC):
_admissioner: Admissioner # Internal C++ admissioner object

def __init__(self, _admissioner: Admissioner):
self._admissioner = _admissioner

def clone(self):
return self._admissioner.clone()

def update(self, req: Request, cache_size: int):
return self._admissioner.update(req, cache_size)

def admit(self, req: Request):
return self._admissioner.admit(req)

def free(self):
return self._admissioner.free()


class BloomFilterAdmissioner(AdmissionerBase):
def __init__(self):
admissioner = create_bloomfilter_admissioner(None)
super().__init__(admissioner)


class ProbAdmissioner(AdmissionerBase):
def __init__(self, prob: float = None):
params = f"prob={prob}" if prob is not None else None
admissioner = create_prob_admissioner(params)
super().__init__(admissioner)


class SizeAdmissioner(AdmissionerBase):
def __init__(self, size_threshold: int = None):
params = f"size={size_threshold}" if size_threshold is not None else None
admissioner = create_size_admissioner(params)
super().__init__(admissioner)


class SizeProbabilisticAdmissioner(AdmissionerBase):
def __init__(self, exponent: float = None):
params = f"exponent={exponent}" if exponent is not None else None
admissioner = create_size_probabilistic_admissioner(params)
super().__init__(admissioner)


class AdaptSizeAdmissioner(AdmissionerBase):
def __init__(self, max_iteration: int = None, reconf_interval: int = None):
params = ",".join(
f'{arg}={val}' for arg, val in {
'max-iteration': max_iteration,
'reconf-interval': reconf_interval,
}.items() if val is not None
) or None

admissioner = create_adaptsize_admissioner(params)
super().__init__(admissioner)


class PluginAdmissioner(AdmissionerBase):
def __init__(self,
admissioner_name,
admissioner_init_hook,
admissioner_admit_hook,
admissioner_clone_hook,
admissioner_update_hook,
admissioner_free_hook):
admissioner = create_plugin_admissioner(
admissioner_name,
admissioner_init_hook,
admissioner_admit_hook,
admissioner_clone_hook,
admissioner_update_hook,
admissioner_free_hook)
super().__init__(admissioner)
18 changes: 14 additions & 4 deletions libcachesim/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
# Optimal algorithms
Belady_init,
BeladySize_init,
# Cache admission
Admissioner,
# Probabilistic algorithms
LRU_Prob_init,
flashProb_init,
Expand All @@ -49,7 +51,9 @@ class CacheBase(ABC):

_cache: Cache # Internal C++ cache object

def __init__(self, _cache: Cache):
def __init__(self, _cache: Cache, admissioner: Admissioner = None):
if admissioner is not None:
_cache.admissioner = admissioner._admissioner
self._cache = _cache

def get(self, req: Request) -> bool:
Expand Down Expand Up @@ -81,7 +85,7 @@ def get_occupied_byte(self) -> int:

def get_n_obj(self) -> int:
return self._cache.get_n_obj()

def set_cache_size(self, new_size: int) -> None:
self._cache.set_cache_size(new_size)

Expand Down Expand Up @@ -171,10 +175,16 @@ class LRU(CacheBase):
"""Least Recently Used cache (no special parameters)"""

def __init__(
self, cache_size: int, default_ttl: int = 86400 * 300, hashpower: int = 24, consider_obj_metadata: bool = False
self,
cache_size: int,
default_ttl: int = 86400 * 300,
hashpower: int = 24,
consider_obj_metadata: bool = False,
admissioner: Admissioner = None,
):
super().__init__(
_cache=LRU_init(_create_common_params(cache_size, default_ttl, hashpower, consider_obj_metadata))
_cache=LRU_init(_create_common_params(cache_size, default_ttl, hashpower, consider_obj_metadata)),
admissioner=admissioner
)


Expand Down
1 change: 1 addition & 0 deletions src/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ PYBIND11_MODULE(libcachesim_python, m) {
// methods if the codebase is large enough

export_cache(m);
export_admissioner(m);
export_reader(m);
export_analyzer(m);
export_misc(m);
Expand Down
1 change: 1 addition & 0 deletions src/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ using py::literals::operator""_a;
void export_cache(py::module &m);
void export_pyplugin_cache(py::module &m);

void export_admissioner(py::module &m);
void export_reader(py::module &m);
void export_analyzer(py::module &m);
void export_misc(py::module &m);
Expand Down
Loading
Loading