8000 Optimize the revalidation logic for same key requests. by agadzik · Pull Request #4138 · vercel/swr · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Optimize the revalidation logic for same key requests. #4138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

agadzik
Copy link
Contributor
@agadzik agadzik commented Jun 27, 2025

Problem

The SWR hook was experiencing performance issues due to inefficient request deduplication logic, causing unnecessary re-renders and redundant API calls when multiple components used the same key.

Solution

Added a performance optimization at line 644 that checks if a request is already in progress before initiating a new one:

  // Performance optimization: if a request is already in progress for this key,
  // skip the revalidation to avoid redundant work
  if (!FETCH[key]) {
    if (isUndefined(data) || IS_SERVER) {
      // Revalidate immediately.
      softRevalidate()
    } else {
      // Delay the revalidate if we have data to return so we won't block
      // rendering.
      rAF(softRevalidate)
    }
  }

Key Changes

  • Deduplication Check: Before triggering initial revalidation, the code now checks if FETCH[key] exists, preventing duplicate revalidations for the same key

This optimization ensures that when multiple components request the same data simultaneously, only one actual fetch request is made, improving overall application performance.

Testing

@gdborton created the e2e/site/app/perf/page.tsx as an example of the problem. I then created a playwright test that asserts that the "Expensive Component" should be rendered under 1 second.

Before the fix

$ pnpm test:e2e perf --repeat-each 10 -j 1
$ pnpm test:e2e perf --repeat-each 10 -j 1 

> swr@2.3.3 test:e2e /Users/agadzik/Developer/swr
> playwright test "perf" "--repeat-each" "10" "-j" "1"


Running 10 tests using 1 worker
  1) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1241

  2) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1218.7000000029802

  3) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1233.3999999985099

  4) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1209.6000000014901

  5) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1254

  6) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1216.6000000014901

  7) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1256.699999999255

  8) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1230.7000000029802

  9) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1200.800000000745

  10) test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 

    Error: expect(received).toBeLessThan(expected)

    Expected: < 1000
    Received:   1227.199999999255

  10 failed
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click 
    test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click

After the fix

$ pnpm test:e2e perf --repeat-each 10 -j 1
$ pnpm test:e2e perf --repeat-each 10 -j 1 

> swr@2.3.3 test:e2e /Users/agadzik/Developer/swr
> playwright test "perf" "--repeat-each" "10" "-j" "1"


Running 10 tests using 1 worker
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 215.90ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 217.80ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 215.00ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 216.30ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 213.90ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 220.80ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 215.80ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 216.40ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 215.30ms
test/perf.test.ts:4:7 › performance › should render expensive component within 1 second after checkbox click
Expensive Component fully rendered and painted in 217.50ms
  10 passed (9.0s)

(Mobile) Deployments List page testing (before and after)

Screen.Recording.2025-06-27.at.9.49.23.AM.mov

(Desktop) Deployments List page testing (before and after)

Screen.Recording.2025-06-26.at.2.18.02.PM.mov

@agadzik agadzik requested review from shuding and huozhi as code owners June 27, 2025 13:43
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
0