@@ -9,6 +9,7 @@ use futures::StreamExt;
99use futures:: stream:: BoxStream ;
1010use parking_lot:: Mutex ;
1111use smol:: block_on;
12+ use vortex_utils:: parallelism:: get_available_parallelism;
1213
1314use crate :: runtime:: BlockingRuntime ;
1415use crate :: runtime:: Executor ;
@@ -67,8 +68,10 @@ impl CurrentThreadRuntime {
6768
6869 // We create an MPMC result channel and spawn a task to drive the stream and send results.
6970 // This allows multiple worker threads to drive the execution while all waiting for results
70- // on the channel.
71- let ( result_tx, result_rx) = kanal:: bounded_async ( 1 ) ;
71+ // on the channel. Channel buffers up to one item per core so calling threads can get a
72+ // ready item without every one of them having to become an executor.
73+ let capacity = get_available_parallelism ( ) . unwrap_or ( 1 ) . max ( 1 ) ;
74+ let ( result_tx, result_rx) = kanal:: bounded_async ( capacity) ;
7275 let driver = self . executor . spawn ( async move {
7376 futures:: pin_mut!( stream) ;
7477 while let Some ( item) = stream. next ( ) . await {
@@ -154,19 +157,28 @@ impl<T> Iterator for ThreadSafeIterator<T> {
154157 type Item = T ;
155158
156159 fn next ( & mut self ) -> Option < Self :: Item > {
160+ // If driver already has an item, take it without driving the executor
161+ match self . results . try_recv ( ) {
162+ Ok ( Some ( item) ) => return Some ( item) ,
163+ Ok ( None ) => { }
164+ Err ( _) => return self . get_task_error ( ) ,
165+ }
166+
157167 match block_on ( self . executor . run ( self . results . recv ( ) ) ) {
158168 Ok ( item) => Some ( item) ,
159- // The result channel closes when the driver task finishes. Join the task so a panic
160- // raised while driving the stream is re-raised here instead of being lost. The first
161- // consumer to observe closure joins it; any later consumer just sees the stream end.
162- Err ( _) => {
163- let task = self . driver . lock ( ) . take ( ) ;
164- if let Some ( task) = task {
165- block_on ( self . executor . run ( task) ) ;
166- }
167- None
168- }
169+ Err ( _) => self . get_task_error ( ) ,
170+ }
171+ }
172+ }
173+
174+ impl < T > ThreadSafeIterator < T > {
175+ // Join current task so panics are re-raised
176+ fn get_task_error ( & self ) -> Option < T > {
177+ let task = self . driver . lock ( ) . take ( ) ;
178+ if let Some ( task) = task {
179+ block_on ( self . executor . run ( task) ) ;
169180 }
181+ None
170182 }
171183}
172184
0 commit comments