about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-27 22:26:37 +0000
committerbors <bors@rust-lang.org>2024-01-27 22:26:37 +0000
commit635124704849eeead4e3a7bb6e663c5351571d93 (patch)
treed0051c5c19bd54511a2a01b44548349c012a65e2
parent6b4f1c5e782c72a047a23e922decd33e7d462345 (diff)
parent1696148a894f6e5fd8857400ebede44dedee0e2c (diff)
downloadrust-635124704849eeead4e3a7bb6e663c5351571d93.tar.gz
rust-635124704849eeead4e3a7bb6e663c5351571d93.zip
Auto merge of #120024 - Mark-Simulacrum:fast-union-merge, r=cjgillot
Merge into larger interval set

This reduces the work done while merging rows. In at least one case (#50450), we have thousands of union([range], [20,000 ranges]), which previously inserted each of the 20,000 ranges one by one. Now we only insert one range into the right hand set after copying the set over.

This cuts the runtime of the test case in #50450 from ~26 seconds to ~6 seconds locally, though it doesn't change the memory usage peak (~9.5GB).
-rw-r--r--compiler/rustc_index/src/interval.rs6
1 files changed, 6 insertions, 0 deletions
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index d3cf267dc9d..0c1180b3e98 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -236,6 +236,12 @@ impl<I: Idx> IntervalSet<I> {
         I: Step,
     {
         assert_eq!(self.domain, other.domain);
+        if self.map.len() < other.map.len() {
+            let backup = self.clone();
+            self.map.clone_from(&other.map);
+            return self.union(&backup);
+        }
+
         let mut did_insert = false;
         for range in other.iter_intervals() {
             did_insert |= self.insert_range(range);