From 1c61573c483f1b9429720e87f5b40e8645af3aa8 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Fri, 6 Jun 2025 11:24:42 -0400 Subject: [PATCH] Shorten throttle to hit a specific target metric --- ...tDOMFizzInstructionSetInlineCodeStrings.js | 4 +-- .../ReactDOMFizzInstructionSetShared.js | 34 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js b/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js index 72a5aba4fb3..6cfb4b61eda 100644 --- a/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js +++ b/packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js @@ -6,9 +6,9 @@ export const markShellTime = export const clientRenderBoundary = '$RX=function(b,c,d,e,f){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),f&&(a.cstck=f),b._reactRetry&&b._reactRetry())};'; export const completeBoundary = - '$RB=[];$RV=function(c){$RT=performance.now();for(var a=0;aa&&2E3q&&2E3 - setTimeout(resolve, SUSPENSEY_FONT_AND_IMAGE_TIMEOUT), - ), + new Promise(resolve => { + const currentTime = performance.now(); + const msUntilTimeout = + // If the throttle would make us miss the target metric, then shorten the throttle. + // performance.now()'s zero value is assumed to be the start time of the metric. + currentTime < TARGET_VANITY_METRIC && + currentTime > TARGET_VANITY_METRIC - FALLBACK_THROTTLE_MS + ? TARGET_VANITY_METRIC - currentTime + : // Otherwise it's throttled starting from last commit time. + SUSPENSEY_FONT_AND_IMAGE_TIMEOUT; + setTimeout(resolve, msUntilTimeout); + }), ]); }, types: [], // TODO: Add a hard coded type for Suspense reveals. @@ -360,8 +377,6 @@ export function clientRenderBoundary( } } -const FALLBACK_THROTTLE_MS = 300; - export function completeBoundary(suspenseBoundaryID, contentID) { const contentNodeOuter = document.getElementById(contentID); if (!contentNodeOuter) { @@ -395,8 +410,15 @@ export function completeBoundary(suspenseBoundaryID, contentID) { // to flush the batch. This is delayed by the throttle heuristic. const globalMostRecentFallbackTime = typeof window['$RT'] !== 'number' ? 0 : window['$RT']; + const currentTime = performance.now(); const msUntilTimeout = - globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - performance.now(); + // If the throttle would make us miss the target metric, then shorten the throttle. + // performance.now()'s zero value is assumed to be the start time of the metric. + currentTime < TARGET_VANITY_METRIC && + currentTime > TARGET_VANITY_METRIC - FALLBACK_THROTTLE_MS + ? TARGET_VANITY_METRIC - currentTime + : // Otherwise it's throttled starting from last commit time. + globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - currentTime; // We always schedule the flush in a timer even if it's very low or negative to allow // for multiple completeBoundary calls that are already queued to have a chance to // make the batch.