avoid calling insert_presorted more than once

This commit is contained in:
Ralf Jung
2025-09-08 16:10:37 +02:00
parent 64ea775d27
commit 7abbc9c8b2
2 changed files with 17 additions and 11 deletions
@@ -249,7 +249,7 @@ pub fn insert_presorted(
}
};
// Insert the rest
// Insert the rest. This is super inefficicent since each insertion copies the entire tail.
for (k, v) in elements {
self.insert(k, v);
}
@@ -376,18 +376,24 @@ pub fn prepare_copy(
pub fn apply_copy(&mut self, copy: ProvenanceCopy<Prov>, range: AllocRange, repeat: u64) {
let shift_offset = |idx: u64, offset: Size| offset + range.start + idx * range.size;
if !copy.ptrs.is_empty() {
for i in 0..repeat {
self.ptrs.insert_presorted(
copy.ptrs.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)),
);
}
// We want to call `insert_presorted` only once so that, if possible, the entries
// after the range we insert are moved back only once.
let chunk_len = copy.ptrs.len() as u64;
self.ptrs.insert_presorted((0..chunk_len * repeat).map(|i| {
let chunk = i / chunk_len;
let (offset, reloc) = copy.ptrs[(i % chunk_len) as usize];
(shift_offset(chunk, offset), reloc)
}));
}
if !copy.bytes.is_empty() {
for i in 0..repeat {
self.bytes.get_or_insert_with(Box::default).insert_presorted(
copy.bytes.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)),
);
}
let chunk_len = copy.bytes.len() as u64;
self.bytes.get_or_insert_with(Box::default).insert_presorted(
(0..chunk_len * repeat).map(|i| {
let chunk = i / chunk_len;
let (offset, reloc) = copy.bytes[(i % chunk_len) as usize];
(shift_offset(chunk, offset), reloc)
}),
);
}
}
}