Make a page fast
420 reads a trace to find out what a request did. This tutorial uses the trace to find which part of a slow page to cut and to check that the cut worked. The changes below are ordered by how much they usually save.
Before you start
Install from crates.io. You need no Node and no package manager.
cargo install snapfire_compiler
cargo install snapfire_fsr_cli
fsr --version
Every command and screenshot on this page was captured with fsr 0.x.
Find the slow part#
| A trace has a span per loader, per service call and per render node. Read the source spans first: they are your loaders, one row each, with the time they took. A page that takes 900ms with one loader at 870ms has a slow loader and nothing else to fix.
Three caches report themselves on those spans. A source span carries memo: hit or memo: miss when that loader is memoizable. A call span carries cache: hit or cache: miss when the method has a cache policy. A render span carries the same for the render cache. A cache: hit high in the render tree means the nodes beneath it were never rendered at all, so they have no spans. When a subtree gets shorter between two requests, the cache is working and the trace hasn't been truncated.
Don't guess from the browser. A network panel shows that the document took 900ms but can't show which of the four things the document waited on.
Memoize or prerender the page#
A route whose loader reads nothing request-specific is a candidate for the render memo; one that reads nothing at all is a candidate for prerendering. 100 covers this in full. The host works it out from what the loader reads, so to make a page memoizable, stop reading the request in it.
Often a single line causes it. A layout loader that reads session for a cart count makes every page under it per session, including the pages that have nothing to do with a cart. Move the cart count into a parallel slot with its own loader and the rest of the layout goes back to being one render for everybody.
This change usually saves the most. The fix is a file move, so it doesn't look like a performance change.
Serial awaits#
Two awaits in a row are two round trips added together:
;
;Neither needs the other, so the page waits for the sum of the two calls instead of the longer one.
If one of them is genuinely slower than the page, give it its own segment and let it stream: 140 shows how. That takes the slow call off the critical path instead of shortening it.
Cache repeated service calls#
A service method with a cache policy answers the second identical call from memory; the call span says cache: hit when it did. You set this in configuration. Check the spans before reaching for it: a call at 6ms doesn't need a cache and caching it only adds an invalidation problem.
Measure the change#
Measure before and after with the same build, the same data and the same request. Caches change the numbers, so request the page twice in each run and compare the second traces.
Compare span times, not how fast the page feels. For example, "the source span went from 870ms to 40ms".
Next up: 440. Find broken links.