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

feat(ByRole): improved byRole query performance #1086

Merged
merged 3 commits into from Aug 9, 2022

Conversation

kalmi
Copy link
Contributor

@kalmi kalmi commented Jan 14, 2022

What: byRole query logic is optimised for performance

Why: We experienced timeouts while using byRole queries, and decided to investigate by performing profiling. We found that each and every byRole query was taking at least hundred(s) of milliseconds in our test cases (even when accessibility/visibility checks were disabled by mocking out getComputedStyle to always return undefined for any property). Our test cases have medium sized trees, nothing excessive.

How: the byRole query logic is refactored, so that less work done in the tight loop of byRole queries. That loop is executed for each and every node and role combination for every element for every byRole query. Some code is moved out of the loop into the surrounding closure, so that some values are precomputed. The most important change is that a cheap tagName equality check is done, and we skip most of the work if the it can't possibly be a match. These changes were done in a way that we now avoid most allocations in the tightest part of the loop.

These changes result in a 2 orders of magnitude speed up for byRole queries according to my profiling results in out test cases. (This was measured while accessibility/visibility checks were disabled (both before and after) by mocking out getComputedStyle to always return undefined for any property.)

Checklist:

  • Documentation added to the
    docs site N/A
  • Tests
  • TypeScript definitions updated N/A
  • Ready to be merged

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 14, 2022

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.

Latest deployment of this branch, based on commit 95e546e:

Sandbox Source
react-testing-library-examples Configuration

@codecov
Copy link

codecov bot commented Jan 14, 2022

Codecov Report

Merging #1086 (95e546e) into main (4f965e9) will not change coverage.
The diff coverage is 100.00%.

@@            Coverage Diff            @@
##              main     #1086   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           24        24           
  Lines          989       990    +1     
  Branches       322       322           
=========================================
+ Hits           989       990    +1     
Flag Coverage Δ
node-12 100.00% <100.00%> (ø)
node-14 100.00% <100.00%> (ø)
node-16 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/role-helpers.js 100.00% <100.00%> (ø)

📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

@eps1lon

This comment has been minimized.

@eps1lon eps1lon added the enhancement New feature or request label Jan 15, 2022
@eps1lon eps1lon changed the title feat(ByRole): improved byRole query performance (#698) feat(ByRole): improved byRole query performance Jan 15, 2022
Copy link
Member

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Nicely spotted!

Hoisting some of the code up so that it doesn't need to access closures definitely makes sense. Not just from a big-O notation standpoint but from a JS engine perspective as well.

I'm not so sure about the introduce short-circuits though. Could you clarify that?

src/role-helpers.js Outdated Show resolved Hide resolved
Copy link
Member

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Looks like we reduced the total time of the created matcher:

Before:
hoist-make-selector-self-before
hoist-make-selector-total-before

After:
hoist-make-selector-self-after

hoist-make-selector-total-after

@eps1lon eps1lon merged commit 0226aea into testing-library:main Aug 9, 2022
@eps1lon
Copy link
Member

eps1lon commented Aug 9, 2022

@all-contributors add @kalmi for code

@allcontributors
Copy link
Contributor

@eps1lon

I've put up a pull request to add @kalmi! 🎉

@eps1lon
Copy link
Member

eps1lon commented Aug 9, 2022

Work towards #698 and #820

@github-actions
Copy link

github-actions bot commented Aug 9, 2022

🎉 This PR is included in version 8.17.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants