Skip to content

Commit f8989ab

Browse files
committed
feat: expose the cache interface
1 parent 4a576ce commit f8989ab

6 files changed

Lines changed: 216 additions & 27 deletions

File tree

libCacheSim/include/python/api.h

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,18 @@ LIBCACHESIM_C_EXPORT int LCS_Simulate(const char* trace_path, const char* trace_
3838
* \brief Create a reader from a trace file.
3939
* \param filename The name of the trace file
4040
* \param parameters Additional parameters
41-
* \param reference Used to align bin mapper with other reader, nullptr means isn't used
4241
* \param[out] out A reader
4342
* \return 0 when succeed, -1 when failure happens
4443
*/
4544
LIBCACHESIM_C_EXPORT int LCS_ReaderCreateFromFile(const char* filename, const char* parameters,
46-
const ReaderHandle reference, ReaderHandle* out);
45+
ReaderHandle* out);
46+
47+
/*!
48+
* \brief Free a reader.
49+
* \param reader The reader
50+
* \return 0 when succeed, -1 when failure happens
51+
*/
52+
LIBCACHESIM_C_EXPORT int LCS_ReaderFree(const ReaderHandle reader);
4753

4854
/*!
4955
* \brief Get the next request from the reader.
@@ -53,26 +59,41 @@ LIBCACHESIM_C_EXPORT int LCS_ReaderCreateFromFile(const char* filename, const ch
5359
*/
5460
LIBCACHESIM_C_EXPORT int LCS_ReaderGetNextRequest(const ReaderHandle reader, RequestHandle* out);
5561

62+
/*!
63+
* \brief Free a request.
64+
* \param request The request
65+
* \return 0 when succeed, -1 when failure happens
66+
*/
67+
LIBCACHESIM_C_EXPORT int LCS_RequestFree(const RequestHandle request);
68+
5669
/*!
5770
* \brief Create a cache.
71+
* \param reader The reader
5872
* \param eviction_algo The name of the eviction algorithm
59-
* \param parameters Additional parameters
60-
* \param reference Used to align bin mapper with other cache, nullptr means isn't used
73+
* \param cache_size The size of the cache
74+
* \param ignore_obj_size Whether to ignore the object size
75+
* \param eviction_parameters Additional parameters
6176
* \param[out] out A cache
6277
* \return 0 when succeed, -1 when failure happens
6378
*/
64-
LIBCACHESIM_C_EXPORT int LCS_CacheCreate(const char* eviction_algo, const char* parameters, const CacheHandle reference,
65-
CacheHandle* out);
79+
LIBCACHESIM_C_EXPORT int LCS_CacheCreate(const ReaderHandle reader, const char* eviction_algo, float cache_size, bool ignore_obj_size,
80+
const char* eviction_parameters, CacheHandle* out);
6681

67-
/*!åå
82+
/*!
83+
* \brief Free a cache.
84+
* \param cache The cache
85+
* \return 0 when succeed, -1 when failure happens
86+
*/
87+
LIBCACHESIM_C_EXPORT int LCS_CacheFree(const CacheHandle cache);
88+
89+
/*!
6890
* \brief Get a cache object.
6991
* \param cache The cache
7092
* \param request The request
71-
* \param[out] out A cache object
7293
* \param[out] hit Whether the request is hit
7394
* \return 0 when succeed, -1 when failure happens
7495
*/
75-
LIBCACHESIM_C_EXPORT int LCS_CacheGet(const CacheHandle cache, const RequestHandle request, CacheObjHandle* out,
96+
LIBCACHESIM_C_EXPORT int LCS_CacheGet(const CacheHandle cache, const RequestHandle request,
7697
bool* hit);
7798

7899
#endif // LIBCACHESIM_API_H_

libCacheSim/python/api.cpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,30 +86,43 @@ char* _extract_trace_type_str(const char* trace_path) {
8686
}
8787
}
8888

