Skip to content
Open
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
42 changes: 24 additions & 18 deletions doc/quickstart_mrcProfiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ First, [build libCacheSim](/doc/install.md). After building libCacheSim, `mrcPro
## Basic Usage

```
./mrcProfiler trace_path trace_type --algo=[LRU] --profiler=[SHARDS|MINISIM]
./bin/mrcProfiler trace_path trace_type --algo=[LRU] --profiler=[SHARDS|MINISIM]
--profiler-params=[FIX_RATE,0.01,hash_salt|FIX_SIZE,8192,hash_salt|FIX_RATE,0.01,thread_num(for MINISIM)]
--size=[0.01,1,100|1MiB,100MiB,100|0.001,0.002,0.004,0.008,0.016|1MiB,10MiB,10MiB,1GiB]
```

Use ./mrcProfiler --help for more details.
Use ./bin/mrcProfiler --help for more details.

Plot scripts are provided in `scripts/profile_mrc.py`. See [here](/scripts/README.md) for more details.

Expand All @@ -35,21 +35,21 @@ SHARDS is configured in `fixed sampling rate` mode with a sampling rate of `0.01
The cache sizes for MRC generation are specified in `fixed-size mode`, spanning `10` evenly spaced points from `100MB` to `1GB`:

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=100MB,1GB,10
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=100MB,1GB,10
```

SHARDS can also operate in `fixed sample size` mode, limiting memory usage by sampling a fixed number of unique objects. The example below samples `2048` objects:

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_SIZE,2048,42 --size=100MB,1GB,10
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_SIZE,2048,42 --size=100MB,1GB,10
```

### Profiling MRC with WSS-Based Sizes

Generate an MRC based on WSS percentages. The example below creates `10` evenly spaced points from `10%` to `50%` of the WSS:

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=0.1,0.5,10
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=0.1,0.5,10
```

### Profiling MRC with Specific Sizes
Expand All @@ -60,13 +60,13 @@ mrcProfiler supports both `WSS-based` and `fixed-size` MRC generation for specif
**WSS-based sizes:**

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=0.01,0.02,0.04,0.08,0.16
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=0.01,0.02,0.04,0.08,0.16
```

**Fixed cache sizes:**

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=10MB,20MB,40MB,80MB,160MB
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=10MB,20MB,40MB,80MB,160MB
```


Expand All @@ -76,15 +76,21 @@ mrcProfiler supports both `WSS-based` and `fixed-size` MRC generation for specif
In the example below, `FIX_RATE,0.01,10` sets a `1%` sampling rate and `10` threads. Note: Sampling rates above 0.5 disable sampling (full trace replay).

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=FIFO --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=0.1,0.5,10
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=FIFO --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=0.1,0.5,10
```

