Upgrade to Pro — share decks privately, control downloads, hide ads and more …

🇨🇭 ZurichJS 2026 (Workshop)

🇨🇭 ZurichJS 2026 (Workshop)

React: Internals and Advanced Performance Patterns

Keeping user interfaces smooth becomes harder as React applications scale, especially across different devices, networks, and workloads. Understanding how React actually schedules and renders work can turn performance tuning from guesswork into engineering.

In this session, we’ll dive into React Fiber and reconciliation, connecting them to classic computer science concepts like cooperative scheduling and incremental work.

From there, we’ll explore practical strategies for production React apps, along with a few browser-level primitives that influence how quickly users actually see content. Finally, we’ll look at how to measure responsiveness in the real world using modern web performance tooling.

The goal is to build the mental models that let you reason about performance problems in React and the web platform.

Avatar for Matheus Albuquerque

Matheus Albuquerque PRO

September 10, 2026

More Decks by Matheus Albuquerque

Other Decks in Programming

Transcript

  1. 𝕏 Matheus Albuquerque ↝ 👨💻 STAFF SWE @ MEDALLIA ↝

    ⚛ CHAIR @ REACT SUMMIT NYC ↝ ⚡ GOOGLE DEVELOPER EXPERT ↝ YTHECOMBINATOR
  2. POLITICAL MIX: CHINA — DECODING THE WEB IN CHINA FOR

    PEAK WEB PERFORMANCE • JODIE CHAN, 2023
  3. FRUSTRATION → STRESS 40% of Brits reported that they had

    become physically violent toward their computers. — British Psychology Society • 2009
  4. FRUSTRATION → STRESS Brainwave analysis from the experiment revealed that

    participants had to concentrate up to 50% more when using websites via the slower connection. — Study conducted by Foviance on behalf of CA • 2011
  5. FRUSTRATION → ANXIETY Delayed web pages caused a 38% rise

    in mobile users' heart rates—equivalent to the anxiety of watching a horror movie alone. — Ericsson ConsumerLab • 2015
  6. “[…] With React you can build applications without even thinking

    about performance and the default state is fast.” — Rethinking Best Practices • Pete Hunt, 2013
  7. WHAT DOES IT MEAN TO BE FAST? ↝ HOW QUICKLY

    A PAGE CAN LOAD AND RENDER ALL OF ITS VISUAL ELEMENTS TO THE SCREEN? ↝ HOW QUICKLY A PAGE CAN LOAD AND RUN ANY REQUIRED JAVASCRIPT IN ORDER FOR COMPONENTS TO RESPOND TO USER INTERACTION? ↝ DO TRANSITIONS AND ANIMATIONS RENDER AT A CONSISTENT FRAME RATE AND FLOW FLUIDLY?
  8. MAKING THINGS “FAST” PERF MITIGATORS: ↝ shouldComponentUpdate • React.PureComponent ↝

    React.memo ↝ useMemo • useCallback ↝ useTransition • useDeferredValue • React.Suspense & MUCH MORE!
  9. […] “While browsing HackerNews, I sometimes get the feeling that

    every developer out there is working for FAANG, as there are always posts from those people doing some hyped stu . Or you might think that PHP is never used nowadays because whenever it’s mentioned, everyone is hating on it in the comments.” […] f — The silent majority • Vadim Kravcenko, 2022
  10. […] “But let’s be straight, that’s like 1% of all

    of the developers out there — the rest of them are just lurking and coding with their language of choice and being content with it. Be it Fortran, COBOL, Perl, or PHP.” […] — The silent majority • Vadim Kravcenko, 2022
  11. WE’LL NOT FOCUS ON… ↝ POPULAR REACT HOOKS • (META)

    FRAMEWORKS. ↝ FINE-GRAINED REACTIVITY AND SIGNALS. ↝ ISG • SSR • STREAMING SSR • RSC. ↝ PROGRESSIVE/SELECTIVE/PARTIAL HYDRATION • ISLANDS ARCHITECTURE • RESUMABILITY. ↝ COMPILERS AND STATIC ANALYSIS.
  12. METHODOLOGY: APP HOLOTYPES Portfolio Content Storefront Social Network I Holotype

    Personal Blog CNN Amazon Facebook Figma Interactivity Minimal Linked Articles Purchase Multi-Point, Real-time Everything Session Depth Shallow Shallow Shallow - Medium Extended Deep Values Simplicity Discover-ability Load Performance Dynamicism Routing Server Server, HTML Swap HTML Swap, Hybrid Hybrid, Client Client Rendering Static Static, SSR Static, SSR SSR CSR Hydration None Progressive, Partial Partial, Resumable Any None (CSR) Frameworks 11ty Astro, Elder Marko, Qwik, Hydrogen Next, Remix Create React App I ersive ersiveness m m m m — PATTERNS FOR BUILDING JAVASCRIPT WEBSITES IN 2022 • RYAN CARNIATO
  13. METHODOLOGY: OVERVIEW ↝ REVISITING COMPUTER SCIENCE CONCEPTS. ↝ UNDERSTANDING HOW

    TOOLS WORK UNDER THE HOOD AND THE RATIONALES BEHIND THEM BY CHECKING THEIR SOURCE CODE. ↝ LEVERAGING REAL-WORLD CASE STUDIES FROM SMALL, MEDIUM, AND ENTERPRISE-SCALE COMPANIES. ↝ MICRO EXPERIMENTS AND THEIR RESULTS.
  14. This workshop is designed to empower you with the knowledge

    and tools needed to tackle a variety of complex React and front-end performance challenges in your personal and professional projects. Also, it’s meant to bridge the gap between foundational computer science concepts and practical front-end development. — React: Internals and Advanced Performance Patterns • Matheus, 2026
  15. METHODOLOGY: STEPS ↝ CLONING THE REPO NOW. ↝ GETTING THE

    SLIDES LATER. ↝ QUESTIONS AT THE END OF EACH SECTION. ↝ CONFERENCE BREAKS.
  16. THIS SECTION PRESENTS… ↝ FIBERS • COROUTINES • EFFECT HANDLERS:

    OVERVIEW • REACT.JS • OTHER ECOSYSTEMS ↝ SCHEDULING: LONG TASKS • RUNNING STRATEGIES ↝ SCHEDULING IN REACT: OVERVIEW • HEURISTICS • PRIORITY LEVELS • RENDER LANES • USE CASES ↝ SCHEDULING ON THE WEB: OVERVIEW • NATIVE SCHEDULING API
  17. STACK FRAMES function add(x,y) { const result let frame: Frame

    { return: frame, x + y; fn: add, return result; parameters: [2, 2], localVariables: { } result: 4, }, add(2, 2) = = }
  18. STACK FRAMES let frame: Frame { let fiber: Fiber {

    return: frame, return: fiber, fn: add, component: Avatar, parameters: [2, 2], props: { id: 4 }, localVariables: { state: { result: 4, isLoaded: true, }, }, = } = }
  19. FIBERS ↝ FIBER ARCHITECTURE: REACT-SPECIFIC IMPLEMENTATION OF A CALL-STACK-LIKE MODEL

    WHERE REACT HAS FULL CONTROL OF SCHEDULING WHAT SHOULD BE DONE. ↝ FIBER: A STACK FRAME FOR A REACT COMPONENT.
  20. UNITS OF WORK ONCE A TEMPLATE GOES THROUGH THE JSX

    COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  21. UNITS OF WORK ONCE A TEMPLATE GOES THROUGH THE JSX

    COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  22. UNITS OF WORK ONCE A TEMPLATE GOES THROUGH THE JSX

    COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  23. UNITS OF WORK ONCE A TEMPLATE GOES THROUGH THE JSX

    COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE.
  24. UNITS OF WORK ONCE A TEMPLATE GOES THROUGH THE JSX

    COMPILER, YOU END UP WITH A BUNCH OF REACT ELEMENTS. DURING RECONCILIATION, DATA FROM EVERY REACT ELEMENT RETURNED FROM THE RENDER METHOD IS MERGED INTO THE TREE OF FIBER NODES. DEPENDING ON THE TYPE OF A REACT ELEMENT THE FRAMEWORK NEEDS TO PERFORM DIFFERENT ACTIVITIES. EACH ELEMENT IS CONVERTED INTO A FIBER NODE THAT DESCRIBES THE WORK THAT NEEDS TO BE DONE. AND THAT MAKES IT A CONVENIENT WAY TO TRACK, SCHEDULE, PAUSE AND ABORT THE WORK.
  25. “Homoiconicity is a property of some programming languages in which

    the code used to express a program is written using the data structures of that language.” — Wikipedia
  26. HOMOICONICITY (let [x 1] (inc x)) ; 2 INCREMENTS X

    TO GIVE THE > = RETURN VALUE OF 2
  27. HOMOICONICITY IT CAN BE THOUGHT OF AS A LIST WITH

    THREE ELEMENTS: ↝ A SYMBOL NAMED LET ↝ A VECTOR WITH TWO ELEMENTS ↝ A LIST WITH TWO ELEMENTS
  28. HOMOICONICITY IT CAN BE THOUGHT OF AS A LIST WITH

    THREE ELEMENTS: ↝ A SYMBOL NAMED LET ↝ A VECTOR WITH TWO ELEMENTS A SYMBOL (X) AND AN INTEGER ↝ A LIST WITH TWO ELEMENTS A SYMBOL (INC) AND A SYMBOL (X)
  29. HOMOICONICITY + REACT ↝ REACT ELEMENTS ARE JUST DATA. ↝

    JUST LIKE IN LISP, REACT COMPONENTS CAN MANIPULATE THEIR CHILDREN AND RETURN COMPLETELY DIFFERENT THINGS.
  30. “[…] Pattern matching consists of specifying patterns to which some

    data should conform and then checking to see if it does and deconstructing the data according to those patterns.” — Learn You a Haskell
  31. PATTERN MATCHING > a - > n * factorial (n

    - 1) = factorial n = 1 = factorial 0 : (Integral a) : factorial a
  32. PATTERN MATCHING factorial factorial 0 factorial n fib (Integral a)

    fib 0 1 fib 1 1 fib n | n a a 2 > > - > = = = = > = = = : : fib (n-1) + fib (n-2)
  33. export function isWhen<Shape extends {}>( child: ElementWithMetadataUnion<Shape> ): child is

    ElementWithMetadata<WhenProps<Shape { return child.element.type === When; } export function nodesToElementWithMetadata<Shape extends {}>( children: ReactNode ) { return Children.toArray(children).map((element, idx) element: element, position: idx, })) as Array<ElementWithMetadata<Shape ; > = > > > > . . . . . . . . . / / } / / / / PATTERN MATCHING ({
  34. export function isWhen<Shape extends {}>( child: ElementWithMetadataUnion<Shape> ): child is

    ElementWithMetadata<WhenProps<Shape { return child.element.type === When; } export function nodesToElementWithMetadata<Shape extends {}>( children: ReactNode ) { return Children.toArray(children).map((element, idx) element: element, position: idx, })) as Array<ElementWithMetadata<Shape ; > = > > > > . . . . . . . . . / / } / / / / PATTERN MATCHING ({
  35. PATTERN MATCHING const supportsSensor const AmbientLight const Fallback () Boolean(window.AmbientLightSensor);

    React.lazy(() React.lazy(() import("./AmbientLight")); import("./Fallback")); export default function MyComponent() { const { Match, When, Otherwise } usePatternMatch(); return ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); > = = > = > = = = = }
  36. PATTERN MATCHING const supportsSensor () const AmbientLight const Fallback Boolean(window.AmbientLightSensor);

    React.lazy(() React.lazy(() import("./AmbientLight")); import("./Fallback")); export default function MyComponent() { const { Match, When, Otherwise } usePatternMatch(); return ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); > = = > = > = = = = } PATTERN MATCHING + REACT.SUSPENSE + REACT.LAZY() = USERS DOWNLOAD ONLY THE COMPONENT BUNDLE THAT MATCHES.
  37. PATTERN MATCHING const supportsSensor () const AmbientLight const Fallback Boolean(window.AmbientLightSensor);

    React.lazy(() React.lazy(() import("./AmbientLight")); import("./Fallback")); export default function MyComponent() { const { Match, When, Otherwise } usePatternMatch(); return ( <Suspense fallback="Loading"> <Match> <When predicate={supportsSensor}> <AmbientLight /> </When> <Otherwise> <Fallback /> </Otherwise> </Match> </Suspense> ); > = = > = > = = = = } MANIPULATING BASED ON ELEMENTS DATA. PATTERN MATCHING + REACT.SUSPENSE + REACT.LAZY() = USERS DOWNLOAD ONLY THE COMPONENT BUNDLE THAT MATCHES.
  38. FIBERS IN REACT: RECAP USING FIBERS, REACT CAN: ↝ PAUSE,

    RESUME, AND RESTART RENDERING WORK ON COMPONENTS AS NEW UPDATES COME IN. ↝ REUSE PREVIOUSLY COMPLETED WORK. ↝ SPLIT WORK INTO CHUNKS AND PRIORITIZE TASKS BASED ON IMPORTANCE.
  39. ASYNCHRONICITY IN JAVASCRIPT ↝ ASYNCHRONICITY IN JAVASCRIPT IS CONTAGIOUS. ↝

    IF ANY FUNCTION IS ASYNC, THEN EVERYTHING THAT CALLS IT MUST ALSO BE ASYNC… ↝ …AND SO ON UNTIL THE ENTIRE PROGRAM IS ASYNCHRONOUS.
  40. ASYNCHRONICITY IN JAVASCRIPT ↝ ASYNCHRONICITY IN JAVASCRIPT ISN’T FREE. ↝

    EVERY ASYNC FUNCTION CALL HAS TO: ↝ ALLOCATE CALLBACKS & STORE THEM SOMEWHERE. ↝ TAKE A TRIP BACK TO THE EVENT LOOP BEFORE INVOKING THOSE CALLBACKS.
  41. ASYNCHRONICITY & SASS ↝ ITS API HAS TWO MAIN FUNCTIONS

    FOR COMPILING SASS FILES: ONE SYNC AND ONE ASYNC. ↝ THE ASYNC ONE BECAME WIDELY USED IN PRACTICE BECAUSE IT ENABLED ASYNC PLUGINS (E.G. WEBPACK’S SASS-LOADER).
  42. ASYNCHRONICITY & SASS ↝ FOR NODE SASS, THE PERFORMANCE DIFFERENCE

    WAS NEGLIGIBLE, BECAUSE IT WAS BUILT ON C++. ↝ HOWEVER, DART SASS RUNS AS PURE JAVASCRIPT, WHICH MAKES IT SUBJECT TO JAVASCRIPT’S ASYNCHRONICITY RULES.
  43. ASYNCHRONICITY & SASS ↝ THE ASYNC VERSION IN DART SASS

    WAS 2-3X SLOWER THAN THE SYNC ONE. ↝ THEY STARTED USING NODE-FIBERS TO IMPLEMENT THE ASYNC API USING THE FAST, SYNC, CODE.
  44. FIBERS OUT THERE ↝ A FIBER IS A LIGHTWEIGHT, COOPERATIVE,

    CONCURRENT EXECUTION UNIT. ↝ FIBERS ARE A COMMON RESOURCE IN SOME OPERATING SYSTEMS AND IN SOME PROGRAMMING LANGUAGES. ↝ RUNTIMES USUALLY INCLUDE A SCHEDULER THAT SCHEDULES THE EXECUTION OF FIBERS.
  45. “This attitude does not only work in the context of

    the game industry, though. Any other industry with strong architectural requirements can be a source of inspiration and knowledge for us and help us write better code on the web” An Actor, a model and an architect walk onto the web... • Surma
  46. COROUTINES IN REACT COROUTINES APPEARED WHEN WORK ON FIBER WAS

    FIRST GOING AS A SPECIFIC COMPONENT TYPE. THE IDEA BEHIND COROUTINES — AS OPPOSED TO FIBERS — WAS TO GIVE COMPONENTS EXPLICIT CONTROL OVER YIELDING AND RESUMPTION.
  47. COROUTINES VS. FIBERS FIBERS COROUTINES CONTROL IS PASSED TO A

    CONTROL IS PASSED TO THE SCHEDULER WHICH DETERMINES CALLER AND HANDLED BY WHAT TO RUN NEXT. APPLICATION CODE.
  48. COROUTINES VS. FIBERS ↝ BOTH DECIDE WHEN TO DROP CONTROL

    (AKA. YIELD). ↝ COROUTINES CAN BE USED TO IMPLEMENT FIBERS BY ALWAYS YIELDING TO A SCHEDULER COROUTINE. ↝ FIBERS CAN BE USED TO IMPLEMENT COROUTINES BY ALLOWING EACH FIBER TO COMMUNICATE TO THE SCHEDULER WHICH FIBER SHOULD BE RUN WHEN IT YIELDS.
  49. EFFECT HANDLERS APPROACH TO REASONING ABOUT COMPUTATIONAL EFFECTS IN PURE

    CONTEXTS. ↝ EFFECT: A SET OF OPERATIONS. ↝ EFFECT HANDLER: RESPONSIBLE FOR HANDLING THE SEMANTICS OF HOW TO IMPLEMENT EFFECTS.
  50. EFFECT HANDLERS: EFF (* state.eff *) type user string *

    int effect Get: user > - = effect Set: user unit
  51. EFFECT HANDLERS: EFF (* state.eff *) type user string *

    int effect Get: user > - = effect Set: user unit A USER WITH A NAME AND AGE.
  52. EFFECT HANDLERS: EFF (* state.eff *) type user string *

    int WE DEFINE EFFECTS WITH THE effect effect Get: user > - = effect Set: user unit KEYWORD AND A TYPE SIGNATURE.
  53. EFFECT HANDLERS: EFF let state | y handler fun currentState

    | effect Get k (y, currentState) (fun currentState | effect (Set newState) k (fun _ > > - - > - > - > - = > - ;; (continue k currentState) currentState) (continue k ()) newState)
  54. EFFECT HANDLERS: EFF WE HAVE A handler WITH THREE BRANCHES,

    AND ALL OF THEM RETURN A FUNCTION. let state | y handler fun currentState | effect Get k (y, currentState) (fun currentState | effect (Set newState) k (fun _ > > - - > - > - > - = > - ;; (continue k currentState) currentState) (continue k ()) newState)
  55. EFFECT HANDLERS: EFF NO EFFECT (WHEN WE REACH THE END

    OF THE BLOCK). y IS THE RETURN VALUE. let state | y handler fun currentState | effect Get k (y, currentState) (fun currentState | effect (Set newState) k (fun _ > > - - > - > - > - = > - ;; (continue k currentState) currentState) (continue k ()) newState)
  56. EFFECT HANDLERS: EFF let state | y handler fun currentState

    | effect Get k (y, currentState) (fun currentState | effect (Set newState) k (fun _ ;; > > - - > - > - > - = > - MATCHING OUR EFFECTS. (continue k currentState) currentState) (continue k ()) newState)
  57. EFFECT HANDLERS: EFF let state | y handler fun currentState

    | effect Get k (y, currentState) (fun currentState | effect (Set newState) k (fun _ (continue k currentState) currentState) (continue k ()) newState) ;; k IS A CONTINUATION. IT REPRESENTS THE REST OF THE > > - - > - > - > - = > - COMPUTATION AFTER WHERE WE PERFORM AN EFFECT.
  58. function getName(user) { let name user.name; if (name === null)

    { name perform 'ask_name'; } return name; } const arya const gendry { name: null, friendNames: [] }; { name: 'Gendry', friendNames: [] }; try { getName(arya); } handle (effect) { if (effect === 'ask_name') { resume with 'Arya Stark'; } = = = = }
  59. function getName(user) { let name user.name; if (name === null)

    { name perform 'ask_name'; } return name; } const arya const gendry { name: null, friendNames: [] }; { name: 'Gendry', friendNames: [] }; try { getName(arya); } handle (effect) { if (effect === 'ask_name') { resume with 'Arya Stark'; } = = = = }
  60. function getName(user) { let name user.name; if (name === null)

    { name perform 'ask_name'; } THROW → PERFORM return name; } const arya const gendry { name: null, friendNames: [] }; { name: 'Gendry', friendNames: [] }; try { getName(arya); } handle (effect) { CATCH → HANDLE if (effect === 'ask_name') { resume with 'Arya Stark'; } = = = LETS US JUMP BACK TO WHERE WE PERFORMED THE EFFECT. = }
  61. EFFECT HANDLERS ↝ IT DOESN'T REALLY MATTER HOW WE HOLD

    STATE. ↝ WITH PROMISES, IF WE WERE TO CHANGE IN THE FUTURE, THAT’D REQUIRE CHANGES ACROSS EVERYTHING. ↝ WITH ALGEBRAIC EFFECTS, WE CAN SIMPLY STOP THE CURRENT PROCESS ALTOGETHER UNTIL OUR EFFECTS ARE FINISHED.
  62. LAYOUT ALGORITHM THE REACT TEAM APPARENTLY SPENT SOME TIME EXPERIMENTING

    WITH EFFECT-HANDLER CONTROL STRUCTURES FOR MANAGING LAYOUT.
  63. function ThemeBorderColorRequest() { } function FancyBox(children) { const color raise

    new ThemeBorderColorRequest(); return { borderWidth: '1px', borderColor: color, children: children }; } function BlueTheme(children) { return try { children(); } catch effect ThemeBorderColorRequest continuation('blue'); } } function App(data) { return BlueTheme( FancyUserList.bind(null, data.users) ); > - = } [, continuation] {
  64. function ThemeBorderColorRequest() { } function FancyBox(children) { const color raise

    new ThemeBorderColorRequest(); return { THROW → RAISE borderWidth: '1px', borderColor: color, children: children }; } function BlueTheme(children) { return try { children(); } catch effect ThemeBorderColorRequest continuation('blue'); } } function App(data) { return BlueTheme( FancyUserList.bind(null, data.users) ); > - = } CATCH → CATCH EFFECT [, continuation] {
  65. HOOKS API ↝ ALGEBRAIC EFFECTS = A SET OF OPERATIONS

    AND A SET OF EFFECT HANDLERS. ↝ THE OPERATIONS HERE ARE OUR HOOKS (E.G. useState, useEffect, AND SO ON). ↝ WE HAVE TO SET UP HANDLERS IN EFF; IN REACT THEY'RE SET UP AS PART OF THE RENDER CYCLE.
  66. HOOKS API ↝ REACT IS RESPONSIBLE FOR MUCH OF THE

    IMPLEMENTATION OF WHEN/HOW OUR EFFECTS RUN. ↝ BY SPLITTING EFFECTS AND RENDERING, WE ALLOW IT TO RELIEVE US OF SOME COMPLEXITY.
  67. SUSPENSE INTERNALS A COMPONENT IS ABLE TO SUSPEND THE FIBER

    IT IS RUNNING IN BY THROWING A PROMISE, WHICH IS CAUGHT AND HANDLED BY THE FRAMEWORK.
  68. SUSPENSE INTERNALS A COMPONENT IS ABLE TO SUSPEND THE FIBER

    IT IS RUNNING IN BY THROWING A PROMISE, WHICH IS CAUGHT AND HANDLED BY THE FRAMEWORK. THROW → HANDLE → RESUME PATTERN.
  69. TASKS A UNIT OF WORK THAT THE BROWSER DOES TO

    RENDER A FRAME. JAVASCRIPT STYLES LAYOUT PAINT COMPOSITE
  70. LONG TASKS ↝ IF A TASK TAKES MORE THAN 50

    MS, USER INPUT FEELS DELAYED. ↝ BASED ON THE USER-CENTRIC PERFORMANCE MODEL CALLED RAIL. ↝ THEY TAKE TOO LONG AND BLOCK OTHER TASKS.
  71. TASK RUNNING STRATEGIES ↝ PARALLELISM: MULTIPLE THREADS = MULTIPLE TASKS

    AT THE SAME TIME ON SEPARATE CPU CORES. ↝ CONCURRENCY: SINGLE THREAD + QUICKLY SWITCHING BETWEEN TASKS. ↝ SCHEDULING: CONCURRENCY + TASK PRIORITIZATION.
  72. WEB WORKERS ↝ DATA EXCHANGE IS THROUGH MESSAGE-PASSING. ↝ NO

    ACCESS TO ANY VARIABLES/CODE FROM THE PAGE THAT CREATED THEM OR VICE VERSA. ↝ NO ACCESS TO THE DOM, MAKING UI UPDATES FROM A WORKER BARELY IMPOSSIBLE. ↝ TWO MODELS: ACTORS & SHARED MEMORY.
  73. WEB WORKERS: ACTORS ↝ EACH ACTOR MAY OR MAY NOT

    RUN ON A SEPARATE THREAD AND FULLY OWNS THE DATA IT IS OPERATING ON. ↝ ACTORS CAN ONLY SEND/REACT TO MESSAGES. ↝ MAIN THREAD = ACTOR THAT OWNS THE DOM/UI.
  74. WEB WORKERS: ACTORS ↝ EVERY MESSAGE WE SEND NEEDS TO

    BE COPIED. ↝ BALANCE: MOVING CODE TO A WORKER VS COMMUNICATION OVERHEAD/WORKER BEING BUSY. ↝ postMessage IS A FIRE-AND-FORGET MESSAGING MECHANISM WITH NO BUILT-IN UNDERSTANDING OF REQUEST AND RESPONSE.
  75. WEB WORKERS: ACTORS ↝ ONE DEDICATED TYPE: SharedArrayBuffer. ↝ A

    LINEAR CHUNK OF MEMORY THAT CAN BE MANIPULATED USING TypedArrays OR DataViews. ↝ IF SENT VIA postMessage, THE OTHER END GETS A HANDLE TO THE EXACT SAME MEMORY CHUNK.
  76. WEB WORKERS: ACTORS ↝ MOST OF THE APIS ARE BUILT

    NO CONCURRENT ACCESS TO OBJECTS IN MIND. ↝ YOU BUILD YOUR OWN MUTEX ABSTRACTIONS AND OTHER CONCURRENT DATA STRUCTURES. ↝ NO DIRECT WAY OF WORKING ON FAMILIAR OBJECTS/ ARRAYS; JUST A SERIES OF BYTES.
  77. WORKERS: WEB ASSEMBLY ↝ WORKERS + SharedArrayBuffers TO SUPPORT THE

    THREADING MODEL OF C++ AND OTHERS. ↝ THE BEST EXPERIENCE FOR SHARED-MEMORY MODEL. ↝ FASTER THAN JS WHEN YOU STAY WITHIN WASM, BUT THE MORE YOU HAVE TO CROSS OVER TO JS APIS THE SLOWER IT IS.
  78. WORKERS: WEB ASSEMBLY ↝ JAVASCRIPT IS OFTEN FASTER AT DOING

    DOM RENDERING. ↝ HIGH-LEVEL LIBRARIES CAN BE MORE PERFORMANT THAN LOW-LEVEL WASM IMPLEMENTATIONS. ↝ DOESN’T OFFER LOT OF THE BENEFITS (AND COMFORT) OF JAVASCRIPT.
  79. PARALLELISM IS GREAT! ↝ GOOD FOR DATA PROCESSING AND CRUNCHING

    NUMBERS. ↝ HARD TO USE FOR UI-RELATED STUFF. ↝ HARDER THAN ADJUSTING IT FOR A SCHEDULER.
  80. function* resourcefulOperation(value: number) { let newValue String(value); while (true) {

    YIELDING EXECUTION yield; for (let i newValue PROMOTED TO A GENERATOR 0; i < 1000000; i++) { `${value} + ${i} ${value + i}`; } return newValue; } } const initialValue const scheduler 0; new Scheduler(resourcefulOperation, initialValue); function ResourcefulComponent(props: { value: number }) { const { value } const result props; scheduler.performUnitOfWork(value); return <p>{result}</p>; = = = = = = = = } DOING CONCURRENT TASKS
  81. SCHEDULING WITH… OUR SCHEDULER function resourcefulOperation(value: number) { let newValue

    for (let i String(value); 0; i < 1000000; i++) { newValue `${value} + ${i} ${value + i}`; } return newValue; } function ResourcefulComponent(props: { value: number }) { const { value } const result props; resourcefulOperation(value); return <p>{result}</p>; = = = = = = }
  82. SCHEDULING WITH… OUR SCHEDULER function resourcefulOperation(value: number) { let newValue

    for (let i String(value); 0; i < 1000000; i++) { newValue `${value} + ${i} ${value + i}`; } return newValue; } function ResourcefulComponent(props: { value: number }) { const [_, startTransition] useTransition(); const [result, setResult] useState(""); useEffect(() { startTransition(() const newResult { resourcefulOperation(props.value); setResult(newResult); }); }, [props.value]); return <p>{result}</p>; > = = = = = > = = = = }
  83. HEURISTICS ↝ A COOPERATIVE MULTITASKING MODEL. ↝ A SINGLE INTERRUPTIBLE

    RENDERING THREAD. ↝ RENDERING CAN BE INTERLEAVED WITH OTHER MAIN THREAD TASKS AND OTHER REACT RENDERS. ↝ AN UPDATE CAN HAPPEN IN THE BACKGROUND WITHOUT BLOCKING THE RESPONSE TO NEW INPUT.
  84. HEURISTICS USER INPUT → ↓ ORIGINAL RENDER TASK ↓ RESUME

    ORIGINAL RENDER TASK ↑ HIGHER PRIORITY RENDER TASK
  85. HEURISTICS ↝ IT YIELDS EXECUTION IS BACK TO THE MAIN

    THREAD EVERY 5MS. ↝ IT'S SMALLER THAN A SINGLE FRAME EVEN ON 120FPS, SO IT WON'T BLOCK ANIMATIONS. ↝ IN PRACTICE, RENDERING IS INTERRUPTIBLE.
  86. PRIORITY LEVELS PRIORITY m m I ediate TIMEOUT SYNCHRONOUSLY UserBlocking

    250MS Normal 5S Low 10S Idle NO TIMEOUT WHEN TASKS THAT NEED TO RUN SYNCHRONOUSLY RESULTS OF A USER INTERACTION (E.G. A BUTTON CLICK) UPDATES THAT DON’T HAVE TO FEEL INSTANTANEOUS TASKS THAT CAN BE DEFERRED BUT MUST STILL COMPLETE EVENTUALLY (E.G. AN ANALYTICS NOTIFICATION) TASKS THAT DO NOT HAVE TO RUN AT ALL (E.G. HIDDEN OFFSCREEN CONTENT)
  87. RENDER LANES ↝ ONE LANE: ONE BIT IN A BITMASK.

    ↝ ONE UPDATE IN REACT: ONE LANE. ↝ ONE RENDER IN REACT: ONE OR MORE LANES. ↝ UPDATES IN THE SAME LANE: RENDER IN THE SAME BATCH. ↝ DIFFERENT LANES: SEPARATE BATCHES.
  88. RENDER LANES ↝ 31 LEVELS OF GRANULARITY (= ONE BITMASK).

    ↝ ALLOWS TO CHOOSE WHETHER TO RENDER MULTIPLE TRANSITIONS IN A SINGLE BATCH OR RENDER THEM INDEPENDENTLY. ↝ REDUCES OVERHEAD OF MULTIPLE LAYOUT PASSES, STYLE RECALCULATIONS, AND MULTIPLE PAINTS.
  89. HANDLING LARGE SETS OF DATA 😔 NON-PRACTICAL… 😊 PRACTICAL… ↝

    FINDING PRIMES ↝ RENDERING MANY DATA-POINTS ↝ CRACKING PASSWORDS ↝ PROCESSING DATA ↝ SIERPINSKI TRIANGLE ↝ RENDERING ON A <canvas>
  90. HANDLING LARGE SETS OF DATA 😔 NON-PRACTICAL… 😊 PRACTICAL… ↝

    FINDING PRIMES ↝ RENDERING MANY DATA-POINTS ↝ CRACKING PASSWORDS ↝ PROCESSING DATA ↝ SIERPINSKI TRIANGLE ↝ RENDERING ON A <canvas>
  91. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS LOCATION DATA ↝ ˜100K

    DATA POINTS PLOTTED #1 ↝ SUPPORT FOR SEARCHING AND FILTERING. ↝ USED WORKERS + REDUX-SAGA UTILITIES + DEBOUNCING. ↝ COULD'VE USED TRANSITIONS.
  92. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS GAME ADMIN PANEL ↝

    THOUSANDS OF REAL-TIME #2 PLAYERS MESSAGING. ↝ SUPPORT FOR SEARCHING AND FILTERING. ↝ USED VIRTUALIZATION AND MEMOIZATION. ↝ COULD'VE USED TRANSITIONS.
  93. useSyncExternalStore function useSyncExternalStore<Snapshot>( subscribe: (onStoreChange: () getSnapshot: () void) ()

    Snapshot, getServerSnapshot?: () Snapshot > = > = > = > = > = ): Snapshot; void,
  94. useLocation function Pathname() { const { pathname } useLocation(); return

    <Badge title={pathname} subtitle="pathname" />; } function Hash() { const { hash } useLocation(); return <Badge title={hash} subtitle="hash" />; = = }
  95. useLocation function Pathname() { const { pathname } useLocation(); return

    <Badge title={pathname} subtitle="pathname" />; } function Hash() { const { hash } useLocation(); return <Badge title={hash} subtitle="hash" />; = = }
  96. useHistorySelector function useHistorySelector(selector) { const history useHistory(); return useSyncExternalStore(history.listen, ()

    selector(history)); } function Pathname() { const pathname useHistorySelector((history) history.location.pathname); return <Badge title={pathname} subtitle="pathname" />; } function Hash() { const hash useHistorySelector((history) history.location.hash); return <Badge title={hash} subtitle="hash" />; > = > = > = = = = }
  97. useHistorySelector function useHistorySelector(selector) { const history useHistory(); return useSyncExternalStore(history.listen, ()

    selector(history)); } function Pathname() { const pathname useHistorySelector((history) history.location.pathname); return <Badge title={pathname} subtitle="pathname" />; } function Hash() { const hash useHistorySelector((history) history.location.hash); return <Badge title={hash} subtitle="hash" />; > = > = > = = = = }
  98. …AND MUCH MORE! function subscribe(callback) { window.addEventListener('online', callback); window.addEventListener('offline', callback);

    return () { window.removeEventListener('online', callback); window.removeEventListener('offline', callback); }; } function getSnapshot() { return navigator.onLine; > = }
  99. …AND MUCH MORE! import { useSyncExternalStore } from 'react'; function

    OnlineStatus() { const isOnline useSyncExternalStore( subscribe, getSnapshot, getSnapshot ); return ( <div className={isOnline ? 'online' : 'offline'}> {isOnline ? '🟢 Online' : '🔴 Offline'} </div> ); = }
  100. NATIVE SCHEDULING: CURRENT ISSUES ↝ NO PRIORITY CONTROL. ↝ NO

    CANCELLATION SEMANTICS. ↝ NO COORDINATION WITH THE BROWSER SCHEDULER. ↝ NO INPUT RESPONSIVENESS GUARANTEES. ↝ NO WAY TO BREAK LONG TASKS SAFELY.
  101. SCHEDULE TASKS: OVERVIEW ↝ SCHEDULE TASKS WITH EXPLICIT PRIORITY. ↝

    COORDINATE WITH THE BROWSER RENDERING PIPELINE. ↝ REPLACE setTimeout( , 0) HACKS. ↝ SUPPORTS CANCELLATION VIA SIGNALS. . . . ↝ WORKS IN WORKERS TOO.
  102. YIELDING: OVERVIEW ↝ SPLIT LONG TASKS SAFELY. ↝ RETURN CONTROL

    TO THE BROWSER MID-EXECUTION. ↝ CONTINUE LATER WITH THE SAME PRIORITY. ↝ AVOID BLOCKING INPUT AND RENDERING. ↝ REPLACE MANUAL CHUNKING LOOPS.
  103. PENDING INPUT: OVERVIEW while (workQueue.length > 0) { if (navigator.scheduling.isInputPending())

    { Stop doing work to handle any input event break; } let job workQueue.shift(); job.execute(); = / / }
  104. CASE STUDY: INTERNAL TOOLING A TOOL TO SPEED UP REPRODUCTION

    → DEBUGGING → FIXING TIME IN CUSTOMERS ESCALATIONS WITH : ↝ A CONSIDERABLE AMOUNT OF CUSTOM CODE. ↝ A CONSIDERABLE AMOUNT OF CUSTOM DESIGN PRIMITIVES. ↝ SANDBOX ⨯ PRODUCTION DISCREPANCIES.
  105. PREDICT WORK ↝ MANY PERFORMANCE OPTIMIZATIONS CAN BE MADE WHEN

    WE CAN PREDICT WHAT USERS MIGHT DO. ↝ THERE ARE A FEW SIMPLE BUT EFFECTIVE WAYS FOR DEVELOPERS TO HELP THE BROWSER STAY ONE STEP AHEAD OF THE USER AND KEEP PAGES FAST.
  106. PREDICT WORK: IDEAS ↝ PREDICT TAB NAVIGATION IN DASHBOARDS. ↝

    PREFETCH THE NEXT ROUTE AFTER LOGIN SUCCESS. ↝ PRECONNECT ANALYTICS ENDPOINTS AFTER CONSENT. ↝ PRERENDER CHECKOUT AFTER CART INTERACTION. ↝ PREFETCH THE NEXT ARTICLE WHEN THE READER SCROLLS 75%.
  107. PRECONNECT: OVERVIEW ↝ IT ALLOWS THE BROWSER TO SET UP

    EARLY CONNECTIONS BEFORE THE REQUEST IS ACTUALLY SENT TO THE SERVER. THIS INCLUDES: ↝ TLS NEGOTIATIONS ↝ TCP HANDSHAKES ↝ ELIMINATES ROUND-TRIP LATENCY.
  108. PRECONNECT: OVERVIEW 100MS 200MS 300MS 400MS 500MS 600MS 700MS HTML

    CSS FONT 1 FONT 2 FONTS START LOADING FONTS RENDERED
  109. PRECONNECT: OVERVIEW 100MS 200MS 300MS 400MS 500MS 600MS HTML CSS

    FONT 1 FONT 1 FONT 2 FONTS START LOADING FONT 2 FONTS RENDERED 700MS
  110. PRECONNECT: IDEAS PRECONNECT: ↝ GOOGLE FONTS BEFORE CSS LOADS. ↝

    THE API ORIGIN AFTER LOGIN SUCCESS. ↝ THE CDN HOSTING HERO IMAGE. ↝ THE ANALYTICS ENDPOINT AFTER CONSENT. ↝ THE CHECKOUT DOMAIN FROM THE PRODUCT PAGE.
  111. SPECULATION RULES: OVERVIEW ↝ DESIGNED TO IMPROVE PERFORMANCE FOR FUTURE

    DOCUMENT NAVIGATIONS. ↝ A MODERN AND MORE EXPRESSIVE REPLACEMENT FOR OLDER PRERENDER TECHNIQUES. ↝ PREFETCH/PRERENDER DOCUMENTS AHEAD OF CLICKS. ↝ WORKS BEST FOR MPAS OR ROUTE-LEVEL TRANSITIONS.
  112. SPECULATION RULES: OVERVIEW <script type="speculationrules"> { "prefetch": [{ "source": "list",

    "urls": ["/checkout"] }] } </script> <script type="speculationrules"> { "prerender": [{ "where": { "href_matches": "/product/ " } }] } * </script>
  113. SPECULATION RULES: IDEAS ↝ PREFETCH /DASHBOARD AFTER LOGIN SUCCESS. ↝

    PREFETCH /CHECKOUT AFTER CART INTERACTION. ↝ PREFETCH TOP RESULT LINKS IN THE VIEWPORT. ↝ PRERENDER LIKELY NEXT SETTINGS TAB.
  114. PRIORITY HINTS: OVERVIEW ↝ TELL THE BROWSER WHAT MATTERS FIRST.

    ↝ OVERRIDE DEFAULT FETCH HEURISTICS WHEN NEEDED. ↝ OPTIMIZE LCP RESOURCES EXPLICITLY.
  115. Increase the priority of the LCP image <img src="image.jpg" fetchpriority="high"

    /> Lower the priority of above-the-fold images <ul class="carousel"> <img src="img/carousel-1.jpg" fetchpriority="high" /> <img src="img/carousel-2.jpg" fetchpriority="low" /> <img src="img/carousel-3.jpg" fetchpriority="low" /> </ul> Reprioritize scripts <script src="async_but_important.js" async fetchpriority="high"></script> > - - > - - > - - - - - - - - ! ! <script src="blocking_but_unimportant.js" fetchpriority="low"></script> ! < < < PRIORITY HINTS: OVERVIEW
  116. Increase the priority of the LCP image <img src="image.jpg" fetchpriority="high"

    /> Lower the priority of above-the-fold images <ul class="carousel"> <img src="img/carousel-1.jpg" fetchpriority="high" /> <img src="img/carousel-2.jpg" fetchpriority="low" /> <img src="img/carousel-3.jpg" fetchpriority="low" /> </ul> Reprioritize scripts <script src="async_but_important.js" async fetchpriority="high"></script> > - - > - - > - - - - - - - - ! ! <script src="blocking_but_unimportant.js" fetchpriority="low"></script> ! < < < PRIORITY HINTS: OVERVIEW
  117. Important validation data const user await fetch("/user"); Less important content

    data = = / const relatedPosts / / / PRIORITY HINTS: OVERVIEW await fetch("/posts/suggested", { priority: "low" });
  118. Important validation data const user await fetch("/user"); Less important content

    data = = / const relatedPosts / / / PRIORITY HINTS: OVERVIEW await fetch("/posts/suggested", { priority: "low" });
  119. PRIORITY HINTS: IDEAS ↝ BOOST HERO IMAGE PRIORITY. ↝ PRIORITIZE

    ROUTE TRANSITION BUNDLES. ↝ DEPRIORITIZE RECOMMENDATION PANELS. ↝ DEPRIORITIZE BELOW-FOLD IMAGES. ↝ CONTROL HYDRATION FETCH ORDERING.
  120. NATIVE LAZY LOADING: OVERVIEW ↝ ZERO JAVASCRIPT. ↝ DEFER IMAGE

    AND IFRAME DOWNLOADS AUTOMATICALLY. ↝ LET THE BROWSER DECIDE OPTIMAL FETCH TIMING. ↝ REMOVE OFF-SCREEN CONTENT FROM THE CRITICAL RENDERING PATH.
  121. NATIVE LAZY LOADING: OVERVIEW <img src="/gallery-1.jpg" loading="lazy" width="800" height="600" />

    <iframe src="https://maps.example.com" loading="lazy" width="600" height="400"> </iframe>
  122. NATIVE LAZY LOADING: IDEAS ↝ PRODUCT GALLERY IMAGES. ↝ EMBEDDED

    YOUTUBE PLAYERS. ↝ MAPS AND CHAT WIDGETS. ↝ ANALYTICS DASHBOARDS BELOW THE FOLD. ↝ ROUTE-LEVEL IFRAMES IN MICRO-FRONTENDS.
  123. “Lazy-loading iframes can lead to 2-3% median data savings, 1-2%

    FCP reductions, and 2% FID improvements at the 95th percentile.” Chrome team’s research • 2019
  124. SMOOTH NAVIGATION: CONTEXT ↝ SURVEY FATIGUE IS A WELL-DOCUMENTED PHENOMENON

    THAT LEADS TO ABANDONMENT AND INCOMPLETE RESPONSES. ↝ LONG SURVEYS CAN SEE COMPLETION RATES DROP DRAMATICALLY AS THE NUMBER OF QUESTIONS AND PAGES INCREASES.
  125. #insight 💡 What if we could make survey navigation feel

    less like page loads and more like a conversation?
  126. SMOOTH NAVIGATION: OVERVIEW ↝ ANIMATE TRANSITIONS BETWEEN DOM STATES. ↝

    WORKS ACROSS SPA AND MPA NAVIGATION. ↝ MAINTAINS USER CONTEXT DURING CHANGE. ↝ REDUCES PERCEIVED LATENCY.
  127. SMOOTH NAVIGATION: IDEAS ↝ ANIMATE LIST → DETAIL NAVIGATION. ↝

    SMOOTH DASHBOARD TAB SWITCHING. ↝ PRESERVE ELEMENT CONTINUITY BETWEEN ROUTES. ↝ REDUCE PERCEIVED LAYOUT SHIFT. ↝ MAKE MPAS FEEL LIKE NATIVE APPS.
  128. Hunt esley ject L y b ro ed Creat he

    Noun P t m fro SMOOTH SMOOTH NAVIGATION: NAVIGATION: CONTEXT MPA — CROSS-DOCUMENT VIEW TRANSITIONS FOR MULTI-PAGE APPLICATIONS • BRAMUS
  129. PREACT: OVERVIEW ↝ WAY SMALLER BUNDLE (APPROXIMATELY 3.5KB). ↝ FASTER

    VIRTUAL DOM IMPLEMENTATION. ↝ MORE EFFECTIVE MEMORY USAGE.
  130. PREACT: CASE STUDY 205.9KB 175.26KB MIN + GZIP / NO

    POLYFILLS MIN + GZIP / NO POLYFILLS
  131. PRESERVE NAVIGATION: OVERVIEW ↝ RESTORE PAGES INSTANTLY ON BACK/FORWARD NAVIGATION.

    ↝ KEEP DOM + JAVASCRIPT HEAP ALIVE IN MEMORY. ↝ ELIMINATE RELOAD ENTIRELY. ↝ TURN NAVIGATION INTO RESTORATION.
  132. PRESERVE NAVIGATION: MONITOR window.addEventListener('pageshow', (event) { if (event.persisted) { console.log('This

    page was restored from the bfcache.'); } else { console.log('This page was loaded normally.'); } > = });
  133. PRESERVE NAVIGATION: MONITOR window.addEventListener('pagehide', (event) { if (event.persisted) { console.log('This

    page might be entering the bfcache.'); } else { console.log('This page will unload normally and be discarded.'); } > = });
  134. PRESERVE NAVIGATION: MONITOR new PerformanceObserver(list { for (const entry of

    list.getEntries()) { console.log(entry.notRestoredReasons); } > = }).observe({ type: "navigation", buffered: true });
  135. DATA-ORIENTED DESIGN ↝ A COLLECTION OF TECHNIQUES TO ANALYZE THE

    ACCESS PATTERNS OF THE DIFFERENT KINDS OF DATA AND SELECT DATA STRUCTURES THAT OPTIMALLY LEVERAGE THE UNDERLYING HARDWARE. ↝ THE OPTIMIZATIONS ARE OFTEN RELATED TO OPTIMIZING USAGE OF THE CPU CACHE, LIMITING LOADING/STORING TO RAM (CACHE MISSES), AND USAGE OF SIMD INSTRUCTIONS.
  136. BECAUSE… CPUs ARE FAST ↝ BASIC MATH CAN BE DONE

    IN A FEW CYCLES. ↝ COMPLEX MATH REQUIRES A FEW MORE CYCLES—BUT IT’S STILL OK. ↝ SIMD MAKES THE THROUGHPUT EVEN BETTER BY PROCESSING MULTIPLE VALUES IN THE TIME IT TAKES TO DO A SINGLE INSTRUCTION.
  137. BUT… MEMORY IS NOT AS FAST ↝ CPUS CAN ONLY

    OPERATE ON DATA THAT IS PHYSICALLY CO-LOCATED. ↝ EITHER IN A REGISTER OR IN THE L1 CACHE. ↝ EVERYTHING ELSE NEEDS TO BE LOADED FIRST.
  138. BUT… MEMORY IS NOT AS FAST CPU MEMORY 4 NS

    ⇆ 0.5 NS ⇆ 100 NS ⇆ L2 CACHE L1 CACHE
  139. BUT… MEMORY IS NOT AS FAST ↝ MEMORY ACCESS IS

    SLOW. ↝ CACHING CAN ALLEVIATE MOST OF THE LATENCY IF THE CPU CAN PREDICT THE ACCESS PATTERN—USUALLY, THE SIMPLE ONES. ↝ LINEAR PATTERNS ARE USUALLY GOOD. ↝ RANDOM PATTERNS ARE USUALLY BAD.
  140. ⨯ AOS SOA ARRAY OF STRUCTURES type Entity = {

    STRUCTURE OF ARRAYS const positions = new Float32Array([0, 0, 10, 5 / position: { x: number; y: number }; const velocities = new Float32Array([1, 1, -1, 0 / velocity: { x: number; y: number }; const hitPoints = new Int16Array([100, 80 / hitPoints: number; }; const i = 0; const entities: Entity[] = [ { position: { x: 0, y: 0 }, velocity: { x: 1, y: 1 }, hitPoints: 100 }, { position: { x: 10, y: 5 }, velocity: { x: -1, y: 0 }, hitPoints: 80 }, * * / * . . . / / console.log(velocities[i * 2], velocities[i * 2 + 1]); console.log(hitPoints[i]); ]; / console.log(positions[i * 2], positions[i * 2 + 1]);
  141. ARRAY OF STRUCTURES type Entity = { position: { x:

    number; y: number }; velocity: { x: number; y: number }; }; const positions = new Float32Array([0, 0, 10, 5 / /]); const velocities = new Float32Array([1, 1, -1, 0 / /]); /]); Entity i = index in all arrays const i = 0; const entities: Entity[] = [ { position: { x: 0, y: 0 }, velocity: { x: 1, y: 1 }, hitPoints: 100 }, { position: { x: 10, y: 5 }, velocity: { x: -1, y: 0 }, hitPoints: 80 }, console.log(positions[i * 2], positions[i * 2 + 1]); console.log(velocities[i * 2], velocities[i * 2 + 1]); console.log(hitPoints[i]); * * . / . . / . . . * * * . . . * ]; . STRUCTURE OF ARRAYS const hitPoints = new Int16Array([100, 80 / hitPoints: number; / / ⨯ AOS SOA x, y
  142. ⨯ AOS SOA ARRAY OF STRUCTURES STRUCTURE OF ARRAYS ✅

    EASY TO READ, WRITE, AND MODEL FOR US. ✅ EXCELLENT DATA LOCALITY. ✅ ENTITIES ARE INTUITIVE BUNDLES. ✅ CACHE-FRIENDLY + SIMD ACCELERATION POSSIBLE. ❌ POOR DATA LOCALITY. ✅ PARALLELIZABLE: SYSTEMS OPERATE ON “COLUMNS” INDEPENDENTLY. ❌ ITERATING OVER MILLIONS SCALES BADLY. ❌ LESS INTUITIVE FOR DEVS USED TO OBJECTS. ❌ HARD TO PARALLELIZE BECAUSE DATA IS INTERLEAVED. ❌ HARDER TO DEBUG AN ENTITY.
  143. ⨯ AOS SOA ARRAY OF STRUCTURES STRUCTURE OF ARRAYS ✅

    EASY TO READ, WRITE, AND MODEL FOR US. ✅ EXCELLENT DATA LOCALITY. ✅ ENTITIES ARE INTUITIVE BUNDLES. ✅ CACHE-FRIENDLY + SIMD ACCELERATION POSSIBLE. ❌ POOR DATA LOCALITY. ✅ PARALLELIZABLE: SYSTEMS OPERATE ON “COLUMNS” INDEPENDENTLY. ❌ ITERATING OVER MILLIONS SCALES BADLY. ❌ LESS INTUITIVE FOR DEVS USED TO OBJECTS. ❌ HARD TO PARALLELIZE BECAUSE DATA IS INTERLEAVED. ❌ HARDER TO DEBUG AN ENTITY.
  144. ARRAY OF STRUCTURES UNITS 0 ⇢ 2 X Y DX

    DY HP X Y DX DY HP X Y DX DY HP HP X Y DX DY HP HP X Y DX DY HP UNITS 3 ⇢ 5 X Y DX DY HP X Y DX DY UNITS … ⇢ N X Y DX DY HP X Y DX DY
  145. ARRAY OF STRUCTURES UNITS 0 ⇢ 2 HP HP HP

    HP HP HP HP UNITS 3 ⇢ 5 HP UNITS … ⇢ N HP
  146. STRUCTURE OF ARRAYS POSITIONS X Y X Y X Y

    X Y X Y X Y X Y DX DY DX DY DX DY HP HP HP HP HP HP VELOCITIES DX DY DX DY DX DY DX DY HIT POINTS HP HP HP HP HP HP HP HP
  147. STRUCTURE OF ARRAYS POSITIONS THREAD A X Y X Y

    X Y X Y X Y X Y DX DY DX DY DX DY HP HP HP HP HP HP VELOCITIES THREAD B DX DY DX DY DX DY HIT POINTS THREAD C HP HP HP HP HP HP
  148. DATA-ORIENTED DESIGN ↝ SMALL LOOPS THAT OPERATE ON ARRAYS OF

    FIELDS. ↝ MINIMIZE THE AMOUNT OF DATA IN CACHE THAT ISN’T READ OR WRITTEN DURING THE UPDATE. ↝ SEVERAL TRANSFORMS CAN RUN IN PARALLEL ON THE SAME LOGICAL OBJECT IF THEY DON’T SHARE FIELDS.
  149. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS #experiment 🧪 Comparing two

    di erent memory layouts for the same data with ff @pmndrs/koota.
  150. MEASURING TIMING PROFILING USER TIMING • EVENT TIMING • RESOURCE

    TIMING • LONG TASKS • LONG ANIMATION FRAMES • SELF SERVER TIMING • ELEMENT TIMING PROFILING • MEMORY USAGE SENSORS OTHERS NETWORK STATUS • BATTERY STATUS • COMPUTE VISIBILITY STATE • INTERSECTION OBSERVER • PRESSURE LAYOUT INSTABILITY • CUSTOM METRICS
  151. LONG TASKS: OVERVIEW new PerformanceObserver((list) { for (const entry of

    list.getEntries()) { console.log("Blocked for:", entry.duration); entry.attribution?.forEach((source) { console.log("Source:", source.containerSrc); }); } > = > = }).observe({ type: "longtask", buffered: true });
  152. LONG TASKS: IDEAS DETECT: ↝ HYDRATION BLOCKING THE MAIN THREAD.

    ↝ LARGE BUNDLE EXECUTION PAUSES. ↝ THIRD-PARTY IFRAME BLOCKING INPUT. ↝ EXPENSIVE LAYOUT RECALCULATIONS.
  153. LONG ANIMATION FRAMES: IDEAS DETECT: ↝ INP REGRESSIONS. ↝ RENDERING

    PIPELINE BOTTLENECKS. ↝ ANIMATION FRAME DROPS. ↝ SLOW CSS/LAYOUT RECALCULATIONS. ↝ SLOW COMPOSITING PHASES.
  154. SELF PROFILING: OVERVIEW const profiler new Profiler({ sampleInterval: 10, maxBufferSize:

    10000 }); await doWork(); const profile await profiler.stop(); = = console.log(profile.samples);
  155. SELF PROFILING: IDEAS ↝ PROFILE REAL-WORLD HYDRATION BOTTLENECKS. ↝ PROFILE

    THIRD-PARTY SCRIPT EXECUTION TIME. ↝ DETECT HOT LOOPS IN DATA PROCESSING PIPELINES. ↝ DETECT REGRESSIONS AFTER FEATURE ROLLOUT.
  156. MEMORY USAGE: LEAKS #1 const obj { a: new Array(1000),

    b: new Array(2000) }; setInterval(() { console.log(obj.a); > = = }, 1000);
  157. MEMORY USAGE: LEAKS #4 const cache new Map(); function track(el)

    { cache.set(el, new Array(100000).fill("data")); = }
  158. MEMORY USAGE: LEAKS ↝ FORGETTING TO UNREGISTER AN EVENT LISTENER.

    ↝ ACCIDENTALLY CAPTURING OBJECTS FROM AN IFRAME. ↝ NOT CLOSING A WORKER. ↝ ACCUMULATING OBJECTS IN ARRAYS. ↝ AND MUCH MORE!
  159. MEMORY USAGE: IDEAS ↝ DETECT MEMORY LEAKS AFTER ROUTE TRANSITIONS.

    ↝ DETECT IFRAME MEMORY ISOLATION ISSUES. ↝ DETECT DOM NODE ACCUMULATION REGRESSIONS. ↝ MEASURE SPA CACHE GROWTH OVER TIME. ↝ COMPARE THE MEMORY COST OF FEATURE VARIANTS.
  160. PROFILING ↝ MAIN-THREAD BLOCKING ↝ WHERE TIME GOES. ↝ FRAME

    PIPELINE BLOCKING ↝ WHERE FRAMES DROP. ↝ CPU HOTSPOT ATTRIBUTION ↝ WHAT CODE RUNS. ↝ MEMORY HOTSPOT ATTRIBUTION ↝ WHERE MEMORY GROWS.
  161. NETWORK STATUS: OVERVIEW API INFORMATION { effectiveType: "4g", rtt: 200,

    const networkInfo navigator.connection.addEventListener('change', onConnectionChange); downlink: 1.65, saveData: false, = }
  162. NETWORK STATUS: IDEAS ↝ DISABLE ROUTE PREFETCHING ON SLOW CONNECTIONS.

    ↝ SKIP ANALYTICS UPLOADS WHEN RTT IS HIGH. ↝ LOAD LOWER-RESOLUTION ON CONSTRAINED BANDWIDTH. ↝ ADAPT TO SITUATIONS WHEN USERS ARE OFFLINE. ↝ RESPECT DATA SAVING AS A USER PERFORMANCE PREFERENCE SIGNAL.
  163. NETWORK STATUS: IDEAS switch (connectionType) { case "4g": return <Video

    src={videoSrc} />; case "3g": return <Image src={imageSrc.hiRes} alt={alt} />; default: return <Image src={imageSrc.lowRes} alt={alt} />; }
  164. BATTERY STATUS: OVERVIEW const batteryInfo await navigator.getBattery(); batteryInfo.addEventListener("chargingchange", listener); batteryInfo.addEventListener("chargingtimechange",

    listener); batteryInfo.addEventListener("dischargingtimechange", listener); = batteryInfo.addEventListener("levelchange", listener);
  165. BATTERY STATUS: IDEAS ↝ DISABLE BACKGROUND POLLING ON LOW BATTERY.

    ↝ REDUCE ANIMATION FREQUENCY. ↝ STOP PREFETCHING BUNDLES. ↝ PERSIST UNSAVED DATA BEFORE SHUTDOWN RISK. ↝ SWITCH TO A STATIC MAP RATHER THAN AN INTERACTIVE ONE.
  166. COMPUTE PRESSURE: OVERVIEW const observer const state new PressureObserver(records {

    records[0].state; if (state === "critical") { reduceRenderingQuality(); } }); > = = = observer.observe("cpu", { sampleInterval: 2000 });
  167. COMPUTE PRESSURE: IDEAS ↝ LOWER CANVAS RESOLUTION DYNAMICALLY. ↝ PAUSE

    BACKGROUND DATA PROCESSING PIPELINES. ↝ SWITCH FROM REAL-TIME UPDATES TO BATCHED ONES. ↝ DROP FRAME RATE IN WEBGL SCENES. ↝ REDUCE ANIMATION QUALITY WHEN CPU PRESSURE RISES.
  168. PAGE VISIBILITY: IDEAS ↝ CANCEL POLLING LOOPS, TIMERS, AND BACKGROUND

    NETWORK REFRESHES WHEN THE TAB BECOMES HIDDEN. ↝ PAUSE VIDEO, AUDIO, AND ANIMATION LOOPS WHEN THE USER ISN’T ACTIVELY WATCHING THE PAGE. ↝ RESUME PROGRESSIVE DOWNLOADS OR DYNAMIC IMPORTS WHEN THE PAGE BECOMES VISIBLE AGAIN.
  169. PAGE VISIBILITY: IDEAS ↝ STOP REFRESHING DASHBOARDS OR LIVE DATA

    FEEDS WHILE THE TAB IS BACKGROUNDED. ↝ SEND ANALYTICS RELIABLY AT SESSION END WHEN VISIBILITY BECOMES HIDDEN. ↝ SILENCE NOTIFICATIONS OR SOUNDS WHEN THE DEVICE SCREEN LOCKS OR THE TAB LOSES VISIBILITY.
  170. INTERSECTION OBSERVER: OVERVIEW const onIntersection (entries) { for (const entry

    of entries) { if (entry.isIntersecting) { console.log(entry); } } }; const observer new IntersectionObserver(onIntersection); > = = = observer.observe(document.querySelector('#target'));
  171. INTERSECTION OBSERVER: IDEAS ↝ INITIALIZE EXPENSIVE RENDERING PIPELINES (CHARTS, CANVAS,

    WEBGL) ONLY WHEN NEEDED. ↝ LAZY-LOAD IMAGES, IFRAMES, AND ROUTE BUNDLES WHEN THEY APPROACH THE VIEWPORT. ↝ DELAY LOADING THIRD-PARTY WIDGETS (MAPS, VIDEO EMBEDS, CHAT CLIENTS) UNTIL VISIBLE. ↝ CONTROL MEDIA PLAYBACK DEPENDING ON VISIBILITY.
  172. INTERSECTION OBSERVER: IDEAS ↝ RENDER/HYDRATE COMPLEX UI COMPONENTS ONLY WHEN

    THEY BECOME RELEVANT. ↝ TRIGGER ANALYTICS EVENTS WHEN USERS ACTUALLY SEE IMPORTANT UI SECTIONS. ↝ MEASURE HOW LONG ELEMENTS REMAIN VISIBLE (E.G., AD IMPRESSIONS).
  173. LAYOUT INSTABILITY: OVERVIEW ↝ MANY WEBSITES HAVE DOM ELEMENTS SHIFTING

    AROUND DUE TO CONTENT LOADING ASYNCHRONOUSLY. ↝ MEASURE REAL CLS VALUES IN PRODUCTION. ↝ IDENTIFY THE EXACT DOM ELEMENTS RESPONSIBLE FOR LAYOUT INSTABILITY. ↝ IGNORE EXPECTED SHIFTS CAUSED BY USER INTERACTION.
  174. LAYOUT INSTABILITY: OVERVIEW let cls 0; new PerformanceObserver((list) { for

    (const entry of list.getEntries()) { if (entry.hadRecentInput) continue; ignore expected shifts cls += entry.value; const culprit entry.sources?.[0]?.node; console.log("Shift:", entry.value); console.log("Element:", culprit); console.log("CLS so far:", cls); } / / > = = = }).observe({ type: "layout-shift", buffered: true });
  175. LAYOUT INSTABILITY: IDEAS ↝ DETECT INSTABILITY INTRODUCED BY THIRD-PARTY EMBEDS

    OR PERSONALIZATION. ↝ DETECT IMAGES OR IFRAMES LOADING WITHOUT A RESERVED SPACE. ↝ DETECT LAYOUT SHIFTS CAUSED BY WEB-FONT SWAPS.
  176. USER TIMING: IDEAS ↝ MEASURE ROUTE TRANSITIONS IN AN SPA.

    ↝ MEASURE API LATENCY (REQUEST → RENDER). ↝ MEASURE THE TIME BETWEEN USER INTENT AND UI CONFIRMATION. ↝ MEASURE HYDRATION FOR ISLANDS/COMPONENTS. ↝ TRACK TIME SPENT INSIDE SUSPENSE FALLBACKS.
  177. EVENT TIMING: OVERVIEW new PerformanceObserver(list { for (const entry of

    list.getEntries()) { console.log("Input delay:", entry.processingStart - entry.startTime); console.log("Handler time:", entry.processingEnd - entry.processingStart); console.log("Total latency:", entry.duration); } > = }).observe({ type: "event", buffered: true });
  178. EVENT TIMING: IDEAS ↝ MEASURE DROPDOWN RESPONSIVENESS. ↝ MEASURE DRAG-AND-DROP

    LATENCY. ↝ DETECT SLOW SLIDER INTERACTIONS. ↝ DETECT INPUT LAG IN FORMS. ↝ TRACK RESPONSIVENESS REGRESSIONS AFTER RELEASES.
  179. RESOURCE TIMING: OVERVIEW new PerformanceObserver(list { for (const entry of

    list.getEntries()) { console.log(entry.name); console.log("TTFB:", entry.responseStart - entry.requestStart); console.log("Download:", entry.responseEnd - entry.responseStart); console.log("Cache Hit:" entry.transferSize === 0); } > = }).observe({ type: "resource", buffered: true });
  180. RESOURCE TIMING: IDEAS ↝ MEASURE THIRD-PARTY SCRIPTS COST. ↝ MEASURE

    API ENDPOINT LATENCY. ↝ DETECT SLOW FONT LOADING. ↝ DETECT CACHE MISSES VS CACHE HITS. ↝ DETECT CDN CONFIGURATION ISSUES.
  181. SERVER TIMING: IDEAS ↝ MEASURE DB LATENCY IN THE BROWSER.

    ↝ DETECT A SLOW AUTH MIDDLEWARE. ↝ DEBUG EDGE-CACHE EFFECTIVENESS. ↝ DETECT TEMPLATE RENDERING BOTTLENECKS.
  182. ELEMENT TIMING: OVERVIEW ↝ ALLOWS YOU TO MEASURE THE RENDER

    TIME OF SPECIFIC ELEMENTS. ↝ USEFUL FOR KNOWING WHEN THE LARGEST IMAGE OR TEXT BLOCK WAS PAINTED TO THE SCREEN. ↝ THE BASIS FOR THE LARGEST CONTENTFUL PAINT (LCP) METRIC.
  183. ELEMENT TIMING: OVERVIEW <img src="/hero.jpg" elementtiming="hero" /> <script> new PerformanceObserver(list

    const entry { list.getEntries()[0]; console.log("Hero render:", entry.startTime); }).observe({ type: "element", buffered: true }); > = = </script>
  184. ELEMENT TIMING: IDEAS ↝ MEASURE HERO IMAGE RENDER TIMING. ↝

    MEASURE ABOVE-THE-FOLD READINESS. ↝ TRACK MARKETING CTA VISIBILITY TIMING. ↝ MEASURE WHEN SKELETON LOADERS DISAPPEAR. ↝ REPLACE SYNTHETIC LCP TRACKING WITH PRODUCTSPECIFIC METRICS.
  185. #protip 💡 Existing RUM and DXA tools are great—until scale,

    cost, or product-speci c questions force you to measure fi things yourself.
  186. PRODUCT-SPECIFIC QUESTIONS TIME UNTIL THE… ↝ SCROLL EFFECTS WORK. ↝

    APP RESPONDS TO CLICKS. ↝ MOST MEANINGFUL VIDEOS/ANIMATIONS RUN. ↝ PRIMARY FEATURE SHOWS UP/IS INTERACTIVE. ↝ COOKIE BANNER SHOWS UP.
  187. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS #2 React is a

    spreading agent for Computer Science in our realm. DSLs, COMPILERS, CONCURRENCY, FIBERS, EFFECT HANDLERS, IMMUTABILITY… OH MY!
  188. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS #3 React tries to

    address the lack of some JavaScript/Web Platform resources.
  189. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS Understanding these #4 internals

    and their rationales helps us implement our own abstractions.
  190. OUR OWN ABSTRACTIONS… ↝ INTERNAL SUSPENSE-READY SOLUTIONS. ↝ GENERATOR-BASED SCHEDULER.

    ↝ CUSTOM MEMORY MANAGEMENT. ↝ CUSTOM METRICS (E.G. DXA, JQUERY TRACKING). ↝ STATIC-ANALYSIS-ENABLED WORKFLOWS.
  191. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS AI agents can write

    React. But engineers #5 who understand scheduling, rendering, and data- ow boundaries can decide what should be fl optimized.
  192. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS Internals matter more in

    the AI era. #5 Compilers automate optimizations. Agents automate code. Only engineers understand ff tradeo s.
  193. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS React stopped being #6

    just a library years ago. AND WE’RE STILL CATCHING UP TO WHAT IT BECAME… ↝ COMPILER TARGET? ↝ RUNTIME SCHEDULER? ↝ SERVER-FIRST PLATFORM?
  194. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS #7 Core Web Vitals

    are a better starting point than a nish line. fi — IN THE BLINK OF AN EYE • TIM KADLEC , 2024
  195. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS Always try to correlate

    #9 behavior analysis with contextual metrics and business outcomes to tell the full story.
  196. LCP ⇆ RETENTION RATE — CORE WEB VITALS AND THEIR

    EFFECT ON USER EXPERIENCE • PHILIP TELLIS, 2025
  197. CLS ⇆ RELOAD RATE — CORE WEB VITALS AND THEIR

    EFFECT ON USER EXPERIENCE • PHILIP TELLIS, 2025
  198. INP ⇆ RAGE CLICK RATE — CORE WEB VITALS AND

    THEIR EFFECT ON USER EXPERIENCE • PHILIP TELLIS, 2025
  199. REACT: INTERNALS AND ADVANCED PERFORMANCE PATTERNS There's probably a business

    case for #11 making your app faster. But web performance is about more than “just” business.