Преглед на файлове

Used a pool of buffers to avoid allocating during every read in the ServerCallback.

Matthew Carr преди 2 години
родител
ревизия
3359079efe
променени са 3 файла, в които са добавени 34 реда и са изтрити 4 реда
  1. 19 0
      Cargo.lock
  2. 1 0
      crates/btfproto/Cargo.toml
  3. 14 4
      crates/btfproto/src/server.rs

+ 19 - 0
Cargo.lock

@@ -189,6 +189,7 @@ dependencies = [
  "paste",
  "positioned-io",
  "serde",
+ "swimmer",
  "tokio",
 ]
 
@@ -1875,6 +1876,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "swimmer"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "963def60929892c4b13817d852a02ae7516d43e5aa8e0eeb560f580b1ce1e157"
+dependencies = [
+ "thread_local",
+]
+
 [[package]]
 name = "swtpm-harness"
 version = "0.1.0"
@@ -1970,6 +1980,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "thread_local"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
+dependencies = [
+ "lazy_static",
+]
+
 [[package]]
 name = "time"
 version = "0.1.44"

+ 1 - 0
crates/btfproto/Cargo.toml

@@ -24,3 +24,4 @@ positioned-io = { version = "0.3.1", optional = true }
 fuse-backend-rs = { version = "0.9.6", optional = true }
 btserde = { path = "../btserde", optional = true }
 bytes = { version = "1.3.0", optional = true }
+swimmer = "0.3.0"

+ 14 - 4
crates/btfproto/src/server.rs

@@ -8,6 +8,7 @@ use btlib::{crypto::Creds, BlockPath, Result};
 use btmsg::{receiver, MsgCallback, MsgReceived, Receiver};
 use core::future::Future;
 use std::{io::Read, net::IpAddr, sync::Arc};
+use swimmer::Pool;
 
 pub trait FsProvider: Send + Sync {
     type LookupFut<'c>: Send + Future<Output = Result<LookupReply>>
@@ -237,12 +238,22 @@ impl<P: FsProvider> FsProvider for &P {
 }
 
 struct ServerCallback<P> {
+    pool: Arc<Pool<Vec<u8>>>,
     provider: Arc<P>,
 }
 
 impl<P> ServerCallback<P> {
+    const POOL_SZ: usize = 8;
+
     fn new(provider: Arc<P>) -> Self {
-        Self { provider }
+        let pool = swimmer::builder()
+            .with_starting_size(Self::POOL_SZ)
+            .with_supplier(|| Vec::with_capacity(btlib::SECTOR_SZ_DEFAULT))
+            .build();
+        Self {
+            provider,
+            pool: Arc::new(pool),
+        }
     }
 }
 
@@ -250,6 +261,7 @@ impl<P> Clone for ServerCallback<P> {
     fn clone(&self) -> Self {
         Self {
             provider: self.provider.clone(),
+            pool: self.pool.clone(),
         }
     }
 }
@@ -267,9 +279,7 @@ impl<P: 'static + Send + Sync + FsProvider> MsgCallback for ServerCallback<P> {
                 FsMsg::Open(open) => FsReply::Open(provider.open(&from, open).await?),
                 FsMsg::Read(read) => {
                     let buf = provider.read(&from, read, move |data| {
-                        // TODO: Avoid allocating a buffer on every read. If possible, avoid coping
-                        // data altogether.
-                        let mut buf = Vec::with_capacity(data.len());
+                        let mut buf = self.pool.get();
                         buf.extend_from_slice(data);
                         buf
                     })?;