# How to Configure Hashpower and Memory Footprint for libCacheSim Simulations

> Optimize libCacheSim simulations by configuring hashpower and memory footprint. Learn how hashpower controls table size, impacting memory usage for your cache simulations.

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

---

**Set the `hashpower` field in `common_cache_params_t` to control the internal hash table size, where memory usage scales as `sizeof(cache_obj_t) × 2^hashpower`.**

libCacheSim uses an internal hash table to map object IDs to cache entries, and the **hashpower** parameter directly determines how much DRAM is allocated for this structure. Understanding how to tune this value lets you balance lookup performance against memory constraints, whether you are running simulations on a laptop or a high-capacity server.

## Understanding Hashpower in libCacheSim

**Hashpower** is the exponent that defines the number of buckets in the cache’s internal hash table. The table contains `2^hashpower` buckets, with each bucket storing a pointer (or metadata structure) to a cache object.

The macro that performs this calculation is defined in [`libCacheSim/dataStructure/hashtable/hashtableStruct.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/dataStructure/hashtable/hashtableStruct.h):

```c
#define hashsize(n) ((uint64_t)1 << (uint16_t)(n))

```

Consequently, the base memory consumed by a cache grows roughly as:

```

memory ≈ sizeof(cache_obj_t) × 2^hashpower

```

Additional overhead comes from linked-list entries, algorithm-specific metadata (e.g., Bloom filters, priority queues), and the actual object storage.

## Default Hashpower Values and Where They Are Set

libCacheSim sets different defaults depending on the entry point you use.

| Source | Default Value | Location |
|--------|---------------|----------|
| Library API | `hashpower = 20` | [`libCacheSim/include/libCacheSim/cache.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/include/libCacheSim/cache.h) (lines 63-68) |
| CLI (`cachesim`) | `hashpower = 24` | [`libCacheSim/bin/cachesim/cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cache_init.h) (lines 22-26) |
| Small traces | Reduced by 8 (minimum 16) | [`libCacheSim/bin/cachesim/cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cache_init.h) (lines 31-33) |

The CLI automatically reduces `hashpower` by 8 if the trace path contains "data/trace.", capping the lower bound at 16 for algorithms like Hyperbolic or BeladySize:

```c
cc_params.hashpower = MAX(cc_params.hashpower - 8, 16);

```

## How Hashpower Affects Memory Footprint

For a 64-bit system where `sizeof(void*) == 8`, a **hashpower of 24** creates:

```

2^24 = 16,777,216 buckets
≈ 128 MiB just for the bucket array

```

Increasing `hashpower` by 1 doubles the bucket array size; decreasing it by 1 halves the allocation.

