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

railties/test_parser: Cache prism work done in definition_for #53936

Merged
merged 1 commit into from
Dec 13, 2024

Conversation

jsharpify
Copy link
Contributor

This PR applies to the Prism implementation of definition_for.

Motivation

In files with lots of tests, definition_for is called repeatedly and performs a lot of work that really adds up. The work is reusable across many tests, so let's do it.

Details

definition_for is used to extract the line numbers of a test, which is relevant when filtering tests to a line number or range, eg my_test.rb:1-2.

The filter itself operates by, for each test, comparing the lines the test spans against the filter. In the existing code, this will call Prism.parse_file and then walk the parse result until the matching definition/call is found.

For files with a large number of tests, this is fairly onerous and can dominate the test runtime. Fortunately, we can parse the file once and cache the starts and ends of every def/call node.
This brings the definition_for runtime down from seconds to low milliseconds.

We also see a reduction in gc time that is probably attributable to not repeatedly parsing the file.
For a test run in an 240 test file that went from 11s of definition_for to 20ms, gc went from 4.5 to 2.2 seconds.

Finally, for any user that has written a test reporter or otherwise hooked into the filters, this should provide speedup as well.

Checklist

  • This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

Sorry, something went wrong.

@rails-bot rails-bot bot added the railties label Dec 13, 2024
@jsharpify jsharpify force-pushed the jsharpify/prism-parsing branch from 9861e49 to 1d95d38 Compare December 13, 2024 13:37
Copy link
Contributor

@nvasilevski nvasilevski left a comment

Choose a reason for hiding this comment

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

Makes sense!

definition_for is called repeatedly and performs a lot of work that really adds up.

Occasionally there would be an opportunity to avoid calling definition_for repeatedly in the first place, by either changing the code or moving memoization at a higher level. However this doesn't seem to be the case, I briefly looked over the code and it does look like definition_for is expected to be called multiple times so memoizing parse results makes perfect sense

@jsharpify jsharpify force-pushed the jsharpify/prism-parsing branch from 1d95d38 to fa5e5b5 Compare December 13, 2024 19:04
`definition_for` is used to extract the line numbers of a test, which
is relevant when filtering tests to a line number or range, eg
my_test.rb:1-2.

The filter itself operates by, for each test, comparing the lines the
test spans against the filter. In the current code, this will call
`Prism.parse_file` and then walk the parse result until the matching
definition/call is found.

For files with a large number of tests, this is fairly onerous and can
dominate the test runtime. Fortunately, we can parse the file once and
cache the starts and ends of every def/call node.
This beings the `definition_for` runtime down from seconds to low
milliseconds.

We also see a reduction in gc time that is probably attributable to
not repeatedly parsing the file.
For a test run in an 240 test file that went from 11s of parsing to
20ms, gc went from 4.5-2.2 seconds.

Finally, for any user that has written a reporter or otherwise hooked
into the filters, this should provide speedup as well.

Co-authored-by: Stath Stivaros <stath.stivaros@shopify.com>
@jsharpify jsharpify force-pushed the jsharpify/prism-parsing branch from fa5e5b5 to fbb37c0 Compare December 13, 2024 19:05
@rafaelfranca rafaelfranca merged commit 1f9b696 into rails:main Dec 13, 2024
3 checks passed
rafaelfranca added a commit that referenced this pull request Dec 13, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
railties/test_parser: Cache prism work done in definition_for
rafaelfranca added a commit that referenced this pull request Dec 13, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
railties/test_parser: Cache prism work done in definition_for
@Ashnic27
Copy link

J

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

Successfully merging this pull request may close these issues.

None yet

4 participants