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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ See [libCacheSim-node](/libCacheSim-node/) for the full API and the bundled `cac
The name in `code` is what you pass to `cachesim` (names are case-insensitive).

### Eviction algorithms
* [FIFO](/libCacheSim/cache/eviction/FIFO.c) `fifo`, [LRU](/libCacheSim/cache/eviction/LRU.c) `lru`, [Clock](/libCacheSim/cache/eviction/Clock.c) `clock`, [SLRU](/libCacheSim/cache/eviction/SLRU.c) `slru`, [Random](/libCacheSim/cache/eviction/Random.c) `random`, [RandomTwo](/libCacheSim/cache/eviction/RandomTwo.c) `randomtwo`
* [FIFO](/libCacheSim/cache/eviction/FIFO.c) `fifo`, [LRU](/libCacheSim/cache/eviction/LRU.c) `lru`, [MRU](/libCacheSim/cache/eviction/MRU.c) `mru`, [Clock](/libCacheSim/cache/eviction/Clock.c) `clock`, [SLRU](/libCacheSim/cache/eviction/SLRU.c) `slru`, [Random](/libCacheSim/cache/eviction/Random.c) `random`, [RandomTwo](/libCacheSim/cache/eviction/RandomTwo.c) `randomtwo`
* [LFU](/libCacheSim/cache/eviction/LFU.c) `lfu`, [LFU with dynamic aging](/libCacheSim/cache/eviction/LFUDA.c) `lfuda`
* [ARC](/libCacheSim/cache/eviction/ARC.c) `arc`, [TwoQ](/libCacheSim/cache/eviction/TwoQ.c) `2q`, [MQ](/libCacheSim/cache/eviction/MQ.c) `mq`, [CLOCK-PRO](/libCacheSim/cache/eviction/ClockPro.c) `clockpro`, [CAR](/libCacheSim/cache/eviction/CAR.c) `car`, [LIRS](/libCacheSim/cache/eviction/LIRS.c) `lirs`, [Clock2QPlus](/libCacheSim/cache/eviction/Clock2QPlus.c) `clock2qplus`
* [LRU-K](/libCacheSim/cache/eviction/cpp/LRU_K.cpp) `lru-k`, [LRU-Prob](/libCacheSim/cache/eviction/LRUProb.c) `lru-prob`, [Size](/libCacheSim/cache/eviction/Size.c) `size`
Expand Down
2 changes: 1 addition & 1 deletion doc/advanced_lib_extend.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Then wire it in. Using `myCache` as the example name:
2. **Add per-object metadata, if you need it.** Add a struct for it to the union in [include/libCacheSim/cacheObj.h](/libCacheSim/include/libCacheSim/cacheObj.h).
3. **Declare the constructor.** Add `myCache_init()` to [include/libCacheSim/evictionAlgo.h](/libCacheSim/include/libCacheSim/evictionAlgo.h).
4. **Compile it.** Add `eviction/myCache.c` to [cache/CMakeLists.txt](/libCacheSim/cache/CMakeLists.txt).
5. **Give it a name.** Add `{"mycache", myCache_init}` to the table in [cache/cacheAlgoRegistry.c](/libCacheSim/cache/cacheAlgoRegistry.c). The table is alphabetical. This one entry makes the algorithm available to `cachesim`, to the MINISIM mode of `mrcProfiler`, and to `create_cache_by_name()`.
5. **Give it a name.** Add `{"mycache", myCache_init}` to the table in [cache/cacheAlgoRegistry.c](/libCacheSim/cache/cacheAlgoRegistry.c). The table is alphabetical. This one entry makes the algorithm available to `cachesim`, to the MINISIM mode of `mrcProfiler`, and to `create_cache_by_name()`. Names are matched case-insensitively, so users can type `mycache` or `myCache`. Only an algorithm that needs more than a lookup, such as a smaller hash table or a check that the trace carries future access times, also needs a branch in [bin/cachesim/cache_init.h](/libCacheSim/bin/cachesim/cache_init.h).
6. **Test and document it.** Add a test to [test/test_evictionAlgo.c](/test/test_evictionAlgo.c), and list the algorithm in the [README](/README.md#supported-algorithms) with the name users type. If it takes `-e` parameters, add a case to the `testCLI` target too, as described in [CONTRIBUTING.md](/CONTRIBUTING.md#testing).

Then rebuild and try it:
Expand Down
2 changes: 1 addition & 1 deletion doc/quickstart_mrcProfiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Each row is one cache size. When you give sizes as fractions, the first column i

| Option | Meaning |
| --- | --- |
| `--algo` | Eviction algorithm. SHARDS only supports `LRU`. MINISIM accepts any name `cachesim` accepts. |
| `--algo` | Eviction algorithm, case-insensitive (`fifo` and `FIFO` are the same). SHARDS only supports `LRU`. MINISIM accepts any name `cachesim` accepts. |
| `--profiler` | `SHARDS` or `MINISIM` |
| `--profiler-params` | See [Profiler parameters](#profiler-parameters) |
| `--size` | See [Choose the cache sizes](#choose-the-cache-sizes) |
Expand Down
10 changes: 5 additions & 5 deletions libCacheSim/bin/mrcProfiler/cli_parser.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <argp.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>

#include <string>
#include <vector>
Expand Down Expand Up @@ -370,10 +371,10 @@ void mrc_profiler_params_parse(const char *cache_algorithm_str,
mrcProfiler::mrc_profiler_e &profiler_type,
mrcProfiler::mrc_profiler_params_t &params) {
// initial the params of mrc profiler
if (strcmp(profiler_str, "SHARDS") == 0 ||
strcmp(profiler_str, "shards") == 0) {
// names are case-insensitive, the same as cachesim and the MINISIM registry
if (strcasecmp(profiler_str, "SHARDS") == 0) {
profiler_type = mrcProfiler::SHARDS_PROFILER;
if (strcmp(cache_algorithm_str, "LRU")) {
if (strcasecmp(cache_algorithm_str, "LRU") != 0) {
ERROR("cache algorithm must be LRU for SHARDS\n")
exit(1);
}
Expand All @@ -382,8 +383,7 @@ void mrc_profiler_params_parse(const char *cache_algorithm_str,

// init shards params
params.shards_params.parse_params(params_str);
} else if (strcmp(profiler_str, "MINISIM") == 0 ||
strcmp(profiler_str, "minisim") == 0) {
} else if (strcasecmp(profiler_str, "MINISIM") == 0) {
profiler_type = mrcProfiler::MINISIM_PROFILER;

params.cache_algorithm_str = (char *)cache_algorithm_str;
Expand Down
5 changes: 5 additions & 0 deletions libCacheSim/cache/cacheAlgoRegistry.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ static const cache_algo_entry_t g_cache_algos[] = {
{"lru", LRU_init},
{"lru-k", LRU_K_init},
{"lru-prob", LRU_Prob_init},
/* lruv0 is deliberately absent. LRUv0 is the older GLib-based LRU and keeps
* its own hash table, so it bypasses the shared find, insert and evict
* paths that implement TTL expiry, admission and the prefetcher callbacks.
* Naming it here would let the CLI silently ignore those options. */
{"merlin", merlin_init},
{"mq", MQ_init},
{"mru", MRU_init},
Comment thread
1a1a11a marked this conversation as resolved.
Resolved
{"multiqueue", MQ_init},
{"nop", nop_init},
/* plugin cache that allows user to implement custom cache */
Expand Down
10 changes: 8 additions & 2 deletions libCacheSim/cache/eviction/MRU.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,14 @@ static cache_obj_t *MRU_to_evict(cache_t *cache, const request_t *req) {
static void MRU_evict(cache_t *cache, const request_t *req) {
MRU_params_t *params = (MRU_params_t *)cache->eviction_params;
cache_obj_t *obj_to_evict = MRU_to_evict(cache, req);
params->q_head = params->q_head->queue.next;
params->q_head->queue.prev = NULL;
DEBUG_ASSERT(obj_to_evict != NULL);
params->q_head = obj_to_evict->queue.next;
if (likely(params->q_head != NULL)) {
params->q_head->queue.prev = NULL;
} else {
/* that was the only object, so the queue is now empty */
params->q_tail = NULL;
}
cache_evict_base(cache, obj_to_evict, true);
}

Expand Down
1 change: 1 addition & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ python3 plot_mrc_time.py \
## Profile miss ratio curves

`mrcProfiler` enables fast profiling of miss ratio curves. With a proper parameter setting (such as `sampling_rate`, see [here](../doc/quickstart_mrcProfiler.md) for details) `mrcProfiler` can profile miss ratio curves in a fast way with acceptable accuracy.
Names passed to `--algos` are case-insensitive, so `LRU,FIFO` and `lru,fifo` both work.

```bash
# plot profiled miss ratio over sizes
Expand Down
57 changes: 57 additions & 0 deletions test/test_evictionAlgo.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,28 @@ static void test_MRU(gconstpointer user_data) {
test_cache_algorithm(user_data, &test_data_truth[18]);
}

