Skip to content

Commit

Permalink
Use Arc wrapper for ConnectOptions to reduce lock contention
Browse files Browse the repository at this point in the history
  • Loading branch information
moatra committed Sep 15, 2022
1 parent ed709f7 commit 5b8dfa5
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 11 deletions.
7 changes: 6 additions & 1 deletion sqlx-core/src/mysql/testing/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -152,7 +153,11 @@ async fn test_context(args: &TestArgs) -> Result<TestContext<MySql>, 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,
})
}
Expand Down
6 changes: 3 additions & 3 deletions sqlx-core/src/pool/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use futures_util::FutureExt;
use std::time::{Duration, Instant};

pub(crate) struct PoolInner<DB: Database> {
pub(super) connect_options: RwLock<<DB::Connection as Connection>::Options>,
pub(super) connect_options: RwLock<Arc<<DB::Connection as Connection>::Options>>,
pub(super) idle_conns: ArrayQueue<Idle<DB>>,
pub(super) semaphore: Semaphore,
pub(super) size: AtomicU32,
Expand All @@ -47,7 +47,7 @@ impl<DB: Database> PoolInner<DB> {
};

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),
Expand Down Expand Up @@ -292,7 +292,7 @@ impl<DB: Database> PoolInner<DB> {
loop {
let timeout = deadline_as_timeout::<DB>(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
Expand Down
9 changes: 3 additions & 6 deletions sqlx-core/src/pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ impl<DB: Database> Pool<DB> {
}

/// Gets a clone of the connection options for this pool
pub fn connect_options(&self) -> <DB::Connection as Connection>::Options {
pub fn connect_options(&self) -> Arc<<DB::Connection as Connection>::Options> {
self.0
.connect_options
.read()
Expand All @@ -501,18 +501,15 @@ impl<DB: Database> Pool<DB> {

/// 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: <DB::Connection as Connection>::Options,
) {
pub fn set_connect_options(&self, connect_options: <DB::Connection as Connection>::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
.0
.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
Expand Down
7 changes: 6 additions & 1 deletion sqlx-core/src/postgres/testing/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -159,7 +160,11 @@ async fn test_context(args: &TestArgs) -> Result<TestContext<Postgres>, 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,
})
}
Expand Down

0 comments on commit 5b8dfa5

Please sign in to comment.