Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
19 changes: 1 addition & 18 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ typedef struct reader {
size_t file_size;

trace_type_e trace_type; /* possible types see trace_type_t */
obj_id_type_e obj_id_type; /* possible types see obj_id_type_e in request.h */

size_t item_size; /* the size of one record, used to
* locate the memory location of next element,
Expand Down Expand Up @@ -53,21 +52,18 @@ typedef struct reader {
* @param trace_path
* @param trace_type CSV_TRACE, PLAIN_TXT_TRACE, BIN_TRACE, VSCSI_TRACE,
* TWR_BIN_TRACE
* @param obj_id_type OBJ_ID_NUM, OBJ_ID_STR
* @param setup_params
* @return a pointer to reader_t struct, the returned reader needs to be
* explicitly closed by calling close_reader or close_trace
*/
reader_t *setup_reader(const char *trace_path, const trace_type_e trace_type,
const obj_id_type_e obj_id_type,
const reader_init_param_t *const reader_init_param);

/* this is the same function as setup_reader */
static inline reader_t *
open_trace(const char *path, const trace_type_e type,
const obj_id_type_e obj_id_type,
const reader_init_param_t *const reader_init_param) {
return setup_reader(path, type, obj_id_type, reader_init_param);
return setup_reader(path, type, reader_init_param);
}

/**
Expand All @@ -86,15 +82,6 @@ static inline trace_type_e get_trace_type(const reader_t *const reader) {
return reader->trace_type;
}

/**
* as the name suggests
* @param reader
* @return
*/
static inline obj_id_type_e get_obj_id_type(const reader_t *const reader) {
return reader->obj_id_type;
}

/**
* read one request from reader/trace, stored the info in pre-allocated req
* @param reader
Expand Down Expand Up @@ -159,7 +146,3 @@ simulate_at_multi_sizes_with_step_size(reader_t *const reader_in,


profiler:




128 changes: 61 additions & 67 deletions doc/advanced_lib.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# libCacheSim library user guide
libCacheSim is a library to build fast cache simulators.
# libCacheSim library user guide
libCacheSim is a library to build fast cache simulators.
With its high-throughput, low-footprint, flexible API design, libCacheSim can simulate large caches within seconds to minutes.
Some example usages of libCacheSim
* design/compare cache admission/eviction algorithms.
Some example usages of libCacheSim
* design/compare cache admission/eviction algorithms.
* design/compare trace sampling techniques.
* simulate a complex cache hierarchy and topology.
For example, build a cache hierarchy with multiple layers to study the impact of exclusive and inclusive caching; or build a cache cluster with consistent hashing to explore the different load balancing techniques on caching.
* simulate a complex cache hierarchy and topology.
For example, build a cache hierarchy with multiple layers to study the impact of exclusive and inclusive caching; or build a cache cluster with consistent hashing to explore the different load balancing techniques on caching.


---

## libCacheSim Modules
Currently there are four main modules in libCacheSim,
## libCacheSim Modules
Currently there are four main modules in libCacheSim,
* **bin**: a set of binary tools including cachesim, traceConv, etc.
* **traceReader**: a module providing trace parsing and reading, currently supports csv, txt, and binary traces.
* **cache**: it includes three modules --- eviction, admission and prefetching.
* **eviction**: provides a set of cache eviction algorithms such as LRU, LFU, FIFO, CLOCK, ARC, LFUDA (LFU with dynamic aging), SLRU, Hyperbolic, LHD, LeCaR, Cacheus, GLCache, etc.
* **traceReader**: a module providing trace parsing and reading, currently supports csv, txt, and binary traces.
* **cache**: it includes three modules --- eviction, admission and prefetching.
* **eviction**: provides a set of cache eviction algorithms such as LRU, LFU, FIFO, CLOCK, ARC, LFUDA (LFU with dynamic aging), SLRU, Hyperbolic, LHD, LeCaR, Cacheus, GLCache, etc.
* **admission**: provides a set of admission algorithms including size, bloomFilter, adaptSize.
* **prefetch**: provides various prefetch algorithms, currently it is not used.
* **prefetch**: provides various prefetch algorithms, currently it is not used.

---

Expand All @@ -37,9 +37,9 @@ bool LRU_remove(cache_t *cache, const obj_id_t obj_id);
```

#### Create Cache
We can create a cache by calling the cache initialization function, such as for LRU
We can create a cache by calling the cache initialization function, such as for LRU
```c
cache_t *cache = LRU_init(common_cache_params, NULL);
cache_t *cache = LRU_init(common_cache_params, NULL);
```
The common_cache_params is a `common_cache_params_t` struct, the hashpower is the estimated size of hash table, default is 24, which means default hash table size is `1 << 24` (16777216) objects. Note that setting an appropriate
```c
Expand All @@ -49,7 +49,7 @@ typedef struct {
int hashpower;
} common_cache_params_t;
```
Note that setting an appropriate hashpower can reduce the number of times hash table expands, but only set it if you know what you doing, otherwise, leave it as the default.
Note that setting an appropriate hashpower can reduce the number of times hash table expands, but only set it if you know what you doing, otherwise, leave it as the default.

#### Close/free the cache
```c
Expand All @@ -58,7 +58,7 @@ cache->cache_free(cache);
```

#### Cache get
This is the highest level cache API, which tries to find the object in the cache. If found, it updates the cache state (e.g., moving the object to the head of queue in LRU); otherwise, it inserts the object in the cache, and evict if necessary.
This is the highest level cache API, which tries to find the object in the cache. If found, it updates the cache state (e.g., moving the object to the head of queue in LRU); otherwise, it inserts the object in the cache, and evict if necessary.
```c
// req is the request, see the next section for reading from a trace
cache->get(cache, req);
Expand All @@ -67,30 +67,30 @@ cache->get(cache, req);
The APIs below is lower level API, if you use the lower level API, you need to explicitly update the `n_req` field of the cache after each user request, otherwise, some algorithms that rely on virtual time may not work correctly.

#### Cache find
This is the lower level cache API, which tries to find the object in the cache. If found, it updates the cache state if `update_cache` is true, and return the found object; otherwise, it returns NULL.
This is the lower level cache API, which tries to find the object in the cache. If found, it updates the cache state if `update_cache` is true, and return the found object; otherwise, it returns NULL.
```c
cache->find(cache, req, update_cache);
```

#### Cache insert
This is the lower level cache API, which tries to insert the object in the cache. If the object can be inserted into the cache, it returns the inserted object. Otherwise, it returns NULL.
This is the lower level cache API, which tries to insert the object in the cache. If the object can be inserted into the cache, it returns the inserted object. Otherwise, it returns NULL.

Note that there are cases that the object is not inserted into the cache, e.g., the object is too large to fit in the cache.
Note that there are cases that the object is not inserted into the cache, e.g., the object is too large to fit in the cache.

Because this is the second level API, this function does not perform eviction and assumes the cache has enough space.
If using this function, you need to explicitly call `evict` to evict objects.
Because this is the second level API, this function does not perform eviction and assumes the cache has enough space.
If using this function, you need to explicitly call `evict` to evict objects.
```c
cache->insert(cache, req);
```

#### Cache evict
This is the lower level cache API, which tries to evict the object in the cache. If the object can be evicted from the cache, it returns the evicted object. Otherwise, it returns NULL.
This is the lower level cache API, which tries to evict the object in the cache. If the object can be evicted from the cache, it returns the evicted object. Otherwise, it returns NULL.
```c
cache->evict(cache, req);
```

#### Cache remove
This is the lower level cache API, which tries to remove the object in the cache. If the object is in the cache and can be removed, it returns true. Otherwise, it returns false.
This is the lower level cache API, which tries to remove the object in the cache. If the object is in the cache and can be removed, it returns true. Otherwise, it returns false.
Note that this function should not be used for eviction purpose.
```c
cache->remove(cache, obj_id);
Expand All @@ -105,75 +105,73 @@ cache->to_evict(cache, req);

### TraceReader APIs
There are mostly three APIs related to readers, `open_trace`, `close_trace`, `read_one_req`, let's take a look how
they work.
they work.

##### Setup a txt reader (trace can only contain request id)
```c
open_trace(data_path, PLAIN_TXT_TRACE, obj_id_type, NULL);
open_trace(data_path, PLAIN_TXT_TRACE, NULL);
```
obj_id_type can be `OBJ_ID_NUM` or `OBJ_ID_STR`, if the object id is a number then use `OBJ_ID_NUM`, otherwise use
`OBJ_ID_STR`.

##### Setup a csv reader

##### Setup a csv reader
```c
reader_init_param_t init_params_csv =
{.delimiter=',', .time_field=2, .obj_id_field=6, .obj_size_field=4, .has_header=FALSE};
reader_t *reader_csv_c = open_trace("data/trace.csv", CSV_TRACE, OBJ_ID_STR, &init_params_csv);
reader_init_param_t init_params_csv =
{.delimiter=',', .time_field=2, .obj_id_field=6, .obj_size_field=4, .has_header=FALSE};
reader_t *reader_csv_c = open_trace("data/trace.csv", CSV_TRACE, &init_params_csv);
```

##### Setup a binary reader
##### Setup a binary reader
```c
reader_init_param_t init_params_bin = {.binary_fmt="<3I2H2Q", .obj_size_field=2, .obj_id_field=6, };
reader_t *reader_bin_l = setup_reader("data/trace.vscsi", BIN_TRACE, OBJ_ID_NUM, &init_params_bin);
reader_t *reader_bin_l = setup_reader("data/trace.vscsi", BIN_TRACE, &init_params_bin);
```
The format of a binary trace is the same as
[Python struct format specifier](https://docs.python.org/3/library/struct.html).
The format of a binary trace is the same as
[Python struct format specifier](https://docs.python.org/3/library/struct.html).




### Simulator APIs
The simulator API allows you to run multiple simulations at the same time.
### Simulator APIs
The simulator API allows you to run multiple simulations at the same time.
The different simulations can have different cache sizes or different cache eviction algorithms.

```c
// simulate multiple cache sizes specified using cache_sizes
// warmup_reader and warmup_perc is optional, if you do not need to warmup your cache, just pass `NULL` and 0.
// warmup_reader and warmup_perc is optional, if you do not need to warmup your cache, just pass `NULL` and 0.
sim_res_t *
simulate_at_multi_sizes(reader_t reader*,
cache_t *cache,
int num_of_sizes,
simulate_at_multi_sizes(reader_t reader*,
cache_t *cache,
int num_of_sizes,
uint64_t *cache_sizes,
reader_t *warmup_reader,
double warmup_perc,
reader_t *warmup_reader,
double warmup_perc,
int num_of_threads);

// simulate multiple cache sizes from step_size to cache->cache_size
// it runs cache->cache_size/step_size simulations
sim_res_t *
simulate_at_multi_sizes_with_step_size(reader_t *reader,
cache_t *cache,
uint64_t step_size,
reader_t *warmup_reader,
double warmup_perc,
simulate_at_multi_sizes_with_step_size(reader_t *reader,
cache_t *cache,
uint64_t step_size,
reader_t *warmup_reader,
double warmup_perc,
int num_of_threads);

// simulate with multiple caches, which can have different eviction algorithms or sizes
cache_stat_t *simulate_with_multi_caches(reader_t *reader,
cache_stat_t *simulate_with_multi_caches(reader_t *reader,
cache_t *caches[],
int num_of_caches,
reader_t *warmup_reader,
double warmup_frac,
double warmup_frac,
int warmup_sec,
int num_of_threads)
```

`simulate_at_multi_sizes` allows you to pass in an array of `cache_sizes` to simulate;
`simulate_at_multi_sizes` allows you to pass in an array of `cache_sizes` to simulate;
`simulate_at_multi_sizes_with_step_size` allows you to specify the step size to simulate, the simulations will run at
cache sizes `step_size, step_size*2, step_size*3 .. cache->cache_size`.
cache sizes `step_size, step_size*2, step_size*3 .. cache->cache_size`.
`simulate_with_multi_caches` allows you to pass in an array of `cache_t` to simulate, which can have different eviction algorithms or sizes.

The return result is an array of simulation results, the users are responsible for free the array.
The return result is an array of simulation results, the users are responsible for free the array.
```c
typedef struct {
uint64_t req_cnt;
Expand All @@ -187,27 +185,27 @@ typedef struct {
```


### Trace utils
#### get reuse/stack distance
### Trace utils
#### get reuse/stack distance
```c
// get the stack distance (number of uniq objects) since last access or till next request
// reader: trace reader
// dist_type: STACK_DIST or FUTURE_STACK_DIST
// return an array of int32_t with size written in array_size
int32_t *get_stack_dist(reader_t *reader,
int32_t *get_stack_dist(reader_t *reader,
const dist_type_e dist_type,
int64_t *array_size);

// get the distance (number of requests) since last/first access
// reader: trace reader
// dist_type DIST_SINCE_LAST_ACCESS or DIST_SINCE_FIRST_ACCESS
// return an array of int32_t with size written in array_size
int32_t *get_access_dist(reader_t *reader,
int32_t *get_access_dist(reader_t *reader,
const dist_type_e dist_type,
int64_t *array_size);
```

## Examples
## Examples
#### C example


Expand All @@ -220,10 +218,10 @@ int32_t *get_access_dist(reader_t *reader,
### Build a cache cluster with consistent hashing


## FAQ
## FAQ
#### Linking with libCacheSim
linking can be done in cmake or use pkg-config
Such as in the `_build` directory:
linking can be done in cmake or use pkg-config
Such as in the `_build` directory:
```
export PKG_CONFIG_PATH=$PWD
```
Expand All @@ -234,7 +232,3 @@ export PKG_CONFIG_PATH=$PWD


---




2 changes: 1 addition & 1 deletion libCacheSim/bin/customized/fast23/compareGrouping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ void compareGrouping::cal_group_metric_utility(string trace_path,
vector<int> &group_sizes,
int n_repeat, int n_thread) {
reader_t *reader =
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, OBJ_ID_NUM, nullptr);
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, nullptr);
request_t *req = new_request();
int64_t n_total_req = get_num_of_req(reader);
int64_t n_skip = n_total_req / 10;
Expand Down
2 changes: 1 addition & 1 deletion libCacheSim/bin/customized/fast23/compareGroups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void compareGroups::cal_group_metric_utility_over_time(string trace_path,
string ofilepath,
int group_size) {
reader_t *reader =
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, OBJ_ID_NUM, nullptr);
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, nullptr);
request_t *req = new_request();
int64_t n_skip = 0;
int64_t n_req = n_skip;
Expand Down
4 changes: 2 additions & 2 deletions libCacheSim/bin/customized/fast23/objectInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct map_val {
std::vector<fast23::obj_reuse_stat> objectInfo::compute_obj_reuse_stat(
std::string trace_path) {
reader_t *reader =
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, OBJ_ID_NUM, nullptr);
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, nullptr);
request_t *req = new_request();
int64_t n_req = 0;
unordered_map<uint64_t, shared_ptr<struct map_val>> objmap;
Expand Down Expand Up @@ -93,7 +93,7 @@ int64_t objectInfo::convert_trace_to_requests(
std::string trace_path, fast23::request_info *request_info,
int64_t request_info_size, int64_t n_skip) {
reader_t *reader =
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, OBJ_ID_NUM, nullptr);
open_trace(trace_path.c_str(), ORACLE_GENERAL_BIN, nullptr);
request_t *req = new_request();
int64_t n_req = n_skip;

Expand Down
2 changes: 1 addition & 1 deletion libCacheSim/include/libCacheSim/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ extern "C" {
*
* @param cache_alg_name Name of the cache replacement algorithm (case
* sensitive)
* @param cc_params General cache parameters (cache_size, obj_id_type,
* @param cc_params General cache parameters (cache_size,
* support_ttl, etc.)
* @param cache_specific_params Algorithm-specific parameters (can be NULL)
* @return Pointer to initialized cache handler, or NULL on failure
Expand Down
3 changes: 0 additions & 3 deletions libCacheSim/include/libCacheSim/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,6 @@ static inline reader_init_param_t default_reader_init_params(void) {
* @param trace_path path to the trace
* @param trace_type CSV_TRACE, PLAIN_TXT_TRACE, BIN_TRACE, VSCSI_TRACE,
* TWR_BIN_TRACE, see libCacheSim/enum.h for more
* @param obj_id_type OBJ_ID_NUM, OBJ_ID_STR,
* used by CSV_TRACE and PLAIN_TXT_TRACE, whether the obj_id in the trace is a
* number or not, if it is not a number then we will map it to uint64_t
* @param reader_init_param some initialization parameters used by csv and
* binary traces these include time_field, obj_id_field, obj_size_field,
* op_field, ttl_field, has_header, delimiter, binary_fmt_str
Expand Down
2 changes: 1 addition & 1 deletion libCacheSim/traceReader/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ int read_one_req(reader_t *const reader, request_t *const req) {
break;
default:
ERROR(
"cannot recognize reader obj_id_type, given reader obj_id_type: "
"cannot recognize reader trace_type, given reader trace_type: "
"%c\n",
reader->trace_type);
abort();
Expand Down
Loading