89-
int LCS_ReaderCreateFromFile(const char* filename, const char* parameters, const ReaderHandle reference,
89+
int LCS_ReaderCreateFromFile(const char* filename, const char* parameters,
9090
ReaderHandle* out) {
9191
API_BEGIN();
9292
// TODO(haocheng): add more parameters
93-
// initialize reader by reference
94-
if (reference != nullptr) {
95-
*out = reference;
96-
return 0;
97-
}
9893
// initialize reader by filename
9994
trace_type_e trace_type = trace_type_str_to_enum(_extract_trace_type_str(filename), filename);
10095
reader_t* reader = setup_reader(filename, trace_type, NULL);
101-
*out = reader;
96+
if (reader == NULL) {
97+
printf("Failed to create reader\n");
98+
}
99+
*out = (ReaderHandle)reader;
100+
API_END();
101+
}
102+
103+
int LCS_ReaderFree(const ReaderHandle reader) {
104+
API_BEGIN();
105+
close_reader(static_cast<reader_t*>(reader));
102106
API_END();
103107
}
104108

105-
RequestHandle LCS_ReaderGetNextRequest(const ReaderHandle reader) {
109+
int LCS_ReaderGetNextRequest(const ReaderHandle reader, RequestHandle* out) {
110+
API_BEGIN();
106111
request_t* request = (request_t*)malloc(sizeof(request_t));
107-
int ret = read_one_req(static_cast<reader_t*>(reader), request);
108-
return ret == 0 ? request : nullptr;
112+
int status = read_one_req(static_cast<reader_t*>(reader), request);
113+
if (status == 0) {
114+
*out = request;
115+
} else if (status == 1) {
116+
*out = NULL;
117+
} else {
118+
printf("Failed to get next request\n");
119+
return -1;
120+
}
121+
API_END();
109122
}
110123

111124
int LCS_CacheCreate(const ReaderHandle reader, const char* eviction_algo, float cache_size, bool ignore_obj_size,
112-
const char* eviction_parameters, const CacheHandle reference, CacheHandle* out) {
125+
const char* eviction_parameters, CacheHandle* out) {
113126
API_BEGIN();
114127
// TODO(haocheng): add more parameters
115128
const char* trace_path = static_cast<reader_t*>(reader)->trace_path;
@@ -120,10 +133,23 @@ int LCS_CacheCreate(const ReaderHandle reader, const char* eviction_algo, float
120133
API_END();
121134
}
122135

123-
int LCS_CacheGet(const CacheHandle cache, const RequestHandle request, CacheObjHandle* out, bool* hit) {
136+
int LCS_CacheFree(const CacheHandle cache) {
137+
API_BEGIN();
138+
cache_t* cache_ptr = static_cast<cache_t*>(cache);
139+
cache_ptr->cache_free(cache_ptr);
140+
API_END();
141+
}
142+
143+
int LCS_CacheGet(const CacheHandle cache, const RequestHandle request, bool* hit) {
124144
API_BEGIN();
125145
*hit = cache_get_base(static_cast<cache_t*>(cache), static_cast<request_t*>(request));
126-
return 0;
146+
// printf("hit from c side: %d\n", *hit);
147+
API_END();
148+
}
149+
150+
int LCS_RequestFree(const RequestHandle request) {
151+
API_BEGIN();
152+
free_request(static_cast<request_t*>(request));
127153
API_END();
128154
}
129155

python-package/example_cache.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from libcachesim import simulate, FIFO, Reader
2+
3+
reader = Reader(b"/proj/cache-PG0/haocheng/libCacheSim/data/cloudPhysicsIO.vscsi")
4+
cache = FIFO(reader, cache_size=0.1, ignore_obj_size=False)
5+
6+
hit_cnt = 0
7+
miss_cnt = 0
8+
for req in reader:
9+
hit = cache.get(req)
10+
hit_cnt += 1 if hit else 0
11+
miss_cnt += 1 if not hit else 0
12+
13+
print(hit_cnt, miss_cnt)
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from libcachesim import simulate
22

3-
req, miss = simulate(b"/proj/cache-PG0/haocheng/libCacheSim/data/cloudPhysicsIO.vscsi", b"vscsi", b"lru", 0.1)
3+
req, miss = simulate(b"/proj/cache-PG0/haocheng/libCacheSim/data/cloudPhysicsIO.vscsi", b"vscsi", b"fifo", 0.1)
44
print(req, miss)
55
print(miss / req)

python-package/libcachesim/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# .basic is intentionally loaded as early as possible, to dlopen() libcachesim.{dll,dylib,so}
1010
# and its dependencies as early as possible
11-
from .basic import simulate
11+
from .basic import simulate, FIFO, Reader, Request, Cache
1212

1313

1414
# _version_path = Path(__file__).absolute().parent / "VERSION.txt"
@@ -18,4 +18,9 @@
1818

1919
__all__ = [
2020
"simulate",
21+
"Reader",
22+
"Request",
23+
"Cache",
24+
# eviction algorithms
25+
"FIFO",
2126
]

python-package/libcachesim/basic.py

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@
44
# This import causes liblibcachesim.{dll,dylib,so} to be loaded.
55
from .libpath import _LIB
66
import ctypes
7-
from typing import Optional
7+
from typing import Optional, Union, Dict, Any
8+
from pathlib import Path
9+
10+
11+
_ReaderHandle = ctypes.c_void_p
12+
_CacheHandle = ctypes.c_void_p
13+
_ReqHandle = ctypes.c_void_p
14+
815

916
def _safe_call(ret: int) -> None:
1017
"""Check the return value from C API call.
@@ -18,7 +25,9 @@ def _safe_call(ret: int) -> None:
1825
# TODO(haocheng):add error message from C API
1926
raise Exception(f"C API call failed with error code {ret}")
2027

21-
28+
# -----------------------------------------------------------------------------
29+
# Simulation API
30+
# -----------------------------------------------------------------------------
2231
def simulate(trace_path: str, trace_type_str: str, eviction_algo: str, cache_size: float,
2332
eviction_params: Optional[str]=None, consider_obj_metadata: bool=False) -> float:
2433
"""Simulate the cache performance.
@@ -41,4 +50,119 @@ def simulate(trace_path: str, trace_type_str: str, eviction_algo: str, cache_siz
4150
consider_obj_metadata,
4251
ctypes.byref(n_req),
4352
ctypes.byref(n_miss)))
44-
return n_req.value, n_miss.value
53+
return n_req.value, n_miss.value
54+
55+
# -----------------------------------------------------------------------------
56+
# Reader API
57+
# -----------------------------------------------------------------------------
58+
class Reader:
59+
def __init__(self,
60+
trace_file: Union[str, Path],
61+
reader_params: Dict[str, Any] = None,
62+
):
63+
"""Initialize the Reader.
64+
65+
Parameters
66+
----------
67+
trace_file : str or pathlib.Path
68+
Path to the trace file.
69+
reader_params : dict
70+
Other parameters for the reader.
71+
reference : Reader
72+
Reference reader.
73+
"""
74+
self._handle = ctypes.c_void_p()
75+
# TODO(haocheng): implement reader_params and utilize reference
76+
_safe_call(_LIB.LCS_ReaderCreateFromFile(trace_file, b"",ctypes.byref(self._handle)))
77+
78+
def __del__(self) -> None:
79+
try:
80+
self._free_handle()
81+
except AttributeError:
82+
pass
83+
84+
def _free_handle(self) -> "Reader":
85+
if self._handle is not None:
86+
_safe_call(_LIB.LCS_ReaderFree(self._handle))
87+
self._handle = None
88+
return self
89+
90+
def read(self) -> "Request":
91+
"""Read a request from the reader.
92+
"""
93+
req_handle = ctypes.c_void_p()
94+
_safe_call(_LIB.LCS_ReaderGetNextRequest(self._handle, ctypes.byref(req_handle)))
95+
if not req_handle:
96+
raise StopIteration
97+
return Request(req_handle)
98+
99+
def __iter__(self):
100+
while True:
101+
try:
102+
yield self.read()
103+
except StopIteration:
104+
break
105+
106+
def __next__(self):
107+
return self.read()
108+
109+
110+
class Request:
111+
def __init__(self, handle: _ReqHandle):
112+
self._handle = handle
113+
114+
# def __del__(self) -> None:
115+
# try:
116+
# self._free_handle()
117+
# except AttributeError:
118+
# pass
119+
120+
# def _free_handle(self) -> "Request":
121+
# if self._handle is not None:
122+
# _safe_call(_LIB.LCS_RequestFree(self._handle))
123+
# self._handle = None
124+
# return self
125+
126+
# -----------------------------------------------------------------------------
127+
# Cache API
128+
# -----------------------------------------------------------------------------
129+
130+
class Cache:
131+
def __init__(self, reader: "Reader",
132+
cache_size: float=0.1,
133+
ignore_obj_size: bool=True,
134+
eviction_params: Optional[str]=None):
135+
self.reader = reader
136+
self.cache_size = cache_size
137+
self.ignore_obj_size = ignore_obj_size
138+
self.eviction_params = eviction_params
139+
self._handle = None
140+
141+
def _free_handle(self) -> "Cache":
142+
if self._handle is not None:
143+
_safe_call(_LIB.LCS_CacheFree(self._handle))
144+
self._handle = None
145+
return self
146+
147+
148+
class FIFO(Cache):
149+
def __init__(self, reader: "Reader",
150+
cache_size: float=0.1,
151+
ignore_obj_size: bool=True,
152+
eviction_params: Optional[str]=b""):
153+
super().__init__(reader, cache_size, ignore_obj_size, eviction_params)
154+
# TODO(haocheng): add more parameters and reference
155+
self._handle = ctypes.c_void_p()
156+
_safe_call(_LIB.LCS_CacheCreate(reader._handle, b"fifo", ctypes.c_float(cache_size), ignore_obj_size, eviction_params, ctypes.byref(self._handle)))
157+
158+
def get(self, request: "Request") -> bool:
159+
hit = ctypes.c_bool()
160+
_safe_call(_LIB.LCS_CacheGet(self._handle, request._handle, ctypes.byref(hit)))
161+
return hit.value
162+
163+
def __del__(self) -> None:
164+
try:
165+
self._free_handle()
166+
except AttributeError:
167+
pass
168+

0 commit comments

Comments
 (0)