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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,8 @@ configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_BINAR
configure_file(${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Find${PROJECT_NAME}.cmake @ONLY)

# Install configuration
install(FILES LICENSE NOTICE
DESTINATION ${CMAKE_INSTALL_DATADIR}/licenses/${PROJECT_NAME})
install(DIRECTORY ${PROJECT_SOURCE_DIR}/libCacheSim/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
Expand Down
39 changes: 39 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Portions of libCacheSim's native synthetic reader are adapted from:

Apache Commons RNG
Copyright 2016-2025 The Apache Software Foundation

This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).

The bounded Zipf sampler in synthetic.c is adapted to C and uses indexed
random draws. It is distributed under the Apache License 2.0 (see LICENSE).

Random123 (Philox2x64-10)

Copyright 2010-2011, D. E. Shaw Research.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of D. E. Shaw Research nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ If you need to add a new trace type or a new algorithm, please see [here](/doc/a
We encourage users to check [deepWiki](https://deepwiki.com/1a1a11a/libCacheSim) for more detailed documentation.

---

### Synthetic traces

Generate native uniform or Zipf workloads without a trace file using the `syn`
trace type. See [synthetic traces](doc/synthetic_traces.md) for syntax, seeds,
reader behavior and limitations.

## Python package

If you are not extremely sensitive to performance, our Python binding offers an easier way to access the core features of libCacheSim.
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 @@ -81,7 +81,7 @@ int myReader_read_one_req(reader_t *reader, request_t *req);
Here are the steps to add a new trace reader:
1. add a new new trace type, e.g., `MYREADER_TRACE` in `trace_type_e` in [include/libCacheSim/enum.h](/libCacheSim/include/libCacheSim/enum.h).
2. add a new reader file, e.g., `myReader.h` in [traceReader/customizedReader/](/libCacheSim/traceReader/customizedReader/) and implement the two functions.
3. add `myReader_setup()` to `setup_reader()`and `myReader_read_one_req()` to `read_one_req()` in [traceReader/reader.c](/libCacheSim/traceReader/reader.c).
3. add `myReader_setup()` to `setup_reader()` in [traceReader/reader.c](/libCacheSim/traceReader/reader.c), and `myReader_read_one_req()` to `read_one_req()` in [traceReader/readerRequest.c](/libCacheSim/traceReader/readerRequest.c).
4. add `MYREADER_TRACE` to `trace_type_str_to_enum()` in [bin/cli_reader_utils.c](/libCacheSim/bin/cli_reader_utils.c)


93 changes: 93 additions & 0 deletions doc/synthetic_traces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Native synthetic traces

Use the `syn` trace type to generate requests directly in the native reader:

```sh
./_build/bin/cachesim Uniform_1000000_10000 syn lru 1000
./_build/bin/cachesim Zipf_1000000_10000_0.9_42 syn lru,s3fifo 100,1000
```

The specifications are `Uniform_n_m[_seed]` and `Zipf_n_m_alpha[_seed]`:

| Parameter | Meaning | Supported values |
| --- | --- | --- |
| `n` | Number of source requests, before sampling or a request limit | Integer from 1 through `INT64_MAX` |
| `m` | Number of possible objects | Integer from 1 through `INT32_MAX` |
| `alpha` | Zipf exponent; zero selects uniform generation | Finite nonnegative decimal number, including scientific notation |
| `seed` | Independent workload seed | Integer from 0 through `UINT64_MAX`; defaults to 1 |

Distribution names are case-insensitive. Numeric fields must be complete tokens;
negative values, overflow, exponents that underflow to zero, nonfinite exponents
and trailing text are rejected.

IDs are in `[0, m)`. Uniform requests select each ID with probability `1/m`.
For Zipf, ID `k` has probability proportional to `(k + 1)^(-alpha)` over that
finite range. Requests are sampled with replacement; a finite trace need not
contain every object.

Each request has size and cost 1, operation `OP_NOP`, no TTL, and timestamp 0,
matching a plain-text trace without timestamps. There is no arrival-time model;
time-based warmup and analysis are not meaningful for this source. Future-access
metadata is unavailable, so it cannot directly drive offline Belady algorithms.
Reader options for columns, file offsets, headers, block splitting and string
object IDs do not apply. Ordinary spatial sampling and request limits apply to
the generated stream. A positive request limit counts source reads, including
requests discarded by sampling; zero and negative limits mean unlimited.

Fractional/automatic cache capacities retain the existing working-set scan.
That scan consumes time and memory proportional to the observed workload; use
absolute capacities when avoiding that preprocessing is important. Generation
itself keeps constant-size state, without a probability table or trace buffer.

## Library use and reproducibility

```c
reader_t *reader = setup_reader("Zipf_1000000_10000_0.9_42",
SYNTHETIC_TRACE, NULL);
request_t *req = new_request();
while (read_one_req(reader, req) == 0) {
/* Consume req. */
}
free_request(req);
close_reader(reader);
```

Reset replays the same sequence. A clone starts at the beginning with the same
configuration and independent state, following the existing reader convention.
The source cursor supports skipping, fractional seeking and reverse traversal
without replaying the prefix. First/last-request helpers leave the original
reader untouched. Counting requests returns the declared source length.

The generator uses Philox2x64-10 with the source index and rejection-draw index
as its counter and the seed as its key. It never consumes the eviction
algorithms' random state. Changing worker count or algorithm order does not
change the workload, and increasing `n` preserves its prefix. Randomized cache
algorithms may still produce different simulation results.

Uniform sampling removes modulo bias. Bounded Zipf uses rejection-inversion,
with stable integral/inverse calculations around exponent 1, adapted from
Apache Commons RNG. The object-count bound keeps the ranks within the reference
algorithm's supported integer range. Floating-point precision limits very small
tail probabilities. Zipf output is reproducible within the same implementation
and numerical environment; identical output across different math libraries or
future generator changes is not guaranteed. Materialize a trace when exact
long-term replay across environments is required.

Spatial sampling preserves source-index navigation. Stateful temporal sampling
supports forward reads, reset and clones; seek/skip/reverse move the source
cursor, not the temporal sampler's history. Reset before a new forward pass.

## Validation

`testSyntheticReader` covers published RNG vectors, reset/clone/navigation,
sampling and limits, finite-distribution checks, and equality with a materialized
trace for LRU, FIFO and S3FIFO in serial and parallel simulations. `testCLI`
covers synthetic syntax and invalid inputs.

```sh
ctest --test-dir _build --output-on-failure
```

Reader throughput includes generation cost. For benchmarks, report generation
and simulation separately; replaying an existing binary file can be faster when
many experiments reuse a workload.
6 changes: 5 additions & 1 deletion libCacheSim/bin/cachesim/cli_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ static char doc[] =
"example: ./cachesim /trace/path csv LRU 100MB\n\n"
"trace can be zstd compressed\n"
"cache_size is in byte, but also support KB/MB/GB\n"
"supported trace_type: txt/csv/twr/vscsi/oracleGeneralBin\n"
"supported trace_type: txt/csv/twr/vscsi/oracleGeneralBin/syn\n"
"supported eviction_algo: LRU/LFU/FIFO/ARC/LeCaR/Cacheus/Merlin\n"
"print-head-req: Print the first few requests when simulating start\n";

Expand Down Expand Up @@ -276,7 +276,11 @@ void free_arg(struct arguments *args) {
// args->caches[i]->cache_free(args->caches[i]);
// }

/* setup_reader clones the sampler; keep the original alive for reader
* clones, then release the CLI-owned instance when simulation is done. */
sampler_t *sampler = args->reader->init_params.sampler;
close_reader(args->reader);
if (sampler != NULL) sampler->free(sampler);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions libCacheSim/bin/cli_reader_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ trace_type_e trace_type_str_to_enum(const char *trace_type_str,
trace_path);
}
return trace_type;
} else if (strcasecmp(trace_type_str, "syn") == 0) {
return SYNTHETIC_TRACE;
} else if (strcasecmp(trace_type_str, "txt") == 0) {
return PLAIN_TXT_TRACE;
} else if (strcasecmp(trace_type_str, "csv") == 0) {
Expand Down
5 changes: 4 additions & 1 deletion libCacheSim/include/libCacheSim/enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ typedef enum {
BINARY_TRACE_FORMAT,
TXT_TRACE_FORMAT,

INVALID_TRACE_FORMAT
INVALID_TRACE_FORMAT,
SYNTHETIC_TRACE_FORMAT
} trace_format_e;

// trace type
Expand All @@ -43,6 +44,7 @@ typedef enum {
VALPIN_TRACE,

UNKNOWN_TRACE,
SYNTHETIC_TRACE,
} __attribute__((__packed__)) trace_type_e;

static const char* const g_trace_type_name[UNKNOWN_TRACE + 2] = {
Expand All @@ -63,6 +65,7 @@ static const char* const g_trace_type_name[UNKNOWN_TRACE + 2] = {

"VALPIN_TRACE",
"UNKNOWN_TRACE",
"SYNTHETIC_TRACE",
};

typedef enum {
Expand Down
3 changes: 2 additions & 1 deletion libCacheSim/include/libCacheSim/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ static inline reader_init_param_t default_reader_init_params(void) {

/**
* setup a reader for reading trace
* @param trace_path path to the trace
* @param trace_path path to the trace, or Uniform_n_m[_seed] /
* Zipf_n_m_alpha[_seed] for SYNTHETIC_TRACE (see doc/synthetic_traces.md)
* @param trace_type CSV_TRACE, PLAIN_TXT_TRACE, BIN_TRACE, VSCSI_TRACE,
* TWR_BIN_TRACE, see libCacheSim/enum.h for more
* @param reader_init_param some initialization parameters used by csv and
Expand Down
2 changes: 2 additions & 0 deletions libCacheSim/traceReader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
set(traceReader_sources_c
generalReader/binary.c
generalReader/csv.c
generalReader/synthetic.c
generalReader/txt.c
generalReader/libcsv.c
customizedReader/lcs.c
reader.c
readerRequest.c
sampling/spatial.c
sampling/temporal.c
)
Expand Down
Loading
Loading