// Evicting the only object empties the queue. MRU_evict used to write through
// the new, NULL, head and leave the tail pointing at the freed object, so the
// second miss in a one-object cache segfaulted.
static void test_MRU_evict_only_object(void) {
common_cache_params_t cc_params = {.cache_size = 1, .hashpower = 8};
cache_t *cache = MRU_init(cc_params, NULL);
request_t *req = new_request();
req->obj_size = 1;

for (obj_id_t id = 1; id <= 4; id++) {
req->obj_id = id;
g_assert_false(cache->get(cache, req));
g_assert_cmpint(cache->get_n_obj(cache), ==, 1);
g_assert_nonnull(cache->find(cache, req, false));
req->obj_id = id - 1;
g_assert_null(cache->find(cache, req, false));
}

free_request(req);
cache->cache_free(cache);
}

static void test_QDLP_FIFO(gconstpointer user_data) {
test_cache_algorithm(user_data, &test_data_truth[19]);
}
Expand Down Expand Up @@ -563,6 +585,36 @@ static void test_WTinyLFU(gconstpointer user_data) {
// TODO: to be implemented
}

/* The MINISIM profiler only knows an algorithm by its name and reaches it
* through create_cache_using_plugin(). That used to go straight to dlsym(),
* which cannot see a built-in constructor in a statically linked build — the
* archive member holding it is never pulled in — so every built-in name failed
* with "undefined symbol: lru_init" (issue #304). The registry lookup that
* replaced it matches names case-insensitively, the same way cachesim does. */
static void test_create_cache_by_name(gconstpointer user_data) {
common_cache_params_t cc_params = {
.cache_size = CACHE_SIZE, .hashpower = 20, .default_ttl = DEFAULT_TTL};

static const struct {
const char *requested;
const char *expected_name;
} names[] = {
{"lru", "LRU"}, {"LRU", "LRU"}, {"Lru", "LRU"}, {"fifo", "FIFO"},
{"FIFO", "FIFO"}, {"fIfO", "FIFO"}, {"mru", "MRU"}, {"MRU", "MRU"},
};

for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
cache_t *cache =
create_cache_using_plugin(names[i].requested, cc_params, NULL);
g_assert_nonnull(cache);
g_assert_cmpstr(cache->cache_name, ==, names[i].expected_name);
cache->cache_free(cache);
}

