React Forum
Blog & Guide Responses
Aug 02, 2022 · 04:00 PM

[Deep Dive #17] Rendering Budgeting - discussion

Started by Ari Novak
blogrenderingbudgetperformanceaudit trailssignals

We have a few screens that "feel slow" in a way that's hard to pin down: not one expensive call, but a steady stream of small rerenders and derivations.

Read the post

Do you set explicit rendering budgets per route/surface (rerenders, derived work, fetch count), or do you just optimize when it hurts? What signals do you render to make render cost explainable (render trail, reasons, surface counts)? How do you keep budgeting from becoming "optimize everything" instead of focusing on user-visible pain?

Comments (10)

Back to latest
Evan Brooks
Aug 02, 2022 · 04:05 PM

How do you avoid budgeting turning into a perf police situation? People will just stop touching the code.

Dmitri Kline
Aug 02, 2022 · 04:14 PM

We budget per surface, not per component, and we only budget the stuff users feel (keystroke latency, navigation jitter).

The signals are the key: once you can see a render trail, you can make small fixes without blame.

Related: Performance and Rendering Best Practices and Performance Audit Trails (Deep Dive #6).

Salma Qureshi
Aug 02, 2022 · 04:26 PM

We keep a cheap render-trail signal per route and roll it up:

ts
type Trail = { surface: string; reason: string; at: number };

function pushTrail(doc: any, e: Trail) {
  const prev = (doc.read('trail') as Trail[]) ?? [];
  const next = [...prev.slice(-49), e];
  doc.write('trail', next);
  doc.write('trailAgg', aggregate(next));
}

Then the UI renders trailAgg in a tiny signals bar. It's not perfect, but it gives you a starting point.

Hana Saito
Aug 02, 2022 · 04:35 PM

Counterpoint: signals can become performance overhead if you're not careful.

We only enable full trails when a route posture key is set (like perf=profile), otherwise we keep it to counts only.

Ari Novak
Aug 02, 2022 · 04:40 PM

That seems right. I like the idea that profiling is a route posture, not a developer-only mode.

If you can share a URL that reproduces the profiling posture, debugging gets way faster.

Hana Saito
Aug 02, 2022 · 04:43 PM

Exactly. It also stops the "works on my machine" vibe because the posture is explicit.

Maya Henson
Aug 02, 2022 · 04:48 PM

We got the most win from budgeting forms. If typing feels bad, the whole app feels bad.

Keira Santos
Aug 02, 2022 · 04:56 PM

Our budgets are mostly "avoid identity churn".

A lot of React perf problems were just hooks returning unstable objects and triggering rerenders everywhere.

Amina Farouk
Aug 02, 2022 · 05:10 PM

Budgeting also prevented us from optimizing the wrong thing.

If a trail shows 30 rerenders but users don't feel it, we don't burn time. If INP is bad and the trail points to one surface, we fix that first.

Jules Kwon
Aug 02, 2022 · 05:21 PM

We made budgets part of route docs. If a route has a known expensive derivation, the doc should name it and signals should prove it isn't running on every keystroke.

Inez Park
Aug 02, 2022 · 05:36 PM

The budget isn't "no rerenders". It's rerenders that are explainable.

Benji Rios
Aug 02, 2022 · 05:49 PM

If your signals can't tell you why something rerendered, you'll end up cargo-culting memoization. Trails prevent that.