Repository navigation
test: create each SQL Server test database once, as rows arriving together would race it - #252
Merged
Merged
Conversation
… SQL Server database once After #250, CI's Linux leg ends every run, and the EF Core project is half of it: its two query sweeps are one class each of 12,275 rows, which xunit's default mode ran one after another (#251). A row waits on SQLite, SQL Server or PostgreSQL more than it computes: at four threads the project took 55 s instead of 123 s for the same CPU. The project now runs with parallelMode "all" (xunit.runner.json). A row reads only what was seeded for its model, and each SQLite class opens its own database per test. SqlServerRoundTripTests opts out ([TestClass(DisableParallelization = true)]): each of its tests creates the same tables in one database. Seeded by removing the opt-out: 5 of its 7 tests fail. The whole suite found a race in the SQL Server fixture: DatabaseAsync's GetOrAdd ran its factory more than once for callers that arrived together, and the first rows of a sweep dropped and created typekit_queries under each other. Each database is now created once behind a Lazy, as the sweeps' own seeded databases are. SqlServerFixtureTests asks for one database from 32 callers at once; with the plain GetOrAdd restored it fails 3 runs of 3. The profile also answered the issue's other half: a CMTK0003 sweep row costs its own file, and reusing the compilation or compiling the declarations to metadata saves nothing, so DroppedTaskVariantTests is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e fixture's create-once On CI, parallel rows bought the EF Core project almost nothing (#251, #252's run): the database containers share the runner's four cores with the tests, so what looked like waiting on a local machine with spare cores became CPU. The Linux test step went from 9m 28s to 9m 17s, and the Windows one from 5m 17s to 7m 11s, as the projects beside EF Core slowed. xunit.runner.json and SqlServerRoundTripTests' opt-out go. SqlServer.DatabaseAsync keeps creating each database once behind a Lazy, with SqlServerFixtureTests as its guard: GetOrAdd may run its factory twice for callers that arrive together, which rows run in parallel did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #251
Problem
After #250, CI's Linux test leg ends every run, with the analyzer tests and EF Core finishing within 40 s of each other (#251). The profile found two things. CMTK0003's sweep has nothing to share between rows. EF Core's query sweeps ran their rows one after another, which looked like the lever. On the way, the whole suite under parallel rows found a race in the SQL Server fixture:
SqlServer.DatabaseAsyncusedConcurrentDictionary.GetOrAdd(name, CreateAsync), which can run the factory more than once for callers that arrive together. The first rows of a sweep then dropped and createdtypekit_queriesunder each other (11,832 failures in that run).Change
SqlServer.DatabaseAsynccreates each database once, behind aLazy<Task<string>>, the pattern the query sweeps already use for their seeded databases.SqlServerFixtureTests: a guard that asks for one database from 32 callers at once.Parallel rows for the EF Core project were in this PR's first commit and are taken out by its second. On CI they bought almost nothing, because the database containers share the runner's four cores with the tests:
Test code only: no package, no changelog entry.
Tests
GetOrAddrestored, and passes with theLazy.🤖 Generated with Claude Code