From 4dfa0371e4c86c2c41376f41afe00946a5dfc99d Mon Sep 17 00:00:00 2001 From: Florent Tapponnier Date: Fri, 29 May 2026 17:12:09 +0200 Subject: [PATCH] perf: inherit editorial copy on filtered variants instead of re-computing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #182 made every filtered variant run the per-chain Prom fan-out so {{best_name:chain:X}} could resolve in the variant's findings/faq/seoIntro. That quadrupled cold-cache Prom load per page (3 extra queries × 9 pre-fetched variants on benches like aggregator-head-lag), making cold-start visibly sluggish on Vercel preview URLs and pushing some bench loads close to the function timeout. Cleaner: editorial copy is the same on every tab (it's the same YAML), so filtered variants don't need their own per-chain compute. They inherit findings / faq / seoIntro / abstract / methodology / perChainExplainer / bestPerChain / worstPerChain from the aggregate at the page-level fetch. Per-chain compute stays on the unfiltered hub only. Net effect: page cold-start drops from 36 query sets to 9, while keeping all the chain-aware placeholders correctly resolved on every tab. --- src/app/benchmarks/[slug]/page.tsx | 26 +++++++++++++++++++++++++- src/lib/spec.ts | 18 +++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/app/benchmarks/[slug]/page.tsx b/src/app/benchmarks/[slug]/page.tsx index d92cca42..dbf9ce4c 100644 --- a/src/app/benchmarks/[slug]/page.tsx +++ b/src/app/benchmarks/[slug]/page.tsx @@ -171,7 +171,31 @@ export default async function BenchmarkPage({ ), getBenchmarks(), ]); - const variants: Record = Object.fromEntries(variantList); + // Variants only contribute chart / leaderboard / extras to the displayed + // bench (those legitimately differ per (chain, region) filter). Editorial + // copy (findings, faq, seoIntro, abstract, methodology) is the SAME on + // every tab and only resolves chain placeholders against the aggregate's + // bestPerChain/worstPerChain stash (computed unfiltered only), so we + // override these fields onto every variant. Without this, switching to + // a chain tab surfaces raw `{{best_name:chain:X}}` strings. + const variants: Record = Object.fromEntries( + variantList.map(([key, v]) => [ + key, + v === aggregate + ? v + : { + ...v, + findings: aggregate.findings, + faq: aggregate.faq, + seoIntro: aggregate.seoIntro, + abstract: aggregate.abstract, + methodology: aggregate.methodology, + perChainExplainer: aggregate.perChainExplainer, + bestPerChain: aggregate.bestPerChain, + worstPerChain: aggregate.worstPerChain, + }, + ]), + ); const benchmark = variants[variantKey(chain, region)] ?? aggregate; const isDraft = benchmark.status === "draft"; diff --git a/src/lib/spec.ts b/src/lib/spec.ts index 2df90d39..7d21ea4e 100644 --- a/src/lib/spec.ts +++ b/src/lib/spec.ts @@ -371,15 +371,15 @@ async function specToBenchmark( let bestPerChain: Record | undefined; let worstPerChain: Record | undefined; let providersPerChain: Record | undefined; - // Compute per-chain leaders for BOTH unfiltered and filtered views. - // Filtered variants are pre-fetched by the page (one per chain × region - // combo) and end up in the RSC payload; their findings/seo_intro/faq - // reference `{{best_name:chain:X}}` for ALL chains, not just the - // currently selected one, so each variant needs the full stash to - // resolve those placeholders. Cached per (slug, filterSig) via - // loadBenchmarkFiltered's unstable_cache so the extra Prom roundtrips - // are paid once per variant, not per request. - if (spec.dimensions?.chain && spec.dimensions.chain.length > 0) { + // Per-chain leaders/trailers/presence are computed ONLY on the + // unfiltered view. Earlier this also ran for filtered variants to + // populate {{best_name:chain:X}} in the variant's editorial copy, + // but that quadrupled Prom load per page (3 extra queries × 9 + // pre-fetched variants on benches like aggregator-head-lag). The + // filtered variants now inherit findings/faq/seoIntro from the + // aggregate via the page-level fetch in app/benchmarks/[slug]/page.tsx, + // so per-chain compute on filtered variants is no longer needed. + if (!isFiltered && spec.dimensions?.chain && spec.dimensions.chain.length > 0) { const chainValues = spec.dimensions.chain .map((c) => c.value) .filter((v) => v !== "all");