> ## 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.

export const CIWorkflow = ({minimal = false, enableWorkflowDispatch = true, runsOn = "ubuntu-latest", highlight = [], mode, modes, submodules = false, preSteps = [], buildSteps = ["# ...", "# Setup your environment here:", "#  - Configure your Python/Rust/Node version", "#  - Install your dependencies", "#  - Build your benchmarks (if using a compiled language)", "# ..."], benchmarkCommand = ["<Insert your benchmark command here>"], jobName = "Run benchmarks", env = {}}) => {
  const modeList = modes || (mode ? [mode] : undefined);
  if (!modeList || modeList.length === 0) {
    throw new Error("mode or modes is required");
  }
  const indent = (lines, depth) => {
    const reindentedLines = lines.map(l => l.length === 0 ? l : (" ").repeat(depth) + l);
    return reindentedLines.join("\n");
  };
  const workflowDispatchSection = enableWorkflowDispatch ? "  # `workflow_dispatch` allows CodSpeed to trigger backtest\n" + "  # performance analysis in order to generate initial data.\n" + "  workflow_dispatch:\n" : "";
  let yaml = "";
  if (!minimal) {
    yaml += `
name: CodSpeed Benchmarks

on:
  push:
    branches:
      - "main" # or "master"
  pull_request:
`;
    yaml += workflowDispatchSection;
  }
  yaml += `
jobs:
  benchmarks:
    name: ${jobName}
    runs-on: ${runsOn}`;
  if (!minimal) {
    yaml += `
    permissions: # optional for public repositories
      contents: read # required for actions/checkout
      id-token: write # required for OIDC authentication with CodSpeed`;
  }
  if (preSteps.length > 0) yaml += "\n" + indent(preSteps, 4);
  yaml += `
    steps:
      - uses: actions/checkout@v5`;
  if (submodules) {
    const value = typeof submodules === "string" ? submodules : "true";
    yaml += `\n        with:\n          submodules: ${value}`;
  }
  yaml += "\n" + indent(buildSteps, 6);
  const modeValue = modeList.join(",");
  yaml += `
      - name: Run the benchmarks
        uses: CodSpeedHQ/action@v4
        with:
          mode: ${modeValue}`;
  if (benchmarkCommand.length > 0) {
    const indentedBenchCommand = benchmarkCommand.length > 1 ? benchmarkCommand[0] + "\n" + indent(benchmarkCommand.slice(1), 12) : benchmarkCommand;
    const runLine = indent(["run: "], 10) + indentedBenchCommand;
    yaml += `\n${runLine}`;
  }
  const envEntries = Object.entries(env);
  if (envEntries.length > 0) {
    const envLines = ["env:", ...envEntries.map(([k, v]) => `  ${k}: ${v}`)];
    yaml += "\n" + indent(envLines, 8);
  }
  return <CodeBlock language="yaml" highlight={JSON.stringify(highlight)} {...minimal || ({
    filename: ".github/workflows/codspeed.yml",
    icon: "github"
  })}>
      {yaml}
    </CodeBlock>;
};

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?

<Frame caption="Memory run of a benchmark">
  <img src="https://mintcdn.com/codspeed/6JQfxVrUMjJz8gDg/instruments/memory/assets/memory-report.png?fit=max&auto=format&n=6JQfxVrUMjJz8gDg&q=85&s=784d668731765ea27fc548e993a138d8" className="rounded-xl w-full max-w-2xl mx-auto" alt="Example of memory for a benchmark, showing peak memory usage, average allocation size, total allocated memory and allocation count" width="1688" height="652" data-path="instruments/memory/assets/memory-report.png" />
</Frame>

* **Peak Memory Usage**: The maximum memory consumed at any single point during
  execution. This determines the minimum RAM requirements for your application
  and helps prevent out-of-memory errors on constrained systems or expensive
  swapping.

* **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.

* **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>

## 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:

<CIWorkflow minimal mode="memory" highlight={[19]} />

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](/reference/codspeed-rust/cargo-codspeed#the-measurement-mode-flag) to `cargo-codspeed`
  * **C++ (Bazel/CMake)**: Define the [`CODSPEED_MODE` flag](/benchmarks/cpp#the-codspeed_mode-flag)

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

## Compatibility

### Language Support

Memory is currently available for:

* **Rust**
  * [`codspeed-divan-compat >= 4.2.0`](https://github.com/CodSpeedHQ/codspeed-rust/releases/tag/v4.2.0)
  * [`codspeed-criterion-compat >= 4.2.0`](https://github.com/CodSpeedHQ/codspeed-rust/releases/tag/v4.2.0)
* **C++**:
  [`codspeed-google-benchmark >= 2.1.0`](https://github.com/CodSpeedHQ/codspeed-cpp/releases/tag/v2.1.0)
* **Python**:
  [`pytest-codspeed >= 4.3.0`](https://github.com/CodSpeedHQ/pytest-codspeed/releases/tag/v4.3.0)
* **Node.js**
  * [`@codspeed/vitest-plugin >= 5.2.0`](https://github.com/CodSpeedHQ/codspeed-node/releases/tag/v5.2.0)
  * [`@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, we support the following allocators:

* **[libc](https://www.gnu.org/software/libc/)**
* **[jemalloc](http://jemalloc.net/)**
* **[mimalloc](https://github.com/microsoft/mimalloc)**

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).

## 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="/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="/benchmarks/overview">
    Learn how to write effective benchmarks for your code
  </Card>

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

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