`--algo` accepts the same names as `cachesim`, so any built-in algorithm works — ARC, S3FIFO, sieve, twoq, and the rest. See the [README](/README.md#supported-algorithms) for the full list.

`belady` and `beladySize` need a trace that carries future access times, so they only run on an oracle format such as `oracleGeneral` or `lcs`; the profiler says so and stops otherwise.

`beladySize` is additionally approximate under sampling, beyond the usual sampling error, and warns when you ask for it. It ranks candidates by reuse distance, computed as `next_access_vtime - n_req`, but `next_access_vtime` counts requests in the full trace while `n_req` counts only the requests the sampler kept, so the distance comes out inflated. On `cloudPhysicsIO` at a 100 MB cache, sample rate 0.5 puts it 0.0126 away from the unsampled miss ratio, against 0.0003 for `belady` and 0.0023 for LRU. Use `FIX_RATE,1,<threads>` for an exact run, or `belady`, which compares future times directly and is unaffected.

### Ignoring Object Sizes

To ignore object sizes (treat all objects as 1-byte):

```bash
./mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=0.1,0.5,10 --ignore-obj-size
./bin/mrcProfiler ../data/cloudPhysicsIO.vscsi vscsi --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,42 --size=0.1,0.5,10 --ignore-obj-size
```

### Supporting Different Trace Formats
Expand All @@ -105,13 +111,13 @@ Commands:

```bash
# cachesim
time ./cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral LRU 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0
time ./bin/cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral LRU 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0

# mrcProfiler with SHARDS with 0.01 sample rate
time ./mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10
time ./bin/mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=LRU --profiler=SHARDS --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10

# mrcProfiler with SHARDS with 8192 sample size
time ./mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=LRU --profiler=SHARDS --profiler-params=FIX_SIZE,32768,10 --size=10MB,100MB,10
time ./bin/mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=LRU --profiler=SHARDS --profiler-params=FIX_SIZE,32768,10 --size=10MB,100MB,10
```

resluts:
Expand All @@ -128,22 +134,22 @@ Commands:

```bash
# cachesim for FIFO
time ./cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral FIFO 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0
time ./bin/cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral FIFO 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0

# cachesim for ARC
time ./cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral ARC 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0
time ./bin/cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral ARC 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0

# cachesim for S3FIFO
time ./cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral S3FIFO 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0
time ./bin/cachesim /path_to/cluster52.oracleGeneral.sample10 oracleGeneral S3FIFO 10MB,20MB,30MB,40MB,50MB,60MB,70MB,80MB,90MB,100MB --verbose=0

# mrcProfiler for FIFO eviction algorithm with MINISIM with 0.01 sample rate
time ./mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=FIFO --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10
time ./bin/mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=FIFO --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10

# mrcProfiler for ARC eviction algorithm with MINISIM with 0.01 sample rate
time ./mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=ARC --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10
time ./bin/mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=ARC --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10

# mrcProfiler for S3FIFO eviction algorithm with MINISIM with 0.01 sample rate
time ./mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=S3FIFO --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10
time ./bin/mrcProfiler /path_to/cluster52.oracleGeneral.sample10 oracleGeneral --algo=S3FIFO --profiler=MINISIM --profiler-params=FIX_RATE,0.01,10 --size=10MB,100MB,10
```

resluts:
Expand Down
7 changes: 4 additions & 3 deletions libCacheSim/bin/MRC/parser_mini.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,10 @@ void parse_mini_cmd(int argc, char *argv[], struct MINI_arguments *args) {
for (int i = 0; i < args->n_eviction_algo; i++) {
for (int j = 0; j < args->n_cache_size; j++) {
int idx = i * args->n_cache_size + j;
args->caches[idx] = create_cache(
args->trace_path, args->eviction_algo[i], args->cache_sizes[j],
args->eviction_params, args->consider_obj_metadata);
args->caches[idx] =
create_cache(args->trace_path, args->eviction_algo[i],
args->cache_sizes[j], args->eviction_params,
args->consider_obj_metadata, DEFAULT_HASHPOWER);

if (args->admission_algo != NULL) {
args->caches[idx]->admissioner =
Expand Down
138 changes: 34 additions & 104 deletions libCacheSim/bin/cachesim/cache_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,121 +14,48 @@
extern "C" {
#endif

/* log2 of the hash table size; 24 gives 16M entries */
#define DEFAULT_HASHPOWER 24

/**
* @brief create a cache for the CLI, given the algorithm name
*
* @param hashpower log2 of the hash table size. This used to be adjusted by
* sniffing the trace path for "data/trace.", a file that has not existed for a
* long time, so the adjustment never fired. It is a --hashpower option now
* rather than a hidden rule, because sampling-based algorithms draw candidates
* from the hash table and so their miss ratios depend on its size — not
* something to change silently based on where a trace happens to live.
*/
static inline cache_t *create_cache(const char *trace_path,
const char *eviction_algo,
const uint64_t cache_size,
const char *eviction_params,
const bool consider_obj_metadata) {
const bool consider_obj_metadata,
const int hashpower) {
common_cache_params_t cc_params = {
.cache_size = cache_size,
.default_ttl = 86400 * 300,
.hashpower = 24,
.hashpower = hashpower,
.consider_obj_metadata = consider_obj_metadata,
};
cache_t *cache;

/* the trace provided is small */
if (trace_path != NULL && strstr(trace_path, "data/trace.") != NULL)
cc_params.hashpower -= 8;
typedef struct {
const char *name;
cache_t *(*init_func)(common_cache_params_t, const char *);
} eviction_algo_entry_t;
static const eviction_algo_entry_t simple_algos[] = {
{"2q", TwoQ_init},
{"arc", ARC_init},
{"arcv0", ARCv0_init},
{"CAR", CAR_init},
{"cacheus", Cacheus_init},
{"clock", Clock_init},
{"clock2qplus", Clock2QPlus_init},
{"clockpro", ClockPro_init},
{"fifo", FIFO_init},
{"fifo-merge", FIFO_Merge_init},
{"fifo-reinsertion", Clock_init},
{"fifomerge", FIFO_Merge_init},
{"flashProb", flashProb_init},
{"gdsf", GDSF_init},
{"lhd", LHD_init},
{"lecar", LeCaR_init},
{"lecarv0", LeCaRv0_init},
{"lfu", LFU_init},
{"lfucpp", LFUCpp_init},
{"lfuda", LFUDA_init},
{"lirs", LIRS_init},
{"lru", LRU_init},
{"lru-k", LRU_K_init},
{"lru-prob", LRU_Prob_init},
{"mq", MQ_init},
{"multiqueue", MQ_init},
{"nop", nop_init},
// plugin cache that allows user to implement custom cache
{"pluginCache", pluginCache_init},
{"qdlp", QDLP_init},
{"random", Random_init},
{"RandomLRU", RandomLRU_init},
{"randomTwo", RandomTwo_init},
{"s3-fifo", S3FIFO_init},
{"s3-fifov0", S3FIFOv0_init},
{"s3fifo", S3FIFO_init},
{"s3fifod", S3FIFOd_init},
{"s3fifov0", S3FIFOv0_init},
{"sieve", Sieve_init},
{"size", Size_init},
{"slru", SLRU_init},
{"slruv0", SLRUv0_init},
{"twoq", TwoQ_init},
{"wtinyLFU", WTinyLFU_init},
#ifdef ENABLE_3L_CACHE
{"3LCache", ThreeLCache_init},
#endif
#ifdef ENABLE_GLCACHE
{"GLCache", GLCache_init},
{"gl-cache", GLCache_init},
#endif
#ifdef ENABLE_LRB
{"lrb", LRB_init},
#endif
};

cache_t *(*init_func)(common_cache_params_t, const char *) = NULL;
for (size_t i = 0; i < sizeof(simple_algos) / sizeof(simple_algos[0]); ++i) {
if (strcasecmp(eviction_algo, simple_algos[i].name) == 0) {
init_func = simple_algos[i].init_func;
break;
}
}

// Initializing for algorithms which require special handling (not in
// simple_algos)
if (init_func) {
cache = init_func(cc_params, eviction_params);
} else if (strcasecmp(eviction_algo, "hyperbolic") == 0) {
/* The name to constructor mapping lives in the library
* (cache/cacheAlgoRegistry.c) so that the MINISIM profiler, which only knows
* the algorithm by name, shares one table with the CLI. The cases below need
* more than a lookup — a smaller hash table, or a check that the trace
* carries the future information the algorithm needs — so they are handled
* here rather than in the registry.
*
* tinyLFU used to be one of them, appending window-size=0.01 when the caller
* had not given one. WTinyLFU's DEFAULT_PARAMS already sets exactly that
* before applying the caller's parameters, so the append never changed
* anything; it is a plain alias in the registry now, which is also what makes
* it reachable from the MRC profiler. */
if (strcasecmp(eviction_algo, "hyperbolic") == 0) {
cc_params.hashpower = MAX(cc_params.hashpower - 8, 16);
cache = Hyperbolic_init(cc_params, eviction_params);
} else if (strcasecmp(eviction_algo, "tinyLFU") == 0) {
if (eviction_params == NULL || eviction_params[0] == '\0') {
cache = WTinyLFU_init(cc_params, NULL);
} else {
const char *window_size = strstr(eviction_params, "window-size=");
if (window_size == NULL) {
// Calculate exact size needed: original + ",window-size=0.01" + null
// terminator
size_t new_params_len =
strlen(eviction_params) + strlen(",window-size=0.01") + 1;
char *new_params = (char *)malloc(new_params_len);
if (new_params == NULL) {
ERROR("failed to allocate memory for new_params\n");
abort();
}
snprintf(new_params, new_params_len, "%s,window-size=0.01",
eviction_params);
cache = WTinyLFU_init(cc_params, new_params);
free(new_params); // Free the allocated memory
} else {
cache = WTinyLFU_init(cc_params, eviction_params);
}
}
} else if (strcasecmp(eviction_algo, "belady") == 0) {
if (strcasestr(trace_path, "oracleGeneral") == NULL &&
strcasestr(trace_path, "lcs") == NULL) {
Expand All @@ -151,8 +78,11 @@ static inline cache_t *create_cache(const char *trace_path,
cc_params.hashpower = MAX(cc_params.hashpower - 8, 16);
cache = BeladySize_init(cc_params, eviction_params);
} else {
ERROR("do not support algorithm %s\n", eviction_algo);
abort();
cache = create_cache_by_name(eviction_algo, cc_params, eviction_params);
if (cache == NULL) {
ERROR("do not support algorithm %s\n", eviction_algo);
abort();
}
}

return cache;
Expand Down
16 changes: 15 additions & 1 deletion libCacheSim/bin/cachesim/cli_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ enum argp_option_short {
OPTION_PREFETCH_ALGO = 'p',
OPTION_PREFETCH_PARAMS = 0x109,
OPTION_PRINT_HEAD_REQ = 0x10a,
OPTION_HASHPOWER = 0x10b,
};

/*
Expand Down Expand Up @@ -94,6 +95,11 @@ static struct argp_option options[] = {
{"verbose", OPTION_VERBOSE, "1", 0, "Produce verbose output", 10},
{"print-head-req", OPTION_PRINT_HEAD_REQ, "false", 0,
"Print the first few requests", 10},
{"hashpower", OPTION_HASHPOWER, "24", 0,
"Log2 of the hash table size, default 24 (16M entries). Lower it to save "
"memory on small traces. Note that sampling-based algorithms draw "
"candidates from the hash table, so their miss ratios depend on this",
10},

{0, 0, 0, 0, 0, 0}};

Expand Down Expand Up @@ -163,6 +169,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
case OPTION_CONSIDER_OBJ_METADATA:
arguments->consider_obj_metadata = is_true(arg) ? true : false;
break;
case OPTION_HASHPOWER:
arguments->hashpower = atoi(arg);
if (arguments->hashpower <= 0 || arguments->hashpower >= 40) {
ERROR("hashpower must be between 1 and 39, got %d\n",
arguments->hashpower);
}
break;
case OPTION_WARMUP_SEC:
arguments->warmup_sec = atoi(arg);
break;
Expand Down Expand Up @@ -226,6 +239,7 @@ static void init_arg(struct arguments *args) {
args->use_ttl = false;
args->ignore_obj_size = false;
args->consider_obj_metadata = false;
args->hashpower = DEFAULT_HASHPOWER;
args->report_interval = 3600 * 24;
args->n_thread = n_cores();
args->warmup_sec = -1;
Expand Down Expand Up @@ -347,7 +361,7 @@ void parse_cmd(int argc, char *argv[], struct arguments *args) {
int idx = i * args->n_cache_size + j;
args->caches[idx] = create_cache(
args->trace_path, args->eviction_algo[i], args->cache_sizes[j],
args->eviction_params, args->consider_obj_metadata);
args->eviction_params, args->consider_obj_metadata, args->hashpower);

if (args->admission_algo != NULL) {
args->caches[idx]->admissioner =
Expand Down
1 change: 1 addition & 0 deletions libCacheSim/bin/cachesim/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct arguments {
bool consider_obj_metadata;
bool use_ttl;
bool print_head_req;
int hashpower;

/* arguments generated */
reader_t *reader;
Expand Down
1 change: 1 addition & 0 deletions libCacheSim/cache/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ set(cache_sources_c
${eviction_sources_c}
${prefetch_sources_c}
cache.c
cacheAlgoRegistry.c
plugin.c
)

Expand Down
Loading
Loading