// left out of the registry on purpose, see cacheAlgoRegistry.c
g_assert_null(create_cache_by_name("lruv0", cc_params, NULL));
}

static void empty_test(gconstpointer user_data) { ; }

static void test_WorkloadAware(gconstpointer user_data) {
Expand Down Expand Up @@ -611,6 +663,8 @@ int main(int argc, char *argv[]) {
g_test_add_data_func("/libCacheSim/cacheAlgo_Merlin", reader, test_Merlin);
g_test_add_data_func("/libCacheSim/cacheAlgo_MQ", reader, test_MQ);
g_test_add_data_func("/libCacheSim/cacheAlgo_MRU", reader, test_MRU);
g_test_add_func("/libCacheSim/cacheAlgo_MRU_evict_only_object",
test_MRU_evict_only_object);
g_test_add_data_func("/libCacheSim/cacheAlgo_QDLP_FIFO", reader,
test_QDLP_FIFO);
g_test_add_data_func("/libCacheSim/cacheAlgo_Random", reader, test_Random);
Expand Down Expand Up @@ -646,6 +700,9 @@ int main(int argc, char *argv[]) {
g_test_add_data_func("/libCacheSim/cacheAlgo_BeladySize", reader,
test_BeladySize);

g_test_add_data_func("/libCacheSim/create_cache_by_name", reader,
test_create_cache_by_name);

g_test_add_data_func_full("/libCacheSim/empty", reader, empty_test,
test_teardown);

Expand Down
Loading