How to Use the Python API for Cache Simulation in libCacheSim: A Complete Guide

The libCacheSim Python API provides lightweight wrappers that compile the C simulator on-demand, invoke it via subprocess, and parse plain-text output into Python dictionaries for analyzing miss-ratio curves.

The libCacheSim repository ships a high-performance C implementation of cache-replacement algorithms wrapped in a minimal Python interface. This guide explains how to leverage the Python API to orchestrate simulations, process traces, and visualize results without writing any C code.

Architecture of the Python API for Cache Simulation

Unlike traditional Python bindings that rely on C extensions or ctypes, the libCacheSim Python API operates as a thin orchestration layer within the scripts/ directory. It automatically compiles the cachesim binary from source when needed, executes it via subprocess, and converts space-separated output into native Python structures.

The core components include:

Setting Up the Environment

Before running simulations, ensure the C binary is available. The setup() function handles compilation transparently by checking CACHESIM_PATH and invoking the build system if the binary is absent.

from scripts.utils.setup_utils import setup

# Compiles bin/cachesim from src/ if missing (safe to call multiple times)

setup()

This initialization requires no manual configuration and executes install_dependency() followed by compile_cachesim() to produce the simulator binary.

Running Size-Based Cache Simulations

The run_cachesim_size() function in scripts/plot_mrc_size.py executes the simulator across a range of cache sizes and returns structured data for plotting miss-ratio curves (MRC).

from scripts.plot_mrc_size import run_cachesim_size, plot_mrc_size

# Execute simulation across specified cache sizes

dataname, mrc_dict, cache_has_units = run_cachesim_size(
    datapath="/path/to/trace.oracleGeneral",
    algos="lru,lfu,arc",              # Comma-separated algorithm list

    cache_sizes="0.01,0.05,0.1",      # Fractions of object count or absolute sizes

    ignore_obj_size=True,             # Treat all objects as equal size

    trace_format="oracleGeneral",     # Built-in trace parser

    trace_format_params="",           # Additional format arguments

    num_thread=-1                     # -1 uses all available cores

)

# Generate PDF visualization

plot_mrc_size(
    mrc_dict=mrc_dict,
    cache_size_has_unit=cache_has_units,
    use_byte_miss_ratio=False,
    name=f"{dataname}_miss_ratio"
)

Key implementation details:

  • run_cachesim_size() constructs the command line and invokes the binary via subprocess.run (source lines 56-70).
  • The internal _parse_cachesim_output() function converts space-separated fields into tuples of (cache_size, miss_ratio, byte_miss_ratio) and normalizes units when traces contain byte suffixes.
  • plot_mrc_size() renders curves with log-scaled cache sizes and writes a PDF file (source lines 64-94).

Running Time-Based Cache Simulations

For analyzing how miss ratios evolve over time, use the time-based API in scripts/plot_mrc_time.py. The interface mirrors the size-based version but requests time-varying statistics from the simulator.

from scripts.plot_mrc_time import run_cachesim_time, plot_mrc_time

dataname, mrc_dict, cache_has_units = run_cachesim_time(
    datapath="/path/to/trace.oracleGeneral",
    algos="lru,arc",
    cache_sizes="0.05,0.1",
    ignore_obj_size=True,
    trace_format="oracleGeneral",
    num_thread=-1
)

plot_mrc_time(
    mrc_dict=mrc_dict,
    cache_size_has_unit=cache_has_units,
    name=f"{dataname}_time_mrc"
)

Benchmarking Simulator Throughput

To extract CPU performance metrics such as cycles per instruction or throughput (MOPS), use the benchmark_throughput.py module. The run_cachesim() function wraps the binary execution with Linux perf and parses the output via parse_perf_stat().

from scripts.benchmark_throughput import run_cachesim

# Returns dictionary of performance counters

results = run_cachesim(
    datapath="trace.oracleGeneral",
    algos="lru",
    cache_size="0.1",
    ignore_obj_size=True
)

Complete Working Example

The following script demonstrates an end-to-end workflow: setup, simulation, and visualization.

#!/usr/bin/env python3
"""Compute and plot size-based MRC for a libCacheSim trace."""

from scripts.utils.setup_utils import setup
from scripts.plot_mrc_size import run_cachesim_size, plot_mrc_size

def main():
    # Ensure binary is compiled

    setup()
    
    # Configuration

    trace = "data/twitter_cluster52.oracleGeneral"
    algorithms = "lru,arc,slru"
    sizes = "0.01,0.05,0.1,0.2"
    
    # Run simulation

    name, mrc, has_units = run_cachesim_size(
        datapath=trace,
        algos=algorithms,
        cache_sizes=sizes,
        ignore_obj_size=True,
        trace_format="oracleGeneral",
        num_thread=-1
    )
    
    # Generate visualization

    plot_mrc_size(
        mrc_dict=mrc,
        cache_size_has_unit=has_units,
        use_byte_miss_ratio=False,
        name=f"{name}_size_mrc"
    )

if __name__ == "__main__":
    main()

Executing this script produces a PDF named <trace_name>_size_mrc.pdf containing one curve per specified algorithm.

Summary

  • The libCacheSim Python API consists of utility scripts in the scripts/ directory that wrap the C cachesim binary via subprocess calls.
  • setup() in scripts/utils/setup_utils.py automatically compiles the simulator on first use by checking CACHESIM_PATH.
  • run_cachesim_size() and run_cachesim_time() execute simulations and return (dataname, mrc_dict, cache_has_units) tuples for analysis.
  • The _parse_cachesim_output() function in scripts/plot_mrc_size.py handles conversion of plain-text output into Python data structures.
  • No third-party Python bindings are required; the API uses standard library modules and matplotlib for visualization.

Frequently Asked Questions

Do I need to manually compile the C code before using the Python API?

No. The setup() function in scripts/utils/setup_utils.py automatically detects if bin/cachesim is missing and compiles it from the src/ directory (source lines 45-53). This compilation happens transparently when you import the setup module or call the function directly.

What trace formats does the Python API support?

The API supports all trace formats built into the C simulator, including oracleGeneral, csv, and binary formats. You specify the format using the trace_format parameter in run_cachesim_size() or run_cachesim_time(), and pass additional parser arguments via trace_format_params if the format requires them.

How do I specify multiple cache replacement algorithms in a single run?

Provide a comma-separated string to the algos parameter, such as "lru,lfu,arc" or "fifo,lru,slru". The scripts/utils/cachesim_utils.py module maintains the mapping between these human-readable names and the internal identifiers used by the C binary.

Can I retrieve simulation results without generating plots?

Yes. The run_cachesim_size() and run_cachesim_time() functions return raw data in the mrc_dict dictionary, which maps algorithm names to lists of (cache_size, miss_ratio, byte_miss_ratio) tuples. You can process this data programmatically without calling plot_mrc_size() or plot_mrc_time().

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →