Share a memray report

memray answers the question top cannot: not how much memory the process is using, but which line allocated it. The capture is a binary file, and the readable artifact is whatever reporter you render from it:

memray run -o output.bin my_service.py

memray flamegraph output.bin           # → memray-flamegraph-my_service.html
memray flamegraph --leaks output.bin   # allocations still live at exit
memray table output.bin                # sortable table of the largest allocations

Each of those writes a standalone HTML file with the viewer inlined. Which is where sharing breaks down: it is a multi-megabyte single file that no chat tool will preview, most trackers will only offer as a download, and GitHub will render as raw source if you commit it.

The usual result is a screenshot of the widest frame — and a screenshot of a flame graph is exactly the part of a flame graph that carries no information.

Publish it

Drag the HTML into the app, or POST it:

memray run --native -o output.bin my_service.py
memray flamegraph --leaks -o leaks.html output.bin

curl -fsS -X POST "https://commareports.com/api/v1/reports" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html leaks.html \
        --arg t "memray leaks — ingest worker, build 4412" '{title: $t, html: $html}')"

Report content renders with scripts enabled inside a sandboxed iframe (allow-scripts, no allow-same-origin), so the reader gets the working graph: click a frame to zoom, search for a module, toggle between the allocation and the "memory at peak" views.

Publishing the leak, not the peak

The two questions look similar and want different reporters:

  • "Why is peak RSS 6 GB?"memray flamegraph output.bin. The widest frame is where the memory went.
  • "Why does RSS climb over 12 hours?"memray flamegraph --leaks, which shows only allocations that were never freed. Almost everything in the peak graph disappears, and what is left is usually short enough to fix.

Publish both onto one report as revisions and the pair reads as an argument rather than two files someone has to correlate.

From CI

Memory regressions are the ones nobody notices until an OOM kill. Capture in the job and PATCH one report id:

memray run -o output.bin -m pytest tests/test_ingest.py
memray flamegraph -o mem.html output.bin

curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html mem.html \
        --arg t "Memory — ingest suite @ $GITHUB_SHA" '{title: $t, html: $html}')"

Run it with if: always() so a failed job still leaves the capture behind — an OOM-killed run is the one whose profile you most want.

What review adds

  • Anchored threads on the allocating frame — see commenting on HTML.
  • Revisions, so "fixed in 4413" is verifiable rather than asserted.
  • Access per report — native frames expose vendored library versions and build paths. See the sharing model.

Limits

  • Entry HTML: 5 MB. memray inlines its viewer and its data, so a long --native capture is the case to watch — narrow the captured region, or publish the --leaks render, which is far smaller.
  • 60 requests/minute per token.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish a memory profile →

Related