Skip to content
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

[FIX]: useQueries have quadratic performance in relation to the number of queries #8641

Merged
merged 2 commits into from
Feb 16, 2025

Conversation

joseph0926
Copy link
Contributor

Tasks

Issue
Comment

Modification

We changed the code so that instead of recalculating the matching observers every time in the trackResult function, we compute the matches once and pass them in. In getOptimisticResult and notify, we now use the precomputed matches instead of calling findMatchingObservers again. This reduces redundant computations (avoiding O(N²) behavior) while keeping the overall functionality the same.

etc,,,

Before modification (500 queries -> Approximately 4500 calls)

스크린샷 2025-02-13 오전 8 28 15

After modification (500 queries -> Approximately 2000 calls)

스크린샷 2025-02-13 오전 9 19 55

Let us know if you have any issues.
We've tried to keep the original code as unaffected as possible.

Test

You can try running the test code below after switching findMatchingObservers to “public”.

import { QueriesObserver, QueryCache, QueryClient } from '@tanstack/query-core'
import { waitFor } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { useQueries } from '../..'
import { queryKey, renderWithClient, sleep } from '../utils'

describe('useQueries O(N²) regression check', () => {
  it('should not call #findMatchingObservers excessively with heavy load (500 queries)', async () => {
    const queryCache = new QueryCache()
    const queryClient = new QueryClient({ queryCache })

    const originalFn = QueriesObserver.prototype.findMatchingObservers
    let callCount = 0

    QueriesObserver.prototype.findMatchingObservers = function (
      ...args: Array<any>
    ) {
      callCount++
      return originalFn.apply(this, args)
    }
    console.log(QueriesObserver.prototype)

    function Page() {
      const size = 500
      const key = queryKey()

      const queries = Array.from({ length: size }, (_, i) => ({
        queryKey: [key, i],
        queryFn: async () => {
          await sleep(1 + Math.random() * 5)
          return `Result ${i}`
        },
      }))

      useQueries({ queries })

      return <div>Heavy queries test</div>
    }

    const rendered = renderWithClient(queryClient, <Page />)

    await waitFor(() => rendered.getByText('Heavy queries test'))

    await sleep(1000)

    console.log('findMatchingObservers call count:', callCount)
    expect(callCount).toBeLessThan(500)
    ;(QueriesObserver.prototype as any)['#findMatchingObservers'] = originalFn
  })
})

Copy link

nx-cloud bot commented Feb 16, 2025

View your CI Pipeline Execution ↗ for commit 4999cce.

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 5m 15s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 58s View ↗

☁️ Nx Cloud last updated this comment at 2025-02-16 12:34:49 UTC

Copy link

pkg-pr-new bot commented Feb 16, 2025

Open in Stackblitz

More templates

@tanstack/angular-query-devtools-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-devtools-experimental@8641

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@8641

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@8641

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@8641

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@8641

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@8641

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@8641

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@8641

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@8641

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@8641

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@8641

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@8641

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@8641

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@8641

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@8641

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@8641

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@8641

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@8641

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@8641

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@8641

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@8641

commit: 4999cce

Copy link

codecov bot commented Feb 16, 2025

Codecov Report

Attention: Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 63.07%. Comparing base (5426e6c) to head (4999cce).
Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #8641       +/-   ##
===========================================
+ Coverage   46.24%   63.07%   +16.83%     
===========================================
  Files         199      135       -64     
  Lines        7532     4837     -2695     
  Branches     1722     1356      -366     
===========================================
- Hits         3483     3051      -432     
+ Misses       3670     1542     -2128     
+ Partials      379      244      -135     
Components Coverage Δ
@tanstack/angular-query-devtools-experimental ∅ <ø> (∅)
@tanstack/angular-query-experimental 88.65% <ø> (ø)
@tanstack/eslint-plugin-query ∅ <ø> (∅)
@tanstack/query-async-storage-persister 43.85% <ø> (ø)
@tanstack/query-broadcast-client-experimental ∅ <ø> (∅)
@tanstack/query-codemods ∅ <ø> (∅)
@tanstack/query-core 94.16% <80.00%> (+<0.01%) ⬆️
@tanstack/query-devtools 4.78% <ø> (ø)
@tanstack/query-persist-client-core 57.73% <ø> (ø)
@tanstack/query-sync-storage-persister 84.61% <ø> (ø)
@tanstack/react-query 95.95% <ø> (ø)
@tanstack/react-query-devtools 10.00% <ø> (ø)
@tanstack/react-query-next-experimental ∅ <ø> (∅)
@tanstack/react-query-persist-client 100.00% <ø> (ø)
@tanstack/solid-query 78.20% <ø> (ø)
@tanstack/solid-query-devtools ∅ <ø> (∅)
@tanstack/solid-query-persist-client 100.00% <ø> (ø)
@tanstack/svelte-query 87.33% <ø> (ø)
@tanstack/svelte-query-devtools ∅ <ø> (∅)
@tanstack/svelte-query-persist-client 100.00% <ø> (ø)
@tanstack/vue-query 71.01% <ø> (ø)
@tanstack/vue-query-devtools ∅ <ø> (∅)

@TkDodo TkDodo merged commit 4ab455c into TanStack:main Feb 16, 2025
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants