Skip to content

Refactor parallelism in testing#826

Merged
oflatt merged 15 commits intomainfrom
oflatt-refactor-parallel
Apr 6, 2026
Merged

Refactor parallelism in testing#826
oflatt merged 15 commits intomainfrom
oflatt-refactor-parallel

Conversation

@oflatt
Copy link
Copy Markdown
Member

@oflatt oflatt commented Mar 11, 2026

Now parallelism can be controlled with new endpoint with_num_threads

Also, parallelism in tests is separate- we test with parallelism on and off instead of randomly choosing.

@oflatt oflatt requested a review from a team as a code owner March 11, 2026 23:13
@oflatt oflatt requested review from FTRobbin and Copilot and removed request for a team March 11, 2026 23:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors parallelism from using rayon's global thread pool to a local, per-EGraph thread pool. Previously, debug/test builds used random coin flips to decide whether to parallelize, and the global pool was configured once. Now, the EGraph owns an Arc<rayon::ThreadPool>, parallel heuristics use deterministic size thresholds, and tests run each case both single-threaded and with 4 threads.

Changes:

  • Added a pool: Arc<rayon::ThreadPool> field to EGraph with with_num_threads()/num_threads() API; public entry points (run_program, resolve_program) wrap execution in pool.install().
  • Replaced all #[cfg(test)]/#[cfg(debug_assertions)] random parallelism decisions with deterministic heuristics based on data size and rayon::current_num_threads().
  • Updated test harness to run each test case with both 1 and 4 threads (instead of random), and removed global rayon pool configuration from benchmarks and CLI.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/lib.rs Added pool field, with_num_threads/num_threads methods, wrapped run_program/resolve_program in pool.install()
src/cli.rs Replaced global rayon pool setup with egraph.with_num_threads()
core-relations/src/parallel_heuristics.rs Removed random coin-flip logic, now always uses size+thread-count heuristics
core-relations/src/table/rebuild.rs Removed #[cfg]-gated random logic in incremental_rebuild
core-relations/src/containers/mod.rs Removed #[cfg]-gated random logic in incremental_rebuild
egglog-bridge/src/lib.rs Simplified do_parallel() to always check rayon::current_num_threads()
tests/files.rs Added threads field to Run, tests run with 1 and 4 threads, snapshot skipping for parallel
benches/common.rs Removed global rayon pool configuration (EGraph default is 1 thread)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core-relations/src/parallel_heuristics.rs Outdated
Comment thread core-relations/src/parallel_heuristics.rs Outdated
Comment thread core-relations/src/table/rebuild.rs Outdated
Comment thread core-relations/src/containers/mod.rs Outdated
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 11, 2026

Merging this PR will degrade performance by 5.91%

❌ 1 regressed benchmark
✅ 37 untouched benchmarks
⏩ 190 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime tests[proof_testing_eqsat-basic] 38.8 ms 41.2 ms -5.91%

Comparing oflatt-refactor-parallel (484531a) with main (21bd8c6)

Open in CodSpeed

Footnotes

  1. 190 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@oflatt oflatt requested review from yihozhang and removed request for FTRobbin March 11, 2026 23:41
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 12, 2026

Codecov Report

❌ Patch coverage is 73.68421% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.87%. Comparing base (afd5c07) to head (484531a).
⚠️ Report is 67 commits behind head on main.

Files with missing lines Patch % Lines
src/lib.rs 30.76% 9 Missing ⚠️
src/cli.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #826      +/-   ##
==========================================
+ Coverage   81.53%   81.87%   +0.33%     
==========================================
  Files          88       88              
  Lines       24157    24868     +711     
==========================================
+ Hits        19697    20361     +664     
- Misses       4460     4507      +47     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ezrosent
Copy link
Copy Markdown
Contributor

I'm seeing a noticeable slowdown for the parallel AC benchmark on my laptop, let me know if you see the same thing:

# this branch
egglog-bridge % time RAYON_NUM_THREADS=1 ../target/release/examples/ac
Finished iteration 0 after 174.041µs
Finished iteration 1 after 116.25µs
Finished iteration 2 after 477.709µs
Finished iteration 3 after 5.882291ms
Finished iteration 4 after 40.823958ms
Finished iteration 5 after 279.820958ms
Finished iteration 6 after 2.38614525s
Finished iteration 7 after 7.372346792s
Finished iteration 8 after 6.258701208s
Finished iteration 9 after 616.87175ms
Time elapsed: 16.962592583s
Finished iteration 0 after 22.125µs
Finished iteration 1 after 46.959µs
Finished iteration 2 after 177.125µs
Finished iteration 3 after 2.042459ms
Finished iteration 4 after 25.968875ms
Finished iteration 5 after 279.294667ms
Finished iteration 6 after 2.346290084s
Finished iteration 7 after 7.353380542s
Finished iteration 8 after 6.2065015s
Finished iteration 9 after 630.996167ms
Time elapsed: 16.8448525s
RAYON_NUM_THREADS=1 ../target/release/examples/ac  33.44s user 0.41s system 99% cpu 34.137 total
egglog-bridge % time RAYON_NUM_THREADS=16 ../target/release/examples/ac
Finished iteration 0 after 100.417µs
Finished iteration 1 after 145.958µs
Finished iteration 2 after 698.958µs
Finished iteration 3 after 6.228666ms
Finished iteration 4 after 20.192167ms
Finished iteration 5 after 104.065209ms
Finished iteration 6 after 796.485083ms
Finished iteration 7 after 2.440710583s
Finished iteration 8 after 1.777115416s
Finished iteration 9 after 132.481833ms
Finished iteration 10 after 46.25µs
Time elapsed: 5.279693167s
Finished iteration 0 after 32.75µs
Finished iteration 1 after 54.667µs
Finished iteration 2 after 258.791µs
Finished iteration 3 after 4.967875ms
Finished iteration 4 after 14.06925ms
Finished iteration 5 after 105.4665ms
Finished iteration 6 after 797.32ms
Finished iteration 7 after 2.432492125s
Finished iteration 8 after 1.728456333s
Finished iteration 9 after 130.441625ms
Finished iteration 10 after 45.375µs
Time elapsed: 5.213766042s
RAYON_NUM_THREADS=16 ../target/release/examples/ac  131.03s user 2.15s system 1263% cpu 10.544 total
# main
egglog-bridge % time RAYON_NUM_THREADS=1 ../target/release/examples/ac
Finished iteration 0 after 247.833µs
Finished iteration 1 after 129.5µs
Finished iteration 2 after 526.833µs
Finished iteration 3 after 5.647166ms
Finished iteration 4 after 42.256ms
Finished iteration 5 after 286.755917ms
Finished iteration 6 after 2.423853083s
Finished iteration 7 after 7.807142458s
Finished iteration 8 after 6.235088584s
Finished iteration 9 after 642.359459ms
Time elapsed: 17.445481042s
Finished iteration 0 after 21.5µs
Finished iteration 1 after 43µs
Finished iteration 2 after 173.125µs
Finished iteration 3 after 2.128ms
Finished iteration 4 after 26.665834ms
Finished iteration 5 after 289.152041ms
Finished iteration 6 after 2.355267792s
Finished iteration 7 after 7.356927667s
Finished iteration 8 after 6.234381666s
Finished iteration 9 after 634.649666ms
Time elapsed: 16.899556375s
RAYON_NUM_THREADS=1 ../target/release/examples/ac  33.95s user 0.43s system 99% cpu 34.588 total
egglog-bridge % time RAYON_NUM_THREADS=16 ../target/release/examples/ac
Finished iteration 0 after 103.25µs
Finished iteration 1 after 138.5µs
Finished iteration 2 after 655µs
Finished iteration 3 after 6.527667ms
Finished iteration 4 after 20.095083ms
Finished iteration 5 after 103.888ms
Finished iteration 6 after 682.652709ms
Finished iteration 7 after 1.785811916s
Finished iteration 8 after 1.074518333s
Finished iteration 9 after 127.437292ms
Finished iteration 10 after 48.792µs
Time elapsed: 3.803388334s
Finished iteration 0 after 35.208µs
Finished iteration 1 after 52µs
Finished iteration 2 after 245.375µs
Finished iteration 3 after 4.738416ms
Finished iteration 4 after 16.524834ms
Finished iteration 5 after 106.523958ms
Finished iteration 6 after 662.67875ms
Finished iteration 7 after 1.78807125s
Finished iteration 8 after 1.050615792s
Finished iteration 9 after 119.656625ms
Finished iteration 10 after 34.833µs
Time elapsed: 3.749351875s
RAYON_NUM_THREADS=16 ../target/release/examples/ac  82.60s user 2.43s system 1118% cpu 7.602 total

Comment thread core-relations/src/tests.rs Outdated
Comment thread tests/files.rs Outdated
Comment thread src/lib.rs Outdated

/// Return the number of threads in this EGraph's thread pool.
pub fn num_threads(&self) -> usize {
#[cfg(not(target_family = "wasm"))]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's move the WASM-gating into its own module, making our own ThreadPool type that exposes the common stuff (like num threads and install).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Let's wait on this since we might make our own threadpool soon

@yihozhang
Copy link
Copy Markdown
Collaborator

yihozhang commented Mar 28, 2026

Weird I don't see a slowdown... @ezrosent

I'm on Linux with a server CPU, though. Maybe issues with macOS?

➜  egglog-main git:(main) ✗ time RAYON_NUM_THREADS=1 target/release/examples/ac   
Finished iteration 0 after 124.144µs
Finished iteration 1 after 199.428µs
Finished iteration 2 after 1.448557ms
Finished iteration 3 after 9.733119ms
Finished iteration 4 after 67.083274ms
Finished iteration 5 after 920.428166ms
Finished iteration 6 after 8.052704913s
Finished iteration 7 after 26.16546065s
Finished iteration 8 after 22.133531943s
Finished iteration 9 after 2.25402405s
Time elapsed: 59.605416622s
Finished iteration 0 after 60.923µs
Finished iteration 1 after 110.904µs
Finished iteration 2 after 443.867µs
Finished iteration 3 after 5.755594ms
Finished iteration 4 after 67.990388ms
Finished iteration 5 after 968.890035ms
Finished iteration 6 after 8.080236345s
Finished iteration 7 after 26.663634781s
Finished iteration 8 after 23.574827581s
Finished iteration 9 after 2.427887041s
Time elapsed: 61.790108901s
RAYON_NUM_THREADS=1 target/release/examples/ac  119.32s user 2.11s system 99% cpu 2:01.47 total
➜  egglog-main git:(main) ✗ time RAYON_NUM_THREADS=16 target/release/examples/ac
Finished iteration 0 after 131.615µs
Finished iteration 1 after 262.33µs
Finished iteration 2 after 1.464427ms
Finished iteration 3 after 15.012965ms
Finished iteration 4 after 43.591217ms
Finished iteration 5 after 436.737187ms
Finished iteration 6 after 2.151402348s
Finished iteration 7 after 5.679616746s
Finished iteration 8 after 3.24783291s
Finished iteration 9 after 361.384272ms
Finished iteration 10 after 108.234µs
Time elapsed: 11.940915263s
Finished iteration 0 after 161.486µs
Finished iteration 1 after 249.509µs
Finished iteration 2 after 1.341182ms
Finished iteration 3 after 20.932935ms
Finished iteration 4 after 74.266602ms
Finished iteration 5 after 401.417271ms
Finished iteration 6 after 2.154214173s
Finished iteration 7 after 5.744284457s
Finished iteration 8 after 3.276267922s
Finished iteration 9 after 350.254268ms
Finished iteration 10 after 105.814µs
Time elapsed: 12.023949689s
RAYON_NUM_THREADS=16 target/release/examples/ac  208.72s user 12.79s system 914% cpu 24.235 total
➜  egglog git:(oflatt-refactor-parallel) ✗ time RAYON_NUM_THREADS=1 target/release/examples/ac   
Finished iteration 0 after 132.885µs
Finished iteration 1 after 215.208µs
Finished iteration 2 after 1.442146ms
Finished iteration 3 after 9.624595ms
Finished iteration 4 after 66.880644ms
Finished iteration 5 after 915.072466ms
Finished iteration 6 after 8.025484014s
Finished iteration 7 after 26.106735617s
Finished iteration 8 after 22.181092982s
Finished iteration 9 after 2.273273632s
Time elapsed: 59.580596645s
Finished iteration 0 after 62.402µs
Finished iteration 1 after 99.794µs
Finished iteration 2 after 454.338µs
Finished iteration 3 after 5.771825ms
Finished iteration 4 after 68.246147ms
Finished iteration 5 after 979.00466ms
Finished iteration 6 after 8.038136315s
Finished iteration 7 after 26.631188851s
Finished iteration 8 after 23.54796049s
Finished iteration 9 after 2.424071768s
Time elapsed: 61.69526831s
RAYON_NUM_THREADS=1 target/release/examples/ac  119.23s user 2.07s system 99% cpu 2:01.34 total
➜  egglog git:(oflatt-refactor-parallel) ✗ time RAYON_NUM_THREADS=16 target/release/examples/ac
Finished iteration 0 after 157.386µs
Finished iteration 1 after 240.079µs
Finished iteration 2 after 1.431775ms
Finished iteration 3 after 10.507999ms
Finished iteration 4 after 41.968023ms
Finished iteration 5 after 400.337297ms
Finished iteration 6 after 2.173587709s
Finished iteration 7 after 5.739993083s
Finished iteration 8 after 3.261168366s
Finished iteration 9 after 349.791391ms
Finished iteration 10 after 107.424µs
Time elapsed: 11.982419906s
Finished iteration 0 after 168.377µs
Finished iteration 1 after 252.77µs
Finished iteration 2 after 1.348472ms
Finished iteration 3 after 18.292261ms
Finished iteration 4 after 74.817651ms
Finished iteration 5 after 418.071608ms
Finished iteration 6 after 2.154349018s
Finished iteration 7 after 5.741408833s
Finished iteration 8 after 3.29963215s
Finished iteration 9 after 360.842301ms
Finished iteration 10 after 106.194µs
Time elapsed: 12.069824276s
RAYON_NUM_THREADS=16 target/release/examples/ac  211.33s user 11.58s system 916% cpu 24.323 total

@yihozhang
Copy link
Copy Markdown
Collaborator

I'll make another PR that merges into this one and moves the thread pool to the backend database, since it seems that is where the pool should be

Comment thread benches/common.rs
@oflatt oflatt changed the title Refactor parallelism to use local thread pool Refactor parallelism in testing Apr 3, 2026
Comment thread src/lib.rs
}
#[cfg(not(target_family = "wasm"))]
{
// This will fail silently if the global pool has already been configured.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Print a log indicating the thread pool has been properly initialized? Currently we don't know if it's initialized (or a failure due to repeated initialization happened).

Also, with_num_threads no longer seems to be the right interface, since it just returns self. Maybe the driver (cli.rs) should config this explicitly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Changed to set_num_threads. We'll fix this when we refactor to use a local pool.

@oflatt oflatt requested a review from yihozhang April 6, 2026 18:47
Comment thread src/lib.rs
@oflatt oflatt merged commit 6b04aeb into main Apr 6, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants