-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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
Make parallel testing db faster #33479
Make parallel testing db faster #33479
Conversation
Thanks for the pull request, and welcome! The Rails team is excited to review your changes, and you should hear from @kaspth (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. This repository is being automatically checked for code quality issues using Code Climate. You can see results for this analysis in the PR status below. Newly introduced issues should be fixed before a Pull Request is considered ready to review. Please see the contribution instructions for more information. |
I'm just dropping the CI failures here so I know what to look at tomorrow: Ruby 2.4.4, 2.5.1 & Head GEM-Railties:
|
ensure | ||
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[Rails.env]) | ||
ENV["VERBOSE"] = old | ||
end | ||
|
||
def self.drop(i, spec_name:) | ||
def self.drop(spec_name:) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not the i
be used here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It took me a couple of looks to see why this is okay: create_and_migrate
modifies the original connection spec hash, so the rest of the (forked) app, including this method, sees that already-suffixed DB name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that is confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had put the i
in when I wrote this and while pairing with Britni on fixing this realized that it isn't used so we should delete it.
@@ -247,6 +247,7 @@ def structure_load(*arguments) | |||
|
|||
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc: | |||
file ||= dump_filename(spec_name, format) | |||
verbose_was, Migration.verbose = Migration.verbose, verbose? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is Migration.verbose
thread-safe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is any of this? It runs in a fork, so I think it should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But doesn't the parallel test also have the threaded mode? I guess this don't run on those threads but before it in a fork.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it does have a threaded mode, but we don't make new databases when we're using the threaded parallelizer because it uses new connections instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need these changes for #load_schema
? Is this method supposed to work with migrations?
If remove these change, tests in railties/test/application/test_test.rb
succeed. See #33479 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't do this running your tests in parallel will display schema output for every single process which is noisy and unnecessary.
Cool! What happens if I create a migration that adds some columns, forget to migrate the test database, and then run my tests. Do the tests fail in a sufficiently obvious manner that I can know I need to run the migration? |
@kaspth this doesn't change how your tests would run if you didn't run a migration. You'd still get blocked by pending migrations error because the create_and_migrate part runs after the tests boot. This just speeds up setting up the databases for |
ActiveSupport::Testing::Parallelization.run_cleanup_hook do |i| | ||
drop(i, spec_name: Rails.env) | ||
ActiveSupport::Testing::Parallelization.run_cleanup_hook do |_| | ||
drop(spec_name: Rails.env) | ||
end | ||
|
||
def self.create_and_migrate(i, spec_name:) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also rename this method to create_and_load
since we're no longer migrating.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it! Thanks.
Thank you @eileencodes for the clarifications, now I understand better the parallel test implementation. Nice improvement @twitnithegirl 👏. |
@rafael @eileencodes @kaspth I just pushed a change that I think will fix CI for |
@twitnithegirl can you rebase and squash your commits into one? |
@eileencodes sure, should I update the changelog too? |
6ac0e99
to
e6173c9
Compare
All squashed up |
Thanks @twitnithegirl - no need for a changelog since this is a performance improvement and not actually in a version of Rails yet. |
rails#33479 changed `#load_schema` to prevent displaying schema load on running tests in parallel. We should test this in order to prevent any regression in the future. Context rails#33479 (comment)
- Fix formatting - Don't repeat "Active Record automatically handles creating and migrating a new database for each worker to use." - Tell that AR loads the schema to a database for each process(Related to rails#33479) - Clarify that `parallelize_teardown` is executed for each process
Summary
Currently TestDatabases.create_and_migrate for parallel tests uses migrate. For a large number of workers this makes the tests run pretty slowly. The PR changes this to load_schema which shows an increase of speed.
Benchmarks below are for a sample app with 6 tables, 10 workers, and generated tests.
Before:
After:
/cc @eileencodes