Skip to content

Commit 0095644

Browse files
committed
WIP refactor: simpler acquire strategy
1 parent 0dd92b4 commit 0095644

1 file changed

Lines changed: 16 additions & 42 deletions

File tree

sqlx-core/src/pool/connection_set.rs

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum AcquirePreference {
3333
struct Global {
3434
unlock_event: Event<usize>,
3535
disconnect_event: Event<usize>,
36+
locked_set: Box<[AtomicBool]>,
3637
num_connected: AtomicUsize,
3738
min_connections: usize,
3839
min_connections_event: Event<()>,
@@ -63,6 +64,7 @@ impl<C> ConnectionSet<C> {
6364
let global = Arc::new(Global {
6465
unlock_event: Event::with_tag(),
6566
disconnect_event: Event::with_tag(),
67+
locked_set: (0..*size.end()).map(|_| AtomicBool::new(false)).collect(),
6668
num_connected: AtomicUsize::new(0),
6769
min_connections: *size.start(),
6870
min_connections_event: Event::with_tag(),
@@ -118,69 +120,41 @@ impl<C> ConnectionSet<C> {
118120
}
119121

120122
async fn acquire_inner(&self, pref: AcquirePreference) -> SlotGuard<C> {
121-
/// Smallest time-step supported by [`tokio::time::sleep()`].
122-
///
123-
/// `async-io` doesn't document a minimum time-step, instead deferring to the platform.
124-
const STEP_INTERVAL: Duration = Duration::from_millis(1);
125-
126-
const SEARCH_LIMIT: usize = 5;
127-
128-
let preferred_slot = current_thread_id() % self.slots.len();
123+
let preferred_slot = current_thread_id() % self.slots.len();
129124

130125
tracing::trace!(preferred_slot, ?pref, "acquire_inner");
131126

132127
// Always try to lock the connection associated with our thread ID
133128
let mut acquire_preferred = pin!(self.slots[preferred_slot].acquire(pref));
134129

135-
let mut step_interval = pin!(rt::interval_after(STEP_INTERVAL));
136-
137-
let mut intervals_elapsed = 0usize;
138-
139-
let mut search_slots = FuturesUnordered::new();
140-
141130
let mut listen_global = pin!(self.global.listen(pref));
142131

143-
let mut search_slot = self.next_slot(preferred_slot);
132+
let mut yielded = false;
144133

145-
std::future::poll_fn(|cx| loop {
134+
std::future::poll_fn(|cx| {
146135
if let Poll::Ready(locked) = acquire_preferred.as_mut().poll(cx) {
147136
return Poll::Ready(locked);
148137
}
149138

150-
// Don't push redundant futures for small sets.
151-
let search_limit = cmp::min(SEARCH_LIMIT, self.slots.len());
152-
153-
if search_slots.len() < search_limit && step_interval.as_mut().poll_tick(cx).is_ready()
154-
{
155-
intervals_elapsed = intervals_elapsed.saturating_add(1);
156-
157-
if search_slot != preferred_slot && self.slots[search_slot].matches_pref(pref) {
158-
search_slots.push(self.slots[search_slot].lock());
159-
}
160-
161-
search_slot = self.next_slot(search_slot);
162-
}
163-
164-
if let Poll::Ready(Some(locked)) = Pin::new(&mut search_slots).poll_next(cx) {
165-
if locked.matches_pref(pref) {
139+
if let Poll::Ready(slot) = listen_global.as_mut().poll(cx) {
140+
if let Some(locked) = self.slots[slot].try_acquire(pref) {
166141
return Poll::Ready(locked);
167142
}
168143

169-
continue;
144+
listen_global.as_mut().set(self.global.listen(pref));
170145
}
171146

172-
if intervals_elapsed > search_limit && search_slots.len() < search_limit {
173-
if let Poll::Ready(slot) = listen_global.as_mut().poll(cx) {
174-
if self.slots[slot].matches_pref(pref) {
175-
search_slots.push(self.slots[slot].lock());
176-
}
147+
if !yielded {
148+
cx.waker().wake_by_ref();
149+
yielded = true;
150+
return Poll::Pending;
151+
}
177152

178-
listen_global.as_mut().set(self.global.listen(pref));
179-
continue;
180-
}
153+
if let Some(locked) = self.try_acquire(pref) {
154+
return Poll::Ready(locked);
181155
}
182156

183-
return Poll::Pending;
157+
Poll::Pending
184158
})
185159
.await
186160
}

0 commit comments

Comments
 (0)