Skip to main content

mlx-profiler

Operation-level profiler for Apple Silicon / MLX. The missing torch.profiler equivalent for the MLX ecosystem.

What it gives you

  • Op-level timing — every matmul, softmax, rms_norm, layer call, etc., measured individually
  • FLOPs estimation — multiply-add counts for matmuls, convolutions
  • Arithmetic intensity — FLOPs/byte ratio per op (roofline model X-axis)
  • Memory bandwidth estimate — tensor traffic through each operation
  • Device attribution — GPU / CPU / Neural Engine breakdown
  • Terminal report — human-readable ANSI table
  • Interactive HTML dashboard — flame timeline, roofline scatter, searchable op table, category donut
  • Trace persistence — save/load JSON, render HTML from CLI

Install

pip install mlx-profiler          # without MLX (manual recording only)
pip install "mlx-profiler[mlx]"   # with MLX for automatic interception

Quick start

import mlx.core as mx
import mlx.nn as nn
import mlx_profiler as mp

model = MyTransformer()
x = mx.random.normal([1, 512])

with mp.profile("my_model") as prof:
    out = model(x)
    mx.eval(out)

prof.report()              # terminal output
prof.html("report.html")   # interactive dashboard
prof.save("trace.json")    # save for later

CLI

# Generate a demo trace + report
mlx-profiler demo

# View a saved trace in the terminal
mlx-profiler view trace.json

# Render HTML from a saved trace
mlx-profiler html trace.json -o report.html

Manual op recording (no MLX required)

from mlx_profiler.trace import Trace
from mlx_profiler.profiler import op_timer
import mlx_profiler as mp

trace = Trace("my_trace")

with op_timer(trace, "matmul",
              input_shapes=[[512, 4096], [4096, 4096]],
              output_shapes=[[512, 4096]],
              dtype="float16"):
    result = my_matmul(a, b)

mp.print_report(trace)

What's measured

Op FLOPs formula Notes
matmul / linear 2·M·K·N multiply-add counted as 2 ops
conv2d 2·Ho·Wo·Co·Ci·Kh·Kw per batch element
All ops input + output tensor bytes memory bandwidth estimate

Design notes

Why wall-clock, not Metal GPU timers?

Metal's MTLCommandBuffer.GPUStartTime gives you true on-chip execution time but requires you to instrument command buffers — not feasible when wrapping MLX's lazy evaluation model. Wall-clock with a forced mx.eval() boundary gives you "latency as the model experiences it", which is the number that matters for interactive applications. A future metal_backend module can add real GPU timers via Metal's performance counter API once the graph is materialized.

Lazy evaluation and timing

MLX uses lazy evaluation — operations aren't executed until mx.eval() is called. The profiler inserts mx.eval() calls at layer boundaries to force materialization and get accurate per-layer timing. This means profiling adds overhead; real-world timings will be slightly slower than unproduced runs.

Roadmap

  • Metal GPU timestamp counters (true on-chip time)
  • Neural Engine vs GPU attribution via os_signpost
  • Continuous batching aware profiling
  • Multi-pass aggregation (average over N forward passes)
  • FlashAttention kernel detection
  • TurboQuant / quantized op analysis
  • Comparison mode: profile A vs profile B

License

MIT

Metadata

Release files for mlx-profiler 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mlx-profiler 0.2.0
File Size Uploaded Provenance Actions
mlx_profiler-0.2.0.tar.gz 17.8 kB Without provenance Details for mlx_profiler-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mlx-profiler 0.2.0
File Interpreter ABI Platform Actions
mlx_profiler-0.2.0-py3-none-any.whl Python 3 none any Details for mlx_profiler-0.2.0-py3-none-any.whl

Total release size: 35.2 kB

Release files / mlx_profiler-0.2.0.tar.gz

Download URL mlx_profiler-0.2.0.tar.gz
Size 17.8 kB
Tags Source
SHA-256 checksum
How to use checksums
167c0821ac031c60e3042c71b64a699a81df65701dd20b8f6da99e40a97716ac
BLAKE2b-256 checksum
How to use checksums
a947127ba394da64156894adf8ea08b7b3c5f46c8dd7f9b6562aceecb0a22f97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / mlx_profiler-0.2.0-py3-none-any.whl

Download URL mlx_profiler-0.2.0-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ad8462677ade7225342a4ebc85bc8e76501f11a7806fd7c7958888f14aa85d08
BLAKE2b-256 checksum
How to use checksums
1657ca67a9a8944f6c4afe847d976b7e8ba5c40a89bb1aa3e10f9efa7aad3c07
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Security for mlx-profiler 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page