Ver Fonte

Improved write performance by buffering writes in `Trailered`.

Matthew Carr há 2 anos atrás
pai
commit
857e996ad8

+ 3 - 0
crates/btlib/benches/block_benches.rs

@@ -1,3 +1,6 @@
+//! Benchmarks for implementations of the [Block] trait.
+//! You can run these with `cargo bench`.
+
 use std::{fs::OpenOptions, time::Duration};
 
 use btlib::{

+ 16 - 9
crates/btlib/src/trailered.rs

@@ -2,7 +2,7 @@ pub use private::Trailered;
 
 mod private {
     use std::{
-        io::{self, Read, Seek, SeekFrom, Write},
+        io::{self, BufReader, Read, Seek, SeekFrom, Write},
         marker::PhantomData,
     };
 
@@ -16,6 +16,7 @@ mod private {
         inner: T,
         body_len: u64,
         phantom: PhantomData<D>,
+        write_buf: Vec<u8>,
     }
 
     impl<T: Read + Seek, D: DeserializeOwned> Trailered<T, D> {
@@ -24,11 +25,12 @@ mod private {
                 inner,
                 body_len: 0,
                 phantom: PhantomData,
+                write_buf: Vec::new(),
             }
         }
 
         /// Creates a new `Trailered<T>` containing the given `T`. This method requires that the given
-        /// stream is either empty, or contains a valid serialization of `D` and a the offset at which
+        /// stream is either empty, or contains a valid serialization of `D` and the offset at which
         /// `D` is stored.
         pub fn new(mut inner: T) -> Result<(Trailered<T, D>, Option<D>)> {
             let pos = inner.stream_position()?;
@@ -36,17 +38,20 @@ mod private {
             if 0 == end {
                 return Ok((Self::empty(inner), None));
             }
-            let offset: i64 = std::mem::size_of::<i64>().try_into().unwrap();
-            inner.seek(SeekFrom::End(-offset))?;
-            let offset: i64 = read_from(&mut inner)?;
-            let body_len = inner.seek(SeekFrom::End(offset))?;
-            let trailer: D = read_from(&mut inner)?;
+            let mut reader = BufReader::new(inner);
+            let offset: i64 = std::mem::size_of::<i64>() as i64;
+            reader.seek(SeekFrom::End(-offset))?;
+            let offset: i64 = read_from(&mut reader)?;
+            let body_len = reader.seek(SeekFrom::End(offset))?;
+            let trailer: D = read_from(&mut reader)?;
+            let mut inner = reader.into_inner();
             inner.seek(SeekFrom::Start(pos))?;
             Ok((
                 Trailered {
                     inner,
                     body_len,
                     phantom: PhantomData,
+                    write_buf: Vec::new(),
                 },
                 Some(trailer),
             ))
@@ -88,10 +93,12 @@ mod private {
         fn write_trailer(&mut self, trailer: &D) -> io::Result<u64> {
             let pos = self.inner.stream_position()?;
             self.inner.seek(SeekFrom::Start(self.body_len))?;
-            write_to(trailer, &mut self.inner).box_err()?;
+            self.write_buf.clear();
+            write_to(trailer, &mut self.write_buf)?;
             let offset_u64 = 8 + self.inner.stream_position()? - self.body_len;
             let offset = -(offset_u64 as i64);
-            write_to(&offset, &mut self.inner).box_err()?;
+            write_to(&offset, &mut self.write_buf)?;
+            self.inner.write_all(&self.write_buf)?;
             Ok(pos)
         }
 

+ 1 - 2
crates/btserde/src/de.rs

@@ -5,13 +5,12 @@ use std::io::Read;
 use std::str;
 
 // This lint is disabled because deserializing from a `&[u8]` is handled by `read_from`.
-#[allow(clippy::ptr_arg)]
 pub fn from_vec<T: DeserializeOwned>(vec: &Vec<u8>) -> Result<T> {
     let mut slice = vec.as_slice();
     read_from(&mut slice)
 }
 
-pub fn read_from<T: DeserializeOwned, R: Read>(read: &mut R) -> Result<T> {
+pub fn read_from<T: for<'de> Deserialize<'de>, R: Read>(read: &mut R) -> Result<T> {
     let mut de = Deserializer::new(read);
     Deserialize::deserialize(&mut de)
 }

+ 1 - 2
crates/btserde/src/ser.rs

@@ -24,8 +24,7 @@ impl<'w, W: Write> Serializer<'w, W> {
 
 pub fn to_vec<T: Serialize + ?Sized>(value: &T) -> Result<Vec<u8>> {
     let mut vec = Vec::new();
-    let result = write_to(value, &mut vec);
-    result?;
+    write_to(value, &mut vec)?;
     Ok(vec)
 }