@@ -14,9 +14,6 @@ use lazy_static::lazy_static;
14
14
use crate :: utils:: abort_on_panic;
15
15
16
16
const MAX_THREADS : u64 = 10_000 ;
17
- const MIN_WAIT_US : u64 = 10 ;
18
- const MAX_WAIT_US : u64 = 10_000 ;
19
- const WAIT_SPREAD : u64 = MAX_WAIT_US - MIN_WAIT_US ;
20
17
21
18
static DYNAMIC_THREAD_COUNT : AtomicU64 = AtomicU64 :: new ( 0 ) ;
22
19
@@ -52,8 +49,7 @@ lazy_static! {
52
49
53
50
// Create up to MAX_THREADS dynamic blocking task worker threads.
54
51
// Dynamic threads will terminate themselves if they don't
55
- // receive any work after a timeout that scales down as the
56
- // total number of threads scales up.
52
+ // receive any work after one second.
57
53
fn maybe_create_another_blocking_thread ( ) {
58
54
// We use a `Relaxed` atomic operation because
59
55
// it's just a heuristic, and would not lose correctness
@@ -63,20 +59,11 @@ fn maybe_create_another_blocking_thread() {
63
59
return ;
64
60
}
65
61
66
- // We want to give up earlier when we have more threads
67
- // to exert backpressure on the system submitting work
68
- // to do.
69
- let utilization_percent = ( workers * 100 ) / MAX_THREADS ;
70
- let relative_wait_limit = ( WAIT_SPREAD * utilization_percent) / 100 ;
71
-
72
- // higher utilization -> lower wait time
73
- let wait_limit_us = MAX_WAIT_US - relative_wait_limit;
74
- assert ! ( wait_limit_us >= MIN_WAIT_US ) ;
75
- let wait_limit = Duration :: from_micros ( wait_limit_us) ;
76
-
77
62
thread:: Builder :: new ( )
78
63
. name ( "async-blocking-driver-dynamic" . to_string ( ) )
79
- . spawn ( move || {
64
+ . spawn ( || {
65
+ let wait_limit = Duration :: from_secs ( 1 ) ;
66
+
80
67
DYNAMIC_THREAD_COUNT . fetch_add ( 1 , Ordering :: Relaxed ) ;
81
68
while let Ok ( task) = POOL . receiver . recv_timeout ( wait_limit) {
82
69
abort_on_panic ( || task. run ( ) ) ;
@@ -86,43 +73,24 @@ fn maybe_create_another_blocking_thread() {
86
73
. expect ( "cannot start a dynamic thread driving blocking tasks" ) ;
87
74
}
88
75
89
- // Enqueues work, blocking on a threadpool for a certain amount of
90
- // time based on the number of worker threads currently active in
91
- // the system. If we cannot send our work to the pool after the
92
- // given timeout, we will attempt to increase the number of
93
- // worker threads active in the system, up to MAX_THREADS. The
94
- // timeout is dynamic, and when we have more threads we block
95
- // for longer before spinning up another thread for backpressure.
76
+ // Enqueues work, attempting to send to the threadpool in a
77
+ // nonblocking way and spinning up another worker thread if
78
+ // there is not a thread ready to accept the work.
96
79
fn schedule ( t : async_task:: Task < ( ) > ) {
97
- // We use a `Relaxed` atomic operation because
98
- // it's just a heuristic, and would not lose correctness
99
- // even if it's random.
100
- let workers = DYNAMIC_THREAD_COUNT . load ( Ordering :: Relaxed ) ;
101
-
102
- // We want to block for longer when we have more threads to
103
- // exert backpressure on the system submitting work to do.
104
- let utilization_percent = ( workers * 100 ) / MAX_THREADS ;
105
- let relative_wait_limit = ( WAIT_SPREAD * utilization_percent) / 100 ;
106
-
107
- // higher utilization -> higher block time
108
- let wait_limit_us = MIN_WAIT_US + relative_wait_limit;
109
- assert ! ( wait_limit_us <= MAX_WAIT_US ) ;
110
- let wait_limit = Duration :: from_micros ( wait_limit_us) ;
111
-
112
- let first_try_result = POOL . sender . send_timeout ( t, wait_limit) ;
80
+ let first_try_result = POOL . sender . try_send ( t) ;
113
81
match first_try_result {
114
82
Ok ( ( ) ) => {
115
83
// NICEEEE
116
84
}
117
- Err ( crossbeam:: channel:: SendTimeoutError :: Timeout ( t) ) => {
85
+ Err ( crossbeam:: channel:: TrySendError :: Full ( t) ) => {
118
86
// We were not able to send to the channel within our
119
87
// budget. Try to spin up another thread, and then
120
88
// block without a time limit on the submission of
121
89
// the task.
122
90
maybe_create_another_blocking_thread ( ) ;
123
91
POOL . sender . send ( t) . unwrap ( )
124
92
}
125
- Err ( crossbeam:: channel:: SendTimeoutError :: Disconnected ( _) ) => {
93
+ Err ( crossbeam:: channel:: TrySendError :: Disconnected ( _) ) => {
126
94
panic ! (
127
95
"unable to send to blocking threadpool \
128
96
due to receiver disconnection"
0 commit comments