Empirical profiling in [`doc/memory_usage_profiling.md`](https://github.com/1a1a11a/libcachesim/blob/main/doc/memory_usage_profiling.md) (lines 71-74) confirms that `create_chained_hashtable_v2()` dominates the memory footprint for FIFO, LRU, and Clock algorithms.

**Estimation formula:**

```

total_memory ≈ cache_size               // object storage
               + sizeof(cache_obj_t) × 2^hashpower   // hash table
               + algorithm_overhead

```

For default LRU with `hashpower = 24` and `cache_obj_t` ≈ 32 bytes:

```

hash table ≈ 32 B × 2^24 ≈ 512 MiB
object storage = 1 GiB  → total ≈ 1.5 GiB

```

Lowering `hashpower` to 20 reduces the hash table to ≈ 32 MiB, saving ~480 MiB.

## Configuring Hashpower for Your Simulation

### Programmatic Configuration (C API)

When calling `create_cache()` or algorithm-specific initializers, populate `common_cache_params_t` with your desired value:

```c
#include "libCacheSim/cache.h"

common_cache_params_t params = {
    .cache_size = 1ULL << 30,            // 1 GiB
    .default_ttl = 86400 * 30,           // 30 days
    .hashpower = 18,                     // 2^18 = 262,144 buckets (~2 MiB)
    .consider_obj_metadata = false,
};

cache_t *c = create_cache("data/trace.vscsi", "lru", params.cache_size,
                         NULL, false);

```

The `hashpower` field is read by `cache_struct_init()` (invoked by each eviction algorithm's `*_init` function), propagating your setting to the hashtable allocation.

### CLI Configuration (cachesim Binary)

The `cachesim` command-line tool does not expose a runtime flag for `hashpower`. To change the default, edit [`libCacheSim/bin/cachesim/cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cache_init.h) and modify the constant:

```c
static inline cache_t *create_cache(...){
    common_cache_params_t cc_params = {
        .cache_size = cache_size,
        .default_ttl = 86400 * 300,
        .hashpower = 22,      // ← new default
        .consider_obj_metadata = consider_obj_metadata,
    };
    // ...
}

```

Recompile the binary:

```bash
mkdir -p build && cd build
cmake .. && make -j

```

### Custom Plugin Configuration

When implementing a custom cache plugin (see [`example/plugin_v1/test_plugin.c`](https://github.com/1a1a11a/libcachesim/blob/main/example/plugin_v1/test_plugin.c)), you receive a `common_cache_params_t` argument. Adjust `hashpower` before passing parameters to internal constructors:

```c
common_cache_params_t params = default_common_cache_params();
params.hashpower = 20;   // optimize for containerized environment

cache_t *my_cache = my_plugin_init(params, custom_args);

```

## Choosing the Right Hashpower Value

| Situation | Recommended Hashpower | Rationale |
|-----------|----------------------|-----------|
| Large caches (≥ 1 GiB) | 24 – 26 | Ample DRAM available; larger tables reduce collisions and improve lookup speed. |
| Small caches (≤ 100 MiB) | 16 – 20 | Saves memory; acceptable collision rates due to lower absolute object counts. |
| Very large workloads (tens of GiB) | 26 – 28 (if RAM permits) | Maintains low load factor, preventing performance degradation on high-traffic traces. |
| Memory-constrained environments (containers, notebooks) | 16 (minimum) | Guarantees hashtable stays under ≈ 8 MiB (pointer array only). |

## Summary

- **Hashpower** controls the size of the internal hash table as `2^hashpower` buckets, directly impacting DRAM usage.
- Default values vary by entry point: **20** for the C API ([`cache.h`](https://github.com/1a1a11a/libcachesim/blob/main/cache.h)), **24** for the CLI ([`cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/cache_init.h)), with automatic reduction for small traces.
- Memory scales linearly with `2^hashpower`; each increment doubles the hash table allocation.
- Configure via `common_cache_params_t.hashpower` in code, or by editing [`cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/cache_init.h) and recompiling for the CLI.
- Select values between **16** (minimum) and **28** based on available RAM and cache size to balance memory footprint against lookup performance.

## Frequently Asked Questions

### What is the minimum hashpower value allowed in libCacheSim?

The minimum enforced value is **16**. This lower bound is hardcoded in [`libCacheSim/bin/cachesim/cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cache_init.h) (lines 101-104) using `MAX(cc_params.hashpower - 8, 16)` to prevent excessive collision rates that would degrade performance on small traces.

### How do I calculate the exact memory usage of the hash table?

Multiply the number of buckets by the size of a pointer on your architecture. Use the formula: `memory_bytes = (1ULL << hashpower) * sizeof(void*)`. For example, with `hashpower = 24` on a 64-bit system: `2^24 * 8 bytes = 134,217,728 bytes` (128 MiB). Add `sizeof(cache_obj_t)` per stored object for total cache memory.

### Why does the CLI use a higher default hashpower than the library API?

The `cachesim` CLI targets production-scale traces and assumes server-class DRAM availability, defaulting to **24** in [`cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/cache_init.h). The library API ([`cache.h`](https://github.com/1a1a11a/libcachesim/blob/main/cache.h)) defaults to **20** to provide a safer baseline for embedded or experimental use where memory constraints are unknown. The CLI also implements automatic reduction logic for small traces that the raw API does not apply.

### Can I change hashpower without recompiling when using the cachesim binary?

No. The `cachesim` command-line tool does not expose a runtime flag (such as `--hashpower`) to adjust this parameter. To modify the default, you must edit [`libCacheSim/bin/cachesim/cache_init.h`](https://github.com/1a1a11a/libcachesim/blob/main/libCacheSim/bin/cachesim/cache_init.h), change the `.hashpower` value in the `cc_params` struct, and recompile the project with `cmake` and `make`.