Skip to content

Proof optimization- consolidate proof and view/UF tables#850

Open
oflatt wants to merge 6 commits intomainfrom
oflatt-proof-optimization
Open

Proof optimization- consolidate proof and view/UF tables#850
oflatt wants to merge 6 commits intomainfrom
oflatt-proof-optimization

Conversation

@oflatt
Copy link
Copy Markdown
Member

@oflatt oflatt commented Apr 18, 2026

This PR makes proofs twice as fast by consolidating tables, also resulting in a negative diff in the core proof instrumentation

Copilot AI review requested due to automatic review settings April 18, 2026 15:34
@oflatt oflatt requested a review from a team as a code owner April 18, 2026 15:34
@oflatt oflatt requested review from yihozhang and removed request for a team April 18, 2026 15:34
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 speeds up proof execution by consolidating proof-related tables (UF + view proof) into fewer function-backed tables, and introduces a built-in Pair container sort to bundle related values (e.g., UF leader + proof) for more efficient lookups.

Changes:

  • Consolidate UF + view proof storage by making UF and view tables function-backed and storing proofs in the function output column (or Unit when proofs are disabled).
  • Add a Pair container sort plus primitives (pair, pair-first, pair-second) and use it for proof-mode UF indexing.
  • Extend parsing/AST/desugaring/extraction to support :term-constructor and :unextractable on function, update subsumption/extraction logic accordingly, and add seminaive “skip focus atom” support in egglog-bridge.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/proofs/proof_encoding.rs Main consolidation of UF/view tables into functions; UF index now returns Pair(leader, proof) in proof mode.
src/proofs/proof_encoding_helpers.rs Removes separate UF/view proof-name maps; adds UF pair sort naming + proof_type_str().
src/proofs/proof_encoding.md Updates documentation to reflect function-backed UF/view tables and proof storage semantics.
src/sort/pair.rs New Pair container sort implementation and primitives.
src/sort/mod.rs, src/lib.rs Wires PairSort into the default EGraph and enables subsumption for view functions (term_constructor).
src/ast/parse.rs, src/ast/mod.rs, src/ast/desugar.rs Adds :term-constructor/:unextractable to function syntax and propagates metadata.
src/extract.rs Allows extracting from functions with term_constructor (view tables), with options to skip them for proof extraction.
egglog-bridge/src/rule.rs Adds skip_seminaive support and public APIs to control seminaive variant generation.
tests/integration_test.rs, tests/pair.egg, snapshots Adds coverage for constructor option rejection and new Pair behavior; updates snapshots for new printed forms.

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

}
// View is always a function (returning Proof or Unit), with :merge old
let proof_type = self.proof_type_str().to_string();
let mut view_flags = String::new();
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

fdecl.cost is only propagated to the hidden/unextractable term constructor (line 472), but the extractable view table is now a function (lines 453–467) and cannot carry :cost. Since extraction now uses view tables (functions with term_constructor) for user-facing extraction, this makes any user-specified constructor costs effectively ignored (all view rows fall back to the default cost). Consider adding :cost support for function, or teaching extraction to use the referenced term_constructor's cost when term_constructor.is_some().

Suggested change
let mut view_flags = String::new();
let mut view_flags = String::new();
if let Some(cost) = fdecl.cost {
view_flags.push_str(&format!(" :cost {cost}"));
}

Copilot uses AI. Check for mistakes.
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.

ah this is a real problem

Comment thread egglog-bridge/src/rule.rs
Comment on lines 796 to 800
'outer: for focus_atom in 0..self.atoms.len() {
if self.skip_seminaive.contains(&focus_atom) {
continue;
}
for (i, (_, _, schema_info)) in self.atoms.iter().enumerate() {
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

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

skip_seminaive is a Vec<usize> and this loop calls contains() inside the seminaive variant generation (including in the nested atom loop). This turns seminaive rule construction into extra O(atoms * skipped) scans and can become noticeable for large rulesets. Consider representing skip_seminaive as a FixedBitSet/Vec<bool> (indexed by atom) or dedup/sort once and use binary search.

Copilot uses AI. Check for mistakes.
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.

hmm this shouldn't be here anymore

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.

we should rip out the changes in this file

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.78102% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.19%. Comparing base (21b99b6) to head (ef00588).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
src/sort/pair.rs 78.49% 20 Missing ⚠️
egglog-bridge/src/rule.rs 54.54% 5 Missing ⚠️
src/prelude.rs 0.00% 2 Missing ⚠️
src/ast/parse.rs 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #850      +/-   ##
==========================================
- Coverage   86.26%   86.19%   -0.08%     
==========================================
  Files          85       86       +1     
  Lines       23262    23348      +86     
==========================================
+ Hits        20067    20124      +57     
- Misses       3195     3224      +29     

☔ 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.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Apr 18, 2026

Merging this PR will improve performance by 43.49%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 6 improved benchmarks
✅ 34 untouched benchmarks
⏩ 190 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime tests[proof_testing_unify] 22.1 ms 18 ms +23.01%
WallTime tests[proof_testing_eqsat-basic] 35.7 ms 26.2 ms +36.08%
WallTime tests[proof_testing_typecheck] 238.1 ms 165.9 ms +43.49%
Simulation tests[proof_testing_unify] 20.4 ms 15.7 ms +29.62%
Simulation tests[proof_testing_eqsat-basic] 34 ms 24.6 ms +38.18%
Simulation tests[proof_testing_typecheck] 218.4 ms 153.6 ms +42.22%

Comparing oflatt-proof-optimization (ef00588) with main (b27cd22)

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.

(sort __view)
(constructor Add (i64 i64) Math :unextractable :internal-hidden)
(constructor __AddView (i64 i64 Math) __view :term-constructor Add)
(function __AddView (i64 i64 Math) Unit :merge old :term-constructor Add)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just curious, why do we need merge old here? Shouldn't any two units be the same value so the default merge function of assert equality should be fine?

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.

4 participants