From 5b8dfa5dc88de8420f09dd7590952b7693b0ca3d Mon Sep 17 00:00:00 2001 From: Thomas Alton Date: Wed, 14 Sep 2022 20:53:28 -0500 Subject: [PATCH] Use Arc wrapper for ConnectOptions to reduce lock contention --- sqlx-core/src/mysql/testing/mod.rs | 7 ++++++- sqlx-core/src/pool/inner.rs | 6 +++--- sqlx-core/src/pool/mod.rs | 9 +++------ sqlx-core/src/postgres/testing/mod.rs | 7 ++++++- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/sqlx-core/src/mysql/testing/mod.rs b/sqlx-core/src/mysql/testing/mod.rs index 5f476e74a2..c31c868dee 100644 --- a/sqlx-core/src/mysql/testing/mod.rs +++ b/sqlx-core/src/mysql/testing/mod.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::ops::Deref; use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; @@ -152,7 +153,11 @@ async fn test_context(args: &TestArgs) -> Result, Error> { // Close connections ASAP if left in the idle queue. .idle_timeout(Some(Duration::from_secs(1))) .parent(master_pool.clone()), - connect_opts: master_pool.connect_options().clone().database(&new_db_name), + connect_opts: master_pool + .connect_options() + .deref() + .clone() + .database(&new_db_name), db_name: new_db_name, }) } diff --git a/sqlx-core/src/pool/inner.rs b/sqlx-core/src/pool/inner.rs index f7655f5503..2a48ac6347 100644 --- a/sqlx-core/src/pool/inner.rs +++ b/sqlx-core/src/pool/inner.rs @@ -20,7 +20,7 @@ use futures_util::FutureExt; use std::time::{Duration, Instant}; pub(crate) struct PoolInner { - pub(super) connect_options: RwLock<::Options>, + pub(super) connect_options: RwLock::Options>>, pub(super) idle_conns: ArrayQueue>, pub(super) semaphore: Semaphore, pub(super) size: AtomicU32, @@ -47,7 +47,7 @@ impl PoolInner { }; let pool = Self { - connect_options: RwLock::new(connect_options), + connect_options: RwLock::new(Arc::new(connect_options)), idle_conns: ArrayQueue::new(capacity), semaphore: Semaphore::new(options.fair, semaphore_capacity), size: AtomicU32::new(0), @@ -292,7 +292,7 @@ impl PoolInner { loop { let timeout = deadline_as_timeout::(deadline)?; - // clone the connect options so they can be used without holding the RwLockReadGuard + // clone the connect options arc so it can be used without holding the RwLockReadGuard // across an async await point let connect_options = self .connect_options diff --git a/sqlx-core/src/pool/mod.rs b/sqlx-core/src/pool/mod.rs index 64b43c4260..91ac3b8dfb 100644 --- a/sqlx-core/src/pool/mod.rs +++ b/sqlx-core/src/pool/mod.rs @@ -491,7 +491,7 @@ impl Pool { } /// Gets a clone of the connection options for this pool - pub fn connect_options(&self) -> ::Options { + pub fn connect_options(&self) -> Arc<::Options> { self.0 .connect_options .read() @@ -501,10 +501,7 @@ impl Pool { /// Updates the connection options this pool will use when opening any future connections. Any /// existing open connection in the pool will be left as-is. - pub fn with_connect_options( - &self, - mut connect_options: ::Options, - ) { + pub fn set_connect_options(&self, connect_options: ::Options) { // technically write() could also panic if the current thread already holds the lock, // but because this method can't be re-entered by the same thread that shouldn't be a problem let mut guard = self @@ -512,7 +509,7 @@ impl Pool { .connect_options .write() .expect("write-lock holder panicked"); - std::mem::swap(guard.deref_mut(), &mut connect_options); + std::mem::swap(guard.deref_mut(), &mut Arc::new(connect_options)); } /// Get the options for this pool diff --git a/sqlx-core/src/postgres/testing/mod.rs b/sqlx-core/src/postgres/testing/mod.rs index e3640b3bed..b566725a51 100644 --- a/sqlx-core/src/postgres/testing/mod.rs +++ b/sqlx-core/src/postgres/testing/mod.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::ops::Deref; use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; @@ -159,7 +160,11 @@ async fn test_context(args: &TestArgs) -> Result, Error> { // Close connections ASAP if left in the idle queue. .idle_timeout(Some(Duration::from_secs(1))) .parent(master_pool.clone()), - connect_opts: master_pool.connect_options().clone().database(&new_db_name), + connect_opts: master_pool + .connect_options() + .deref() + .clone() + .database(&new_db_name), db_name: new_db_name, }) }