@@ -4,13 +4,42 @@ use crossbeam_channel::{unbounded as channel, Receiver, Sender};
44use std:: {
55 collections:: VecDeque ,
66 sync:: {
7- atomic:: { AtomicUsize , Ordering } ,
7+ atomic:: { AtomicU8 , AtomicUsize , Ordering } ,
88 Arc ,
99 } ,
1010} ;
1111
1212pub struct Scheduler {
13- workers : Arc < [ Worker ] > ,
13+ workers : Arc < Batch < Worker > > ,
14+ }
15+
16+ struct Batch < T > {
17+ next_batch : AtomicU8 ,
18+ workers : Box < [ T ] > ,
19+ }
20+
21+ const BATCH_SIZE : usize = 8 ;
22+
23+ impl < T > Batch < T > {
24+ fn new ( workers : Box < [ T ] > ) -> Self {
25+ Self {
26+ next_batch : AtomicU8 :: new ( 0 ) ,
27+ workers,
28+ }
29+ }
30+
31+ #[ inline]
32+ fn next_batch ( & self ) -> & [ T ] {
33+ let len = self . workers . len ( ) ;
34+ if len <= BATCH_SIZE {
35+ & self . workers
36+ } else {
37+ let no = self . next_batch . fetch_add ( 1 , Ordering :: Relaxed ) as usize ;
38+ let next = ( no * BATCH_SIZE ) % len. next_multiple_of ( BATCH_SIZE ) ;
39+ let end = ( next + BATCH_SIZE ) . min ( len) ;
40+ unsafe { self . workers . get_unchecked ( next..end) }
41+ }
42+ }
1443}
1544
1645struct Worker {
@@ -63,7 +92,7 @@ impl Scheduler {
6392
6493 let init_capacity = 256 ;
6594 let mut queues = vec ! [ ] ;
66- let workers: Vec < _ > = ( 0 ..worker_count)
95+ let workers: Box < _ > = ( 0 ..worker_count)
6796 . map ( |_| {
6897 let len = Length :: default ( ) ;
6998 let ( tx, rx) = channel ( ) ;
@@ -80,7 +109,7 @@ impl Scheduler {
80109 . collect ( ) ;
81110
82111 let scheduler = Self {
83- workers : workers. into ( ) ,
112+ workers : Batch :: new ( workers) . into ( ) ,
84113 } ;
85114 ( scheduler, queues)
86115 }
@@ -89,6 +118,7 @@ impl Scheduler {
89118 fn least_loaded_worker ( & self ) -> & Worker {
90119 unsafe {
91120 self . workers
121+ . next_batch ( )
92122 . iter ( )
93123 . min_by_key ( |a| a. len . get ( ) )
94124 . unwrap_unchecked ( )
0 commit comments