# How to Add Custom Events (branch-misses, cache-misses) to magic-trace Traces

> Learn to add custom perf events like branch-misses and cache-misses to magic-trace traces using the --extra-events command-line option. Enhance your performance analysis today.

- Repository: [Jane Street/magic-trace](https://github.com/janestreet/magic-trace)
- Tags: how-to-guide
- Published: 2026-05-24

---

**TL;DR:** Supply extra perf events on the command line with `--extra-events` and magic-trace will parse them, request the kernel to record them via `perf_event_open(2)`, and emit the results as `Event_sample` entries in the trace file.

magic-trace is Jane Street's open-source execution tracer that uses Linux perf to capture high-fidelity timelines. Adding custom hardware events like `branch-misses` or `cache-misses` lets you correlate micro-architectural behavior with specific code regions without recompiling your target or the tracer.

## How magic-trace Represents Hardware Events

The internal event model is defined in **[`src/event.ml`](https://github.com/janestreet/magic-trace/blob/main/src/event.ml)**. Raw counter samples are represented by the `Event_sample` variant of `Event.Ok.Data.t` at lines 84–86:

```ocaml
| Event_sample of {
    location : Location.t;      (* where the event originated *)
    count    : int;             (* sampled count *)
    name     : Collection_mode.Event.Name.t;  (* e.g. "branch-misses" *)
  }

```

The `Collection_mode.Event.Name.t` type is a thin string wrapper, allowing any perf-compatible event name to be stored and later serialized into the output trace.

## Enabling Custom Events via the CLI

magic-trace exposes custom events through the **`--extra-events`** flag implemented in **[`src/trace.ml`](https://github.com/janestreet/magic-trace/blob/main/src/trace.ml)** (around line 900). The argument parsing logic feeds the comma-separated list into the `Collection_mode` module, which produces a list of `Collection_mode.Event.t` values.

These descriptors are passed to the perf backend in **[`src/perf_tool_backend.ml`](https://github.com/janestreet/magic-trace/blob/main/src/perf_tool_backend.ml)**, which opens the hardware counters using `perf_event_open(2)` and attaches them to the tracing session. During trace decoding, **[`src/perf_decode.ml`](https://github.com/janestreet/magic-trace/blob/main/src/perf_decode.ml)** (line 609) matches the raw perf output lines via regex and constructs `Event_sample` records for each sample.

## Recording branch-misses and cache-misses

### Basic syntax

Pass the event names as a comma-separated list:

```bash
magic-trace \
  --target <binary> \
  --extra-events branch-misses,cache-misses \
  --output trace.perfetto

```

The names are forwarded verbatim to the kernel, so any event listed by `perf list` is valid.

### Setting sampling periods

To reduce overhead or increase granularity, append `/period=<N>` to any event:

```bash
magic-trace \
  --target <binary> \
  --extra-events branch-misses/period=100,cache-misses/period=200 \
  --output trace.perfetto

```

This syntax follows the format demonstrated in **[`test/demo_extra_events.ml`](https://github.com/janestreet/magic-trace/blob/main/test/demo_extra_events.ml)**, which prints samples as:

```

<timestamp>  <cpu>  <event-name>/period=<N>/u: <count>

```

### Debugging raw perf output

To inspect the raw data before conversion, add `--debug-perf`:

```bash
magic-trace \
  --target <binary> \
  --extra-events branch-misses/period=50 \
  --debug-perf \
  --output debug.perfetto

```

This preserves the intermediate `perf script` output so you can verify that the kernel is generating samples for your custom events.

## Viewing Custom Events in Perfetto

After the run finishes, open the trace in Perfetto. magic-trace emits `Event_sample` entries that appear as a dedicated track named after the event (e.g., "branch-misses"). Each point on the track represents a sampled count processed by `Perf_decode.to_event`, allowing you to correlate spikes in `branch-misses` or `cache-misses` with specific function executions.

## Key Implementation Files

| File | Role |
|------|------|
| [`src/event.ml`](https://github.com/janestreet/magic-trace/blob/main/src/event.ml) | Defines the `Event_sample` variant (lines 82–86) that stores counter samples. |
| [`src/trace.ml`](https://github.com/janestreet/magic-trace/blob/main/src/trace.ml) | Parses the `--extra-events` CLI argument (around line 900) and wires it to `Collection_mode`. |
| [`src/perf_decode.ml`](https://github.com/janestreet/magic-trace/blob/main/src/perf_decode.ml) | Converts perf output lines into `Event_sample` records via regex matching at line 609. |
| [`src/perf_tool_backend.ml`](https://github.com/janestreet/magic-trace/blob/main/src/perf_tool_backend.ml) | Registers extra events with the kernel using `perf_event_open(2)`. |
| [`test/demo_extra_events.ml`](https://github.com/janestreet/magic-trace/blob/main/test/demo_extra_events.ml) | Example demonstrating extra event output formatting. |

## Summary

- Use `--extra-events` followed by comma-separated perf event names to enable hardware counters like `branch-misses` and `cache-misses`.
- Append `/period=<N>` to set custom sampling frequencies for fine-grained control.
- magic-trace stores samples as `Event_sample` records defined in [`src/event.ml`](https://github.com/janestreet/magic-trace/blob/main/src/event.ml).
- The backend in [`src/perf_tool_backend.ml`](https://github.com/janestreet/magic-trace/blob/main/src/perf_tool_backend.ml) configures the kernel via `perf_event_open(2)`.
- Raw samples are parsed by [`src/perf_decode.ml`](https://github.com/janestreet/magic-trace/blob/main/src/perf_decode.ml) and displayed as tracks in the Perfetto UI.

## Frequently Asked Questions

### What perf events are supported by magic-trace?

Any event name recognized by `perf list` on your Linux system works, including architectural events like `cpu-cycles`, `instructions`, `branch-misses`, and `cache-misses`, as well as vendor-specific PMU events. The `Collection_mode.Event.Name.t` type accepts arbitrary strings, so magic-trace does not maintain a hardcoded allowlist.

### How do I change the sampling rate for custom events?

Append `/period=<N>` to the event name when specifying `--extra-events`. For example, `branch-misses/period=100` instructs the kernel to record one sample every 100 branch misses. Lower values increase granularity but also overhead and trace size.

### Where does magic-trace store the raw counter values?

Counter values are stored in the `count` field of the `Event_sample` variant defined in [`src/event.ml`](https://github.com/janestreet/magic-trace/blob/main/src/event.ml) at lines 84–86. These records are emitted into the trace output and rendered as data points in the Perfetto timeline.

### Can I use custom events without modifying the magic-trace source code?

Yes. The `--extra-events` flag is exposed in the CLI ([`src/trace.ml`](https://github.com/janestreet/magic-trace/blob/main/src/trace.ml) around line 900) specifically to allow users to instrument any perf-supported hardware counter without recompilation. Simply pass the event names on the command line.