# How to Simulate Fractional Cache Sizes (Percentage of Working Set) in libCacheSim

> Learn to simulate fractional cache sizes in libCacheSim. Specify cache capacity as a percentage of your working set for precise memory analysis.

- Repository: [Juncheng Yang/libcachesim](https://github.com/1a1a11a/libcachesim)
- Tags: how-to-guide
- Published: 2026-02-23

---

**libCacheSim lets you specify cache capacity as a floating-point fraction of the trace's working-set size, automatically converting values like `0.01` into concrete byte or object counts.**

libCacheSim's `cachesim` CLI eliminates manual size calculations by interpreting decimal arguments as percentages of the working-set size (WSS). This feature enables rapid sensitivity analysis across relative cache capacities without pre-processing traces to compute absolute storage requirements. The implementation detects fractional inputs through pattern matching and scales them against pre-calculated WSS metrics stored in `wss_obj` and `wss_byte`.

## Parsing Fractional Arguments in the CLI

When you invoke `cachesim`, the argument parser examines each cache-size token to determine whether it represents an absolute value or a relative fraction.

### The `conv_cache_sizes()` Detection Logic

In [`libCacheSim/bin/cachesim/cli_parser.c`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cli_parser.c), the function `conv_cache_sizes()` inspects each size argument:

- If the token contains a dot (`.`), libCacheSim treats it as a **floating-point fraction** of the working set.
- The parser multiplies this fraction by the trace's working-set size to derive the concrete cache capacity.
- If you pass `0` or `auto`, the simulator automatically applies the default fraction set: **0.001, 0.003, 0.01, 0.03, 0.1, 0.2, 0.4, and 0.8** (0.1% through 80%).

The concrete size calculation depends on the `--ignore-obj-size` flag. Without the flag, the fraction applies to `wss_byte` (total unique bytes); with the flag, it applies to `wss_obj` (distinct object count).

### Automatic Cache Size Selection

Passing `0` or `auto` triggers `set_cache_size()` to instantiate eight separate cache simulations spanning the default fraction range. This allows comprehensive hit-rate analysis across orders of magnitude in relative capacity with a single command execution.

## Working-Set Size Calculation

Before simulation begins, libCacheSim computes the working-set size through `cal_working_set_size()` in [`libCacheSim/bin/cli_reader_utils.c`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cli_reader_utils.c).

### Trace Scanning and Sampling

The function performs a complete pass through the trace to count distinct objects and accumulate their total byte size. For very large traces, it employs sampling (examining every *N*-th object) to bound memory consumption during this preprocessing phase. The results populate two critical variables:

- **`wss_obj`**: The number of unique object IDs in the trace.
- **`wss_byte`**: The sum of unique objects' sizes in bytes.

These values persist for the duration of the simulation session, allowing the CLI to scale fractional inputs into absolute capacities.

### Byte Mode vs. Object Mode

- **Default mode**: A fraction like `0.1` allocates cache space equal to 10% of `wss_byte`, respecting variable object sizes.
- **`--ignore-obj-size` mode**: The same fraction allocates space for 10% of `wss_obj`, treating every object as size 1 for capacity calculations.

## Practical CLI Examples

### Simulate 1% of Working-Set Bytes

```bash
./bin/cachesim trace.vscsi vscsi lru 0.01

```

This command configures an LRU cache with capacity equal to 1% of the trace's total unique data volume.

### Simulate 5% of Distinct Objects

```bash
./bin/cachesim trace.vscsi vscsi lru 0.05 --ignore-obj-size

```

Here, libCacheSim calculates 5% of `wss_obj` and configures the cache to hold that many objects, regardless of individual object sizes.

### Run Automatic Fraction Sweep

```bash
./bin/cachesim trace.vscsi vscsi lru auto

```

This executes eight simulations at fractions 0.001, 0.003, 0.01, 0.03, 0.1, 0.2, 0.4, and 0.8, generating a complete performance curve across relative capacities.

### Python Binding Workaround

The Python API does not directly expose fractional size syntax. Instead, compute the working set manually and scale it:

```python
from libcachesim import TraceReader, LRU

reader = TraceReader("trace.vscsi", trace_type="vscsi")

# Calculate working-set size in bytes

wss_bytes = sum(req.obj_size for req in reader)

# Target 2% of working set

cache_size = int(0.02 * wss_bytes)
cache = LRU(cache_size=cache_size)

obj_mr, byte_mr = cache.process_trace(reader)
print(f"Object miss ratio: {obj_mr:.4f}, Byte miss ratio: {byte_mr:.4f}")

```

This approach mirrors the CLI's internal logic while using the Python interface.

## Core Implementation Files

The fractional cache size feature spans three key locations in the codebase:

- **[`libCacheSim/bin/cachesim/cli_parser.c`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cli_parser.c)**: Implements `conv_cache_sizes()` to detect decimal inputs and `set_cache_size()` to handle `auto` generation.
- **[`libCacheSim/bin/cli_reader_utils.c`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cli_reader_utils.c)**: Contains `cal_working_set_size()`, which computes `wss_obj` and `wss_byte` through trace analysis.
- **[`doc/quickstart_cachesim.md`](https://github.com/1a1a11a/libcachesim/blob/main/doc/quickstart_cachesim.md)**: Documents the fraction syntax for end users.

## Summary

- libCacheSim interprets cache-size arguments containing decimals (e.g., `0.01`) as fractions of the working-set size.
- The CLI automatically calculates working-set size via `cal_working_set_size()` before simulation begins.
- Use `--ignore-obj-size` to apply fractions to object counts rather than byte volumes.
- Passing `0` or `auto` triggers a predefined sweep across eight fractions from 0.1% to 80%.
- Implementation resides primarily in [`cli_parser.c`](https://github.com/1a1a11a/libcachesim/blob/main/cli_parser.c) and [`cli_reader_utils.c`](https://github.com/1a1a11a/libcachesim/blob/main/cli_reader_utils.c).

## Frequently Asked Questions

### How does libCacheSim distinguish between fractional and absolute cache sizes?

libCacheSim checks for the presence of a dot (`.`) in the cache-size argument within `conv_cache_sizes()`. Tokens containing a dot are parsed as floating-point numbers and treated as fractions of the working-set size, while integer tokens are interpreted as absolute byte or object counts depending on the mode.

### What is the difference between byte-based and object-based fractional sizing?

Without flags, fractions apply to the total unique bytes (`wss_byte`) in the trace. When you specify `--ignore-obj-size`, libCacheSim applies the fraction to the count of unique objects (`wss_obj`) instead, effectively simulating a cache that holds a percentage of distinct items regardless of their individual sizes.

### Can I use fractional cache sizes with the Python bindings?

No, the Python API requires absolute size values. You must manually calculate the working-set size using `TraceReader`, multiply by your desired fraction, and pass the resulting integer to the cache constructor. This mirrors the CLI's preprocessing logic but requires explicit implementation in your Python script.

### What fractions does libCacheSim use when I specify `auto` or `0`?

The simulator uses a fixed progression optimized for sensitivity analysis: **0.001, 0.003, 0.01, 0.03, 0.1, 0.2, 0.4, and 0.8**. This logarithmic spacing efficiently covers the performance curve from tiny caches (0.1% of working set) to large caches (80% of working set) in a single execution.