Skip to content

Commit fae43ce

Browse files
authored
[Feat] Support LHD (#38)
* Support LHD * Fix with chatbot suggestion
1 parent 36f4bf9 commit fae43ce

File tree

8 files changed

+43
-384
lines changed

8 files changed

+43
-384
lines changed

examples/basic_usage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@
3030
move_to_main_threshold=2,
3131
)
3232
req_miss_ratio, byte_miss_ratio = cache.process_trace(reader, start_req=0, max_req=1000)
33-
print(f"Request miss ratio: {req_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}")
33+
print(f"Request miss ratio: {req_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}")

libcachesim/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .cache import (
2020
CacheBase,
2121
# Core algorithms
22+
LHD,
2223
LRU,
2324
FIFO,
2425
LFU,
@@ -74,6 +75,7 @@
7475
# Cache base class
7576
"CacheBase",
7677
# Core cache algorithms
78+
"LHD",
7779
"LRU",
7880
"FIFO",
7981
"LFU",

libcachesim/cache.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
CacheObject,
77
Cache,
88
# Core cache algorithms
9+
LHD_init,
910
LRU_init,
1011
FIFO_init,
1112
LFU_init,
@@ -152,6 +153,17 @@ def _create_common_params(
152153
# ------------------------------------------------------------------------------------------------
153154
# Core cache algorithms
154155
# ------------------------------------------------------------------------------------------------
156+
class LHD(CacheBase):
157+
"""Least Hit Density cache (no special parameters)"""
158+
159+
def __init__(
160+
self, cache_size: int, default_ttl: int = 86400 * 300, hashpower: int = 24, consider_obj_metadata: bool = False
161+
):
162+
super().__init__(
163+
_cache=LHD_init(_create_common_params(cache_size, default_ttl, hashpower, consider_obj_metadata))
164+
)
165+
166+
155167
class LRU(CacheBase):
156168
"""Least Recently Used cache (no special parameters)"""
157169

scripts/smart_build.py

Lines changed: 0 additions & 126 deletions
This file was deleted.

src/export_cache.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ namespace libcachesim {
2828

2929
namespace py = pybind11;
3030

31+
const cache_obj_t* LHD_HIT_MARKER = reinterpret_cast<cache_obj_t *>(0x1);
32+
3133
// Custom deleters for smart pointers
3234
struct CacheDeleter {
3335
void operator()(cache_t* ptr) const {
@@ -279,9 +281,20 @@ void export_cache(py::module& m) {
279281
"req"_a)
280282
.def(
281283
"find",
282-
[](cache_t& self, const request_t& req, const bool update_cache) {
284+
[](cache_t& self, const request_t& req, const bool update_cache) -> py::object {
283285
cache_obj_t* obj = self.find(&self, &req, update_cache);
284-
return obj ? py::cast(obj, py::return_value_policy::reference) : py::none();
286+
// Return None if obj is null (not found)
287+
if (obj == nullptr) {
288+
return py::none();
289+
}
290+
// NOTE(haocheng): For LHD only, return a dummy object for hit
291+
if (obj == LHD_HIT_MARKER) {
292+
cache_obj_t* dummy_obj = static_cast<cache_obj_t*>(calloc(1, sizeof(cache_obj_t)));
293+
dummy_obj->obj_id = req.obj_id;
294+
dummy_obj->obj_size = req.obj_size;
295+
return py::cast(std::unique_ptr<cache_obj_t, CacheObjectDeleter>(dummy_obj));
296+
}
297+
return py::cast(obj, py::return_value_policy::reference);
285298
},
286299
"req"_a, "update_cache"_a = true)
287300
.def(

tests/test_cache.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import os
1010
from libcachesim import (
1111
# Basic algorithms
12+
LHD,
1213
LRU,
1314
FIFO,
1415
LFU,
@@ -71,6 +72,7 @@ class TestCacheBasicFunctionality:
7172
@pytest.mark.parametrize(
7273
"cache_class",
7374
[
75+
LHD,
7476
LRU,
7577
FIFO,
7678
LFU,
@@ -109,10 +111,14 @@ def test_cache_initialization(self, cache_class):
109111
pytest.skip(f"Cache {cache_class.__name__} failed to initialize: {e}")
110112

111113
@pytest.mark.parametrize(
112-
"cache_class", [LRU, FIFO, LFU, ARC, Clock, Random, S3FIFO, Sieve, LIRS, TwoQ, SLRU, WTinyLFU]
114+
"cache_class", [LHD, LRU, FIFO, LFU, ARC, Clock, Random, S3FIFO, Sieve, LIRS, TwoQ, SLRU, WTinyLFU]
113115
)
114116
def test_basic_get_and_insert(self, cache_class):
115117
"""Test basic get and insert operations"""
118+
if cache_class == LHD:
119+
pytest.skip("LHD's insert always returns None")
120+
121+
116122
cache = cache_class(1024 * 1024) # 1MB cache
117123

118124
# Create a request
@@ -141,6 +147,7 @@ def test_basic_get_and_insert(self, cache_class):
141147
@pytest.mark.parametrize(
142148
"cache_class",
143149
[
150+
LHD,
144151
LRU,
145152
FIFO,
146153
LFU,
@@ -192,6 +199,7 @@ def test_cache_eviction(self, cache_class):
192199
@pytest.mark.parametrize(
193200
"cache_class",
194201
[
202+
LHD,
195203
LRU,
196204
FIFO,
197205
LFU,
@@ -239,6 +247,7 @@ def test_cache_find_method(self, cache_class):
239247
@pytest.mark.parametrize(
240248
"cache_class",
241249
[
250+
LHD,
242251
LRU,
243252
FIFO,
244253
LFU,

0 commit comments

Comments
 (0)