commit 01b6111bbce933ef05f48fc05758256ac11194c0
Author: shirotech <van@shirotech.com>
Date: Thu May 14 18:34:35 2026 +0000
optimize: batch-len-prefix-and-payload [KEPT] -4.5% on reopen_10k
Reserve LEN_BYTES at the front of `scratch` so `flush_scratch` can emit
the length-prefix and payload in a single `BufWriter::write_all` per
mutation. On-disk format unchanged. Mutation scenarios came in flat
(within ±1% noise), but reopen_10k improved -4.79% / -4.71% / -4.54%
consistently across 3 independent runs against a fixed pre-change
baseline; no scenario regressed past +2%. Verdict KEPT per /optimize
gate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
diff --git a/src/lib.rs b/src/lib.rs
index d51b015..42d5a2b 100644
@@ -207,6 +207,7 @@ where
/// [`IndexMap::insert`] semantics).
pub fn insert(&mut self, k: K, v: V) -> io::Result<Option<V>> {
self.scratch.clear();
+ self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
bincode::serialize_into(&mut self.scratch, &LogRef::Insert::<K, V>(&k, &v))
.map_err(serialize_err)?;
self.flush_scratch()?;
@@ -226,6 +227,7 @@ where
return Ok(None);
}
self.scratch.clear();
+ self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
bincode::serialize_into(&mut self.scratch, &LogRef::Remove::<K, V>(k))
.map_err(serialize_err)?;
self.flush_scratch()?;
@@ -253,6 +255,7 @@ where
let v_ref: &V = v_mut;
self.scratch.clear();
+ self.scratch.extend_from_slice(&[0u8; LEN_BYTES]);
bincode::serialize_into(&mut self.scratch, &LogRef::Insert::<K, V>(k, v_ref))
.map_err(serialize_err)?;
@@ -307,10 +310,12 @@ where
}
fn flush_scratch(&mut self) -> io::Result<()> {
- let len = self.scratch.len() as u32;
- self.log.write_all(&len.to_le_bytes())?;
+ // Callers reserve LEN_BYTES at the front of `scratch`; fill the length
+ // in place so the length-prefix and payload land in a single write.
+ let payload_len = (self.scratch.len() - LEN_BYTES) as u32;
+ self.scratch[..LEN_BYTES].copy_from_slice(&payload_len.to_le_bytes());
self.log.write_all(&self.scratch)?;
- self.log_bytes += (LEN_BYTES + self.scratch.len()) as u64;
+ self.log_bytes += self.scratch.len() as u64;
if self.cfg.sync_on_write {
self.log.flush()?;
self.log.get_ref().sync_data()?;