---
title: "Claude on Rust performance pitfalls"
url: https://mdfy.app/77bvsdJ4
updated: 2026-05-14T18:15:49.480Z
source: "mdfy.app"
---
# Claude on Rust performance pitfalls

> Captured chat with Claude Sonnet on 2026-04-02, after I asked it to audit our WASM rendering path. Cleaned, kept the calls I'm acting on.

## The setup

I'd been seeing the editor stutter on docs over ~30KB. The render call (comrak → WASM → JS) sat at 18-25ms p95 — not catastrophic, but mismatched with how snappy the UI should feel. So I dumped `render.rs`, `postprocess.ts`, and the perf trace into Claude and asked it to find three places we're leaving cycles on the floor.

## What Claude actually said

It went past the obvious "use `&str` more" advice and pointed at:

1. **Allocation on hot paths.** `flavor.rs` calls `String::new()` once per detection pass even when the input is unchanged. Most renders hit the same flavor twice in a row (initial mount + autosave debounce), so we're paying for an empty allocation that immediately gets dropped.
2. **Bound-checked loops in postprocess.** The per-line scan in `postprocess.ts` runs without `get_unchecked` in places where we already validated the bound. JS engines do their own bounds elision on monomorphic code, but the V8 + WASM boundary forfeits it.
3. **JSON marshalling for the syntax flavor metadata.** We re-serialise the flavor descriptor on every render. The descriptor is static across a session. One `JSON.stringify` per frame is "free" in isolation, but on a 60Hz update loop it adds up.

## What I'm doing about it

- Skipping (1) for now. The win is < 1% of total render time and the change costs LOC + readability. Filed as `FLAVOR_ALLOC_DEFER` if we ever care.
- Acting on (2) this week. The per-line loop is straightforward and the gain is measurable in the editor profile.
- Caching the flavor descriptor at module scope (fix for (3)). Tiny change, real win.

## What I'd ask differently next time

I gave Claude the trace inline. It would've spotted (1) and (3) faster if I'd also handed it the renderer's call shape — how often `render()` runs per keystroke, autosave cadence. The "what's expensive" question lands better when the upstream pattern is on the table too.
