golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.89k stars 17.52k forks source link

runtime: throttle goroutines on async chans #8900

Open dvyukov opened 9 years ago

dvyukov commented 9 years ago
There is a common trick for reduction of contention on sync primitives. Unfortunately it
does not have a common name, but see mutexWaiterShift handling in sync/mutex.go for an
example. We can use it for async channels to reduce contention as well. Namely:

- add a waiterAwake flag to Hchan
- when a goroutine sends to async chan and there is a parked receiver, if
waiterAwake=false unpark it and set waiterAwake, otherwise do nothing
- if the woken receiver discovers empty queue, it resets waiterAwake before parking again
- if the woken receiver successfully dequeues from the queue, it does:
    if queue empty || no parked receivers {
      waiterAwake = false
    } else {
      unpark one parked receiver
      // responsibility to manage waiterAwake and subsequent parked receivers
      // transfers to that next recevier
    }

This algorithm ensures that there is at most 1 excessive receiver loafs about producing
unnecessary contention. When this receivers goes away, it wakes up another receiver. And
so on.
i3d commented 9 years ago

Under the 11506's scenario, the sender goroutine will also participate in receiving the value (or an-already-running goroutine), so who gets to run once the parked receiver gets unparked?

Let's say in your proposed workflow,

goroutine 1 sent. goroutine 2 unparked.

Now I think 1 and 2 are both possible to get dequeue the value. At this moment, how schedule picks which to run?