> ## Documentation Index
> Fetch the complete documentation index at: https://codspeed.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory

> Track memory usage, heap allocations, and memory leaks in your benchmarks.

The memory instrument captures detailed memory usage of your benchmarks, helping
you identify and optimize allocations before shipping to production.

## How does it work?

CodSpeed builds your benchmarks to **run only once** while measuring the memory.

The profiling is done using a custom eBPF program ensuring stability and minimal
overhead (depending on how allocation-heavy the benchmark is).

The tracking is done by either instrumenting the dynamically loaded allocator
libraries or your benchmark executable (when using a statically linked
allocator). We track all allocation related functions (e.g. `malloc`, `free`,
...) in your benchmark.

## What does it measure?

* **Memory Flamegraphs**: The memory instrument captures the call stack of every
  allocation and shows it as a flamegraph. Memory flamegraphs work like the
  other [CodSpeed flamegraphs](/docs/features/profiling) and can be used with the
  [MCP](/docs/ai/mcp).

  <Frame caption="Memory profile showing allocations by function">
    <img src="https://mintcdn.com/codspeed/D8vtMrehwR37ES3M/instruments/memory/assets/memory-flamegraph-nested-allocations.png?fit=max&auto=format&n=D8vtMrehwR37ES3M&q=85&s=492141d85434b5d058a22db70f8d529a" className="rounded-xl w-full max-w-4xl mx-auto" alt="Fullscreen memory profile with a function table and flamegraph showing allocation counts and total allocated memory" width="2098" height="720" data-path="instruments/memory/assets/memory-flamegraph-nested-allocations.png" />
  </Frame>

* **Memory Usage Over Time**: The timeline shows how the peak memory evolves
  throughout benchmark execution. This graph reveals memory patterns, like
  steady-state behavior, gradual growth, or periodic spikes.

  <Frame caption="Memory usage over time">
    <img src="https://mintcdn.com/codspeed/6JQfxVrUMjJz8gDg/instruments/memory/assets/memory-benchmark-sample.png?fit=max&auto=format&n=6JQfxVrUMjJz8gDg&q=85&s=af5311c79194f0df32c1adf6f679981f" className="rounded-xl w-full max-w-2xl mx-auto" alt="Example of memory showing heap allocations, peak memory usage, allocation count, and memory leak detection in a benchmark" width="1782" height="392" data-path="instruments/memory/assets/memory-benchmark-sample.png" />
  </Frame>

* **Peak Physical Memory**: The maximum memory resident in RAM at any single
  point during execution. This is the most important metric for
  memory-constrained systems, as it determines the minimum RAM requirements for
  your application and helps prevent out-of-memory errors. This metric is
  equivalent to
  [Resident Set Size (RSS)](https://en.wikipedia.org/wiki/Resident_set_size)

* **Peak Allocated Memory**: The maximum memory consumed at any single point
  during execution. This helps identify memory leaks and excessive memory usage,
  which can lead to performance degradation or crashes.

* **Average Allocation Size**: The average size of each heap allocation. Smaller
  allocations can lead to better cache locality and less memory fragmentation.

* **Total Allocations**: The total amount of heap memory allocated throughout
  your benchmark execution. Fewer heap allocations typically mean better cache
  locality and less pressure on the memory allocator, making this a key
  optimization target for performance-critical code.

* **Allocation Count**: The number of individual allocation operations performed
  during the benchmark. Since each allocation has overhead, high allocation
  counts can indicate excessive temporary object creation, impacting both
  performance and memory fragmentation.

<Frame caption="Memory stats of a benchmark">
  <img src="https://mintcdn.com/codspeed/wub_cI-wrp0s4byH/instruments/memory/assets/memory-report.png?fit=max&auto=format&n=wub_cI-wrp0s4byH&q=85&s=0a69a09a7a156755e8fa216e80f81602" className="rounded-xl w-full max-w-4xl mx-auto" alt="Memory metrics for a benchmark, showing peak physical memory, peak allocated memory, average allocation size, total allocated memory and allocation count" width="1167" height="100" data-path="instruments/memory/assets/memory-report.png" />
</Frame>

### Allocated vs. physical memory

The two metrics answer different questions. Peak Allocated Memory is the largest
amount of memory requested through the application's allocator (e.g., `malloc`).
Peak Physical Memory is the largest amount of memory resident in RAM.

Physical memory can be lower than allocated memory when the application or
allocator requests large amounts of memory that it doesn't immediately use. This
memory is lazily allocated by the operating system, meaning that it will only be
backed by physical memory once it's actually accessed.

Physical memory can be higher than allocated memory when:

* Fragmentation is high.
* The allocator keeps memory after the application frees it.
* Large files, executables, shared libraries, or shared memory are included.

## Usage with GitHub Actions

**Requirements:**

* `CodSpeedHQ/action >= 4`
* A supported benchmark framework (see [Language Support](#language-support))

To enable memory in your GitHub Actions workflow, use `mode: memory` in the
CodSpeed Action configuration:

```yaml highlight={16} theme={null}
jobs:
  benchmarks:
    name: Run benchmarks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      # ...
      # Setup your environment here:
      #  - Configure your Python/Rust/Node version
      #  - Install your dependencies
      #  - Build your benchmarks (if using a compiled language)
      # ...
      - name: Run the benchmarks
        uses: CodSpeedHQ/action@v5
        with:
          mode: memory
          run: <Insert your benchmark command here>
```

The CodSpeed action will automatically:

* Instrument your benchmarks to capture memory metrics
* Run your benchmarks once with memory tracking enabled
* Upload results to the CodSpeed dashboard

<Warning>
  For compiled languages you must pass the `memory` mode when building, this varies across languages:

  * **Rust**: Pass the [`--measurement-mode`/`-m` flag](/docs/reference/codspeed-rust/cargo-codspeed#the-measurement-mode-flag) to `cargo-codspeed`
  * **C++ (Bazel/CMake)**: Define the [`CODSPEED_MODE` flag](/docs/benchmarks/cpp#the-codspeed_mode-flag)

  Checkout the [language-specific docs](/docs/benchmarks/overview) for information on
  how to build your benchmarks
</Warning>

## Compatibility

### Language Support

To use the memory instrument, ensure you meet the following minimum version
requirements:

| Language | Minimum required versions |
| :- | :- |
| [Rust](/docs/benchmarks/rust) | [`codspeed-divan-compat >= 4.2.0`](https://github.com/CodSpeedHQ/codspeed-rust/releases/tag/v4.2.0) or [`codspeed-criterion-compat >= 4.2.0`](https://github.com/CodSpeedHQ/codspeed-rust/releases/tag/v4.2.0) |
| [C++](/docs/benchmarks/cpp) | [`codspeed-google-benchmark >= 2.1.0`](https://github.com/CodSpeedHQ/codspeed-cpp/releases/tag/v2.1.0) |
| [Python](/docs/benchmarks/python) | [`pytest-codspeed >= 4.3.0`](https://github.com/CodSpeedHQ/pytest-codspeed/releases/tag/v4.3.0) |
| [Node.js](/docs/benchmarks/nodejs/overview) | [`@codspeed/vitest-plugin >= 5.2.0`](https://github.com/CodSpeedHQ/codspeed-node/releases/tag/v5.2.0) or [`@codspeed/tinybench-plugin >= 5.2.0`](https://github.com/CodSpeedHQ/codspeed-node/releases/tag/v5.2.0) |

If you want to use memory with other languages, please reach out on
[Discord](https://discord.gg/MxpaCfKSqF) or
[email our support](mailto:contact@codspeed.io).

### Supported Allocators

CodSpeed supports both dynamic and statically linked allocators. This is
achieved by locating the libraries on your system in common paths, or by
detecting allocator functions inside your benchmark binary. However, this means
that if your allocator or benchmark binary is in a non-standard path, memory
profiling can fail.

Currently, the following allocators are supported:

* **[libc](https://www.gnu.org/software/libc/)** (glibc, musl)
* **libc++ / libstdc++** (C++ standard library)
* **[jemalloc](https://jemalloc.net/)**
* **[mimalloc](https://github.com/microsoft/mimalloc)**
* **[tcmalloc](https://github.com/google/tcmalloc)**

We're planning to extend this list. If an allocator is missing, feel free to
[open an issue](https://github.com/CodSpeedHQ/codspeed/issues/new) or
[contact us](mailto:contact@codspeed.io).

### Kernel support

Physical memory tracking is supported on Linux kernel 6.8 and newer. On older
kernels, CodSpeed does not collect Peak Physical Memory.

GitHub-hosted `ubuntu-22.04`, `ubuntu-24.04` and `ubuntu-26.04` runners
currently meet this requirement.

## Limitations

* **Instrumentation overhead:** The memory instrument tracks **every individual
  allocation**, which works best for small benchmarks with \<2M allocations. For
  bigger benchmarks, try splitting the input or benchmark into smaller parts.

* **Multi-threaded variance:** Concurrent threads can allocate in
  non-deterministic order, causing allocation counts and peak memory to vary
  between runs.

* **Spawned sub-processes:** Allocations in spawned sub-processes are only
  tracked with dynamically linked allocators. Statically linked allocators (e.g.
  jemalloc in Rust) are not supported.

## Best Practices

To get the most out of memory, consider these recommendations:

* **Run benchmarks with realistic workloads** - Use production-representative
  data sizes and patterns to capture actual memory behavior rather than toy
  examples
* **Focus optimization on hot paths** - Prioritize reducing allocations in
  frequently called code, as allocation count in hot paths can significantly
  impact both memory and CPU performance
* **Combine with CPU profiling** - Memory and CPU metrics together reveal the
  full performance story; high allocation counts often correlate with CPU
  overhead
* **Track trends over time** - Compare memory metrics across benchmark runs to
  catch regressions early and validate that optimizations remain effective as
  code evolves

Just like performance regressions, memory regressions can be caught in CI. If
you notice unexpected increases in heap allocations or allocation counts, it's
often a sign that code changes have introduced inefficiencies.

## Next Steps

<CardGroup cols={2}>
  <Card title="CPU Simulation" icon="https://mintcdn.com/codspeed/DYQLS2JiztYwuRW0/assets/icons/dataflow-03-primary.svg?fit=max&auto=format&n=DYQLS2JiztYwuRW0&q=85&s=4a00d3a388b7a6892592a7f54d44466c" href="/docs/instruments/cpu" width="24" height="24" data-path="assets/icons/dataflow-03-primary.svg">
    Learn about CodSpeed's CPU simulation instrument for performance measurement
  </Card>

  <Card title="Creating Benchmarks" icon="code" href="/docs/benchmarks/overview">
    Learn how to write effective benchmarks for your code
  </Card>

  <Card title="Profiling" icon="bars-sort" href="/docs/features/profiling">
    Explore automated profiling features for deeper performance insights
  </Card>

  <Card title="GitHub Actions Setup" icon="github" href="/docs/integrations/ci/github-actions">
    Complete guide to setting up CodSpeed with GitHub Actions
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.