diff --git a/sstable/src/delta.rs b/sstable/src/delta.rs index 9c17e2de5f..d4fa129f4f 100644 --- a/sstable/src/delta.rs +++ b/sstable/src/delta.rs @@ -16,6 +16,8 @@ where W: io::Write block: Vec, write: CountingWriter>, value_writer: TValueWriter, + // Only here to avoid allocations. + stateless_buffer: Vec, } impl DeltaWriter @@ -28,6 +30,7 @@ where block: Vec::with_capacity(BLOCK_LEN * 2), write: CountingWriter::wrap(BufWriter::new(wrt)), value_writer: TValueWriter::default(), + stateless_buffer: Vec::new(), } } } @@ -42,15 +45,16 @@ where return Ok(None); } let start_offset = self.write.written_bytes() as usize; - // TODO avoid buffer allocation - let mut buffer = Vec::new(); - self.value_writer.serialize_block(&mut buffer); + let buffer: &mut Vec = &mut self.stateless_buffer; + self.value_writer.serialize(buffer); + self.value_writer.clear(); let block_len = buffer.len() + self.block.len(); self.write.write_all(&(block_len as u32).to_le_bytes())?; self.write.write_all(&buffer[..])?; self.write.write_all(&self.block[..])?; let end_offset = self.write.written_bytes() as usize; self.block.clear(); + buffer.clear(); Ok(Some(start_offset..end_offset)) } diff --git a/sstable/src/value/mod.rs b/sstable/src/value/mod.rs index 378c604175..326aac3520 100644 --- a/sstable/src/value/mod.rs +++ b/sstable/src/value/mod.rs @@ -20,6 +20,8 @@ pub trait ValueReader: Default { fn load(&mut self, data: &[u8]) -> io::Result; } +/// `ValueWriter` is a trait to make it possible to write blocks +/// of value. pub trait ValueWriter: Default { /// Type of the value being written. type Value; @@ -30,7 +32,11 @@ pub trait ValueWriter: Default { fn write(&mut self, val: &Self::Value); /// Serializes the accumulated values into the output buffer. - fn serialize_block(&mut self, output: &mut Vec); + fn serialize(&self, output: &mut Vec); + + /// Clears the `ValueWriter`. After a call to clear, the `ValueWriter` + /// should behave like a fresh `ValueWriter::default()`. + fn clear(&mut self); } pub use range::{RangeReader, RangeWriter}; @@ -62,7 +68,8 @@ pub(crate) mod tests { for value in value_block { writer.write(value); } - writer.serialize_block(&mut buffer); + writer.serialize(&mut buffer); + writer.clear(); } let data_len = buffer.len(); buffer.extend_from_slice(&b"extradata"[..]); diff --git a/sstable/src/value/range.rs b/sstable/src/value/range.rs index 3ef554a88f..43ed1d9643 100644 --- a/sstable/src/value/range.rs +++ b/sstable/src/value/range.rs @@ -49,7 +49,7 @@ impl ValueWriter for RangeWriter { } } - fn serialize_block(&mut self, writer: &mut Vec) { + fn serialize(&self, writer: &mut Vec) { let mut prev_val = 0u64; crate::vint::serialize_into_vec(self.vals.len() as u64, writer); for &val in &self.vals { @@ -57,6 +57,9 @@ impl ValueWriter for RangeWriter { crate::vint::serialize_into_vec(delta, writer); prev_val = val; } + } + + fn clear(&mut self) { self.vals.clear(); } } diff --git a/sstable/src/value/u64_monotonic.rs b/sstable/src/value/u64_monotonic.rs index d40ade06d3..311967562f 100644 --- a/sstable/src/value/u64_monotonic.rs +++ b/sstable/src/value/u64_monotonic.rs @@ -42,7 +42,7 @@ impl ValueWriter for U64MonotonicWriter { self.vals.push(*val); } - fn serialize_block(&mut self, output: &mut Vec) { + fn serialize(&self, output: &mut Vec) { let mut prev_val = 0u64; vint::serialize_into_vec(self.vals.len() as u64, output); for &val in &self.vals { @@ -50,6 +50,9 @@ impl ValueWriter for U64MonotonicWriter { vint::serialize_into_vec(delta, output); prev_val = val; } + } + + fn clear(&mut self) { self.vals.clear(); } } diff --git a/sstable/src/value/void.rs b/sstable/src/value/void.rs index 2da7196b50..2e2240bbd3 100644 --- a/sstable/src/value/void.rs +++ b/sstable/src/value/void.rs @@ -25,7 +25,9 @@ impl ValueWriter for VoidWriter { fn write(&mut self, _val: &()) {} - fn serialize_block(&mut self, _output: &mut Vec) {} + fn serialize(&self, _output: &mut Vec) {} + + fn clear(&mut self) {} } #[cfg(test)]