From 53cda6d85ade41080b294881be043060cbe2f1da Mon Sep 17 00:00:00 2001 From: Christopher Hotchkiss Date: Sun, 12 Sep 2021 10:21:14 -0400 Subject: [PATCH] Changed to use supplied buffers to reduce allocations --- src/engine/io/page_formats/page_offset.rs | 26 +++++++++++++++- src/engine/io/row_formats/item_pointer.rs | 38 +++++++++-------------- src/engine/io/row_formats/row_data.rs | 3 +- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/engine/io/page_formats/page_offset.rs b/src/engine/io/page_formats/page_offset.rs index ffe6efb..13a4939 100644 --- a/src/engine/io/page_formats/page_offset.rs +++ b/src/engine/io/page_formats/page_offset.rs @@ -2,7 +2,9 @@ use crate::{ constants::{PAGES_PER_FILE, PAGE_SIZE}, engine::io::ConstEncodedSize, }; +use bytes::{Buf, BufMut}; use std::{ + convert::TryFrom, fmt, mem::size_of, num::TryFromIntError, @@ -14,6 +16,26 @@ use thiserror::Error; pub struct PageOffset(pub usize); impl PageOffset { + pub fn serialize(&self, buffer: &mut impl BufMut) { + //TODO switch this and other serialize calls to usize based once my pull request is accepted + //https://github.com/tokio-rs/bytes/pull/511 + buffer.put_uint_le(self.0 as u64, size_of::()); + } + + pub fn parse(buffer: &mut impl Buf) -> Result { + if buffer.remaining() < size_of::() { + return Err(PageOffsetError::BufferTooShort( + size_of::(), + buffer.remaining(), + )); + } + + let value = buffer.get_uint_le(size_of::()); + let page = usize::try_from(value)?; + + Ok(PageOffset(page)) + } + /// This will calculate a page offset based on the max file count and the offset from the first /// non-zero page in a file. /// @@ -101,8 +123,10 @@ impl Mul for PageOffset { } } -#[derive(Debug, Error)] +#[derive(Debug, Error, PartialEq)] pub enum PageOffsetError { + #[error("Not enough space to parse usize need {0} got {1}")] + BufferTooShort(usize, usize), #[error(transparent)] TryFromIntError(#[from] TryFromIntError), } diff --git a/src/engine/io/row_formats/item_pointer.rs b/src/engine/io/row_formats/item_pointer.rs index 07f8364..77141e5 100644 --- a/src/engine/io/row_formats/item_pointer.rs +++ b/src/engine/io/row_formats/item_pointer.rs @@ -3,7 +3,7 @@ //! //! We will be treating this a little different since our size will be based on usize -use crate::engine::io::page_formats::PageOffset; +use crate::engine::io::page_formats::{PageOffset, PageOffsetError}; use crate::engine::io::ConstEncodedSize; use super::super::page_formats::{UInt12, UInt12Error}; @@ -25,28 +25,15 @@ impl ItemPointer { ItemPointer { page, count } } - pub fn serialize(&self) -> Bytes { - let mut buffer = BytesMut::with_capacity(size_of::()); - - buffer.put_slice(&self.page.0.to_le_bytes()); - UInt12::serialize_packed(&mut buffer, &[self.count]); - - buffer.freeze() + pub fn serialize(&self, buffer: &mut impl BufMut) { + self.page.serialize(buffer); + UInt12::serialize_packed(buffer, &[self.count]); } pub fn parse(buffer: &mut impl Buf) -> Result { - if buffer.remaining() < size_of::() { - return Err(ItemPointerError::BufferTooShort( - size_of::(), - buffer.remaining(), - )); - } - - let value = buffer.get_uint_le(size_of::()); - let page = usize::try_from(value)?; - + let po = PageOffset::parse(buffer)?; let items = UInt12::parse_packed(buffer, 1)?; - Ok(ItemPointer::new(PageOffset(page), items[0])) + Ok(ItemPointer::new(po, items[0])) } } @@ -66,8 +53,8 @@ impl ConstEncodedSize for ItemPointer { #[derive(Debug, Error, PartialEq)] pub enum ItemPointerError { - #[error("Not enough space to parse usize need {0} got {1}")] - BufferTooShort(usize, usize), + #[error(transparent)] + PageOffsetError(#[from] PageOffsetError), #[error(transparent)] TryFromIntError(#[from] TryFromIntError), #[error(transparent)] @@ -84,8 +71,9 @@ mod tests { fn test_item_pointer_roundtrip() -> Result<(), Box> { let test = ItemPointer::new(PageOffset(1), UInt12::new(1).unwrap()); - let mut test_serial = test.clone().serialize(); - let test_reparse = ItemPointer::parse(&mut test_serial)?; + let mut buffer = BytesMut::new(); + test.serialize(&mut buffer); + let test_reparse = ItemPointer::parse(&mut buffer.freeze())?; assert_eq!(test, test_reparse); Ok(()) @@ -96,7 +84,9 @@ mod tests { let parse = ItemPointer::parse(&mut Bytes::new()); assert_eq!( - Err(ItemPointerError::BufferTooShort(size_of::(), 0)), + Err(ItemPointerError::PageOffsetError( + PageOffsetError::BufferTooShort(size_of::(), 0) + )), parse ); diff --git a/src/engine/io/row_formats/row_data.rs b/src/engine/io/row_formats/row_data.rs index 4d8a7a4..da2a6d5 100644 --- a/src/engine/io/row_formats/row_data.rs +++ b/src/engine/io/row_formats/row_data.rs @@ -64,8 +64,7 @@ impl RowData { pub fn serialize(&self, buffer: &mut impl BufMut) { buffer.put_u64_le(self.min.get_u64()); buffer.put_u64_le(self.max.unwrap_or_else(|| TransactionId::new(0)).get_u64()); - - buffer.put(self.item_pointer.serialize()); + self.item_pointer.serialize(buffer); //If there is null we add it to the flags and write a nullmask let mut mask = InfoMask::empty();