Repository: blackbeam/mysql_async (language: rust)

Issue:
BufferPool is extremely slow under contention
I am running a highly concurrent MySQL client and the Mutex contention in BufferPool leads to extreme slowdown.

I tried replacing the `Mutex<Vec<_>>` `with crossbeam::queue::ArrayQueue` and it led to a 4 fold performance improvement (in terms of QPS). I don't really see any downsides in using `ArrayQueue` even under low load, so if you would consider it I will be more than happy to open a pull request.

Thanks.


Discussion / hints:

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index ad3d8765..87702800 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,7 @@ categories = ["asynchronous", "database"]
 
 [dependencies]
 bytes = "1.0"
+crossbeam = "0.8"
 flate2 = { version = "1.0", default-features = false }
 futures-core = "0.3"
 futures-util = "0.3"
diff --git a/src/buffer_pool.rs b/src/buffer_pool.rs
index 14116688..3b2e9a74 100644
--- a/src/buffer_pool.rs
+++ b/src/buffer_pool.rs
@@ -6,17 +6,13 @@
 // option. All files in the project carrying such notice may not be copied,
 // modified, or distributed except according to those terms.
 
-use std::{
-    mem::replace,
-    ops::Deref,
-    sync::{Arc, Mutex},
-};
+use crossbeam::queue::ArrayQueue;
+use std::{mem::replace, ops::Deref, sync::Arc};
 
 #[derive(Debug)]
 pub struct BufferPool {
-    pool_cap: usize,
     buffer_cap: usize,
-    pool: Mutex<Vec<Vec<u8>>>,
+    pool: ArrayQueue<Vec<u8>>,
 }
 
 impl BufferPool {
@@ -32,14 +28,13 @@ impl BufferPool {
             .unwrap_or(4 * 1024 * 1024);
 
         Self {
-            pool: Default::default(),
-            pool_cap,
+            pool: ArrayQueue::new(pool_cap),
             buffer_cap,
         }
     }
 
     pub fn get(self: &Arc<Self>) -> PooledBuf {
-        let mut buf = self.pool.lock().unwrap().pop().unwrap_or_default();
+        let mut buf = self.pool.pop().unwrap_or_default();
 
         // SAFETY:
         // 1. OK – 0 is always within capacity
@@ -66,10 +61,8 @@ impl BufferPool {
             buf.shrink_to_fit();
         }
 
-        let mut pool = self.pool.lock().unwrap();
-        if pool.len() < self.pool_cap {
-            pool.push(buf);
-        }
+        // ArrayQueue will make sure to drop the buffer if capacity is exceeded
+        let _ = self.pool.push(buf);
     }
 }
 


Test patch: