Skip to content

Commit 541dc0c

Browse files
committed
Use condvar instead of spinloop at init
1 parent 35dea46 commit 541dc0c

File tree

1 file changed

+51
-17
lines changed

1 file changed

+51
-17
lines changed

pgvectorscale/src/access_method/build.rs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use std::time::Instant;
33

44
use pg_sys::{FunctionCall0Coll, InvalidOid};
55
use pgrx::ffi::c_char;
6-
use pgrx::pg_sys::{index_getprocinfo, pgstat_progress_update_param, AsPgCStr, Oid};
6+
use pgrx::pg_sys::{
7+
index_getprocinfo, pgstat_progress_update_param, AsPgCStr, ConditionVariable, Oid,
8+
};
79
use pgrx::*;
810

911
use crate::access_method::distance::DistanceType;
@@ -112,10 +114,22 @@ impl<'a> BuildStateParallel<'a> {
112114
// Only update shared counter for the initializing worker until threshold is reached
113115
if self.is_initializing_worker && self.local_ntuples <= parallel::INITIAL_START_NODES_COUNT
114116
{
115-
self.shared_state
117+
let new_count = self
118+
.shared_state
116119
.build_state
117120
.ntuples
118-
.fetch_add(1, Ordering::Relaxed);
121+
.fetch_add(1, Ordering::Relaxed)
122+
+ 1;
123+
124+
// Signal waiting workers when threshold is reached
125+
if new_count >= parallel::INITIAL_START_NODES_COUNT {
126+
unsafe {
127+
let cv_ptr = self.shared_state as *const ParallelShared as *mut ParallelShared;
128+
pg_sys::ConditionVariableBroadcast(
129+
&raw mut (*cv_ptr).build_state.initialization_cv,
130+
);
131+
}
132+
}
119133
}
120134
}
121135

@@ -126,6 +140,14 @@ impl<'a> BuildStateParallel<'a> {
126140
.build_state
127141
.initializing_worker_done
128142
.store(true, Ordering::Relaxed);
143+
144+
// Signal waiting workers that initialization is done
145+
unsafe {
146+
let cv_ptr = self.shared_state as *const ParallelShared as *mut ParallelShared;
147+
pg_sys::ConditionVariableBroadcast(
148+
&raw mut (*cv_ptr).build_state.initialization_cv,
149+
);
150+
}
129151
}
130152

131153
self.update_shared_ntuples();
@@ -191,6 +213,7 @@ struct ParallelBuildState {
191213
ntuples: AtomicUsize,
192214
start_nodes_initialized: AtomicBool,
193215
initializing_worker_done: AtomicBool,
216+
initialization_cv: ConditionVariable,
194217
}
195218

196219
/// Status data for parallel index builds, shared among all parallel workers.
@@ -330,7 +353,7 @@ pub extern "C" fn ambuild(
330353
let parallel_shared =
331354
pg_sys::shm_toc_allocate((*pcxt).toc, size_of::<ParallelShared>())
332355
.cast::<ParallelShared>();
333-
parallel_shared.write(ParallelShared {
356+
let shared_state = ParallelShared {
334357
params: ParallelSharedParams {
335358
heaprelid: heap_relation.rd_id,
336359
indexrelid: index_relation.rd_id,
@@ -341,8 +364,15 @@ pub extern "C" fn ambuild(
341364
ntuples: AtomicUsize::new(0),
342365
start_nodes_initialized: AtomicBool::new(false),
343366
initializing_worker_done: AtomicBool::new(false),
367+
initialization_cv: std::mem::zeroed(), // Will be initialized below
344368
},
345-
});
369+
};
370+
parallel_shared.write(shared_state);
371+
372+
// Initialize the condition variable
373+
pg_sys::ConditionVariableInit(
374+
&raw mut (*parallel_shared).build_state.initialization_cv,
375+
);
346376
let tablescandesc =
347377
pg_sys::shm_toc_allocate((*pcxt).toc, tablescandesc_size_estimate)
348378
.cast::<pg_sys::ParallelTableScanDescData>();
@@ -621,23 +651,27 @@ pub extern "C-unwind" fn _vectorscale_build_main(
621651
};
622652

623653
if !should_initialize {
624-
loop {
625-
let ntuples = unsafe {
626-
(*parallel_shared)
654+
unsafe {
655+
loop {
656+
let ntuples = (*parallel_shared)
627657
.build_state
628658
.ntuples
629-
.load(Ordering::Relaxed)
630-
};
631-
let init_done = unsafe {
632-
(*parallel_shared)
659+
.load(Ordering::Relaxed);
660+
let init_done = (*parallel_shared)
633661
.build_state
634662
.initializing_worker_done
635-
.load(Ordering::Relaxed)
636-
};
637-
if ntuples >= parallel::INITIAL_START_NODES_COUNT || init_done {
638-
break;
663+
.load(Ordering::Relaxed);
664+
665+
if ntuples >= parallel::INITIAL_START_NODES_COUNT || init_done {
666+
break;
667+
}
668+
669+
// Wait on condition variable
670+
pg_sys::ConditionVariableSleep(
671+
&raw mut (*parallel_shared).build_state.initialization_cv,
672+
pg_sys::PG_WAIT_EXTENSION,
673+
);
639674
}
640-
std::thread::sleep(std::time::Duration::from_millis(10));
641675
}
642676
}
643677
debug1!("Worker should initialize: {}", should_initialize);

0 commit comments

Comments
 (0)