perf(std csp): signal-one on channel put/get instead of broadcast
ober
e111d08853164c7bf45f0a88f5b3dcafc8d499e5
--- a/lib/std/csp.ss +++ b/lib/std/csp.ss @@ -186,7 +186,10 @@ ;; past a raw put-check. (def (%chan-enqueue-raw! ch val) (q-enqueue! ch val) - (condition-broadcast (channel-not-empty ch)) + ;; One enqueue can only satisfy one waiting reader; signal-one + ;; avoids the thundering-herd cost of waking every blocked worker + ;; just to have all but one go back to sleep. + (condition-signal (channel-not-empty ch)) ch) ;; Put one value into a channel with the mutex already held, running @@ -208,7 +211,7 @@ (condition-broadcast (channel-not-full ch))))] [else (q-enqueue! ch val) - (condition-broadcast (channel-not-empty ch))]))) + (condition-signal (channel-not-empty ch))]))) (def (chan-put! ch val) (with-mutex (channel-mutex ch) @@ -254,7 +257,8 @@ (cond [(not (q-empty? ch)) (let ([val (q-dequeue! ch)]) - (condition-broadcast (channel-not-full ch)) + ;; One dequeue frees exactly one slot for one writer. + (condition-signal (channel-not-full ch)) val)] [(channel-closed? ch) (eof-object)] @@ -267,7 +271,7 @@ (cond [(not (q-empty? ch)) (let ([val (q-dequeue! ch)]) - (condition-broadcast (channel-not-full ch)) + (condition-signal (channel-not-full ch)) val)] [else #f])))