@@ -13,6 +13,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
1313use std:: sync:: Arc ;
1414use std:: task:: Poll ;
1515use std:: time:: Duration ;
16+ use tracing:: Instrument ;
1617
1718pub struct ConnectionSet < C > {
1819 global : Arc < Global > ,
@@ -120,22 +121,37 @@ impl<C> ConnectionSet<C> {
120121 }
121122
122123 async fn acquire_inner ( & self , pref : AcquirePreference ) -> SlotGuard < C > {
123- let preferred_slot = current_thread_id ( ) % self . slots . len ( ) ;
124-
125- tracing:: trace!( preferred_slot, ?pref, "acquire_inner" ) ;
124+ let preferred_slot = current_thread_id ( ) % self . slots . len ( ) ;
126125
127126 // Always try to lock the connection associated with our thread ID
128127 let mut acquire_preferred = pin ! ( self . slots[ preferred_slot] . acquire( pref) ) ;
129128
129+ let alternate_slot = ( preferred_slot + 547usize . wrapping_mul (
130+ Arc :: strong_count ( & self . slots [ preferred_slot] . connection )
131+ ) ) % self . slots . len ( ) ;
132+
133+ let mut acquire_alternate = pin ! ( self . slots[ alternate_slot] . acquire( pref) ) ;
134+
130135 let mut listen_global = pin ! ( self . global. listen( pref) ) ;
131136
132- let mut yielded = false ;
137+ let mut yielded_1 = false ;
138+ let mut yielded_2 = false ;
133139
134140 std:: future:: poll_fn ( |cx| {
135141 if let Poll :: Ready ( locked) = acquire_preferred. as_mut ( ) . poll ( cx) {
136142 return Poll :: Ready ( locked) ;
137143 }
138144
145+ if let Poll :: Ready ( locked) = acquire_alternate. as_mut ( ) . poll ( cx) {
146+ return Poll :: Ready ( locked) ;
147+ }
148+
149+ // if !yielded_1 {
150+ // cx.waker().wake_by_ref();
151+ // yielded_1 = true;
152+ // return Poll::Pending;
153+ // }
154+
139155 if let Poll :: Ready ( slot) = listen_global. as_mut ( ) . poll ( cx) {
140156 if let Some ( locked) = self . slots [ slot] . try_acquire ( pref) {
141157 return Poll :: Ready ( locked) ;
@@ -144,9 +160,9 @@ impl<C> ConnectionSet<C> {
144160 listen_global. as_mut ( ) . set ( self . global . listen ( pref) ) ;
145161 }
146162
147- if !yielded {
163+ if !yielded_2 {
148164 cx. waker ( ) . wake_by_ref ( ) ;
149- yielded = true ;
165+ yielded_2 = true ;
150166 return Poll :: Pending ;
151167 }
152168
@@ -156,6 +172,12 @@ impl<C> ConnectionSet<C> {
156172
157173 Poll :: Pending
158174 } )
175+ . instrument ( tracing:: trace_span!(
176+ target: "sqlx::pool::connection_set" ,
177+ "acquire_inner" ,
178+ preferred_slot,
179+ ?pref,
180+ ) )
159181 . await
160182 }
161183
@@ -174,14 +196,24 @@ impl<C> ConnectionSet<C> {
174196 }
175197
176198 fn try_acquire ( & self , pref : AcquirePreference ) -> Option < SlotGuard < C > > {
177- let mut search_slot = current_thread_id ( ) % self . slots . len ( ) ;
199+ let preferred_slot = current_thread_id ( ) % self . slots . len ( ) ;
178200
179- for _ in 0 ..self . slots . len ( ) {
180- if let Some ( locked) = self . slots [ search_slot] . try_acquire ( pref) {
181- return Some ( locked) ;
201+ let ( slots_before, slots_after) = self . slots . split_at ( preferred_slot) ;
202+
203+ let ( preferred_slot, slots_after) = slots_after. split_first ( ) . unwrap ( ) ;
204+
205+ if let Some ( locked) = preferred_slot. try_acquire ( pref) {
206+ return Some ( locked) ;
207+ }
208+
209+ for slot in slots_before. iter ( ) . chain ( slots_after) . rev ( ) {
210+ if self . global . locked_set [ slot. index ] . load ( Ordering :: Relaxed ) {
211+ continue ;
182212 }
183213
184- search_slot = self . next_slot ( search_slot) ;
214+ if let Some ( locked) = slot. try_acquire ( pref) {
215+ return Some ( locked) ;
216+ }
185217 }
186218
187219 None
@@ -398,6 +430,7 @@ impl<C> SlotGuard<C> {
398430 let connected = locked. is_some ( ) ;
399431 self . slot . set_is_connected ( connected) ;
400432 self . slot . locked . store ( false , Ordering :: Release ) ;
433+ self . slot . global . locked_set [ self . slot . index ] . store ( false , Ordering :: Relaxed ) ;
401434 connected
402435 } )
403436 }
0 commit comments