* David Bruant:
> Most of my concerns are appearant in the following piece of Go code
> (32'41'' in the video):
>
> c:= make(chan Result)
> go func() { c <- Web(query) } ()
> go func() { c <- Image(query) } ()
> go func() { c <- Video(query) } ()
>
> timeout := time.After(80*time.Milliseconds)
> for i:=0; i<3; i++ {
> select{
> case result := <-c
> results = append(results, result)
> case <- timeout
> fmt.Println("timed out");
> return
> }
> }
> return
This approach is fundamentally broken. If the timeout ever kicks in,
goroutines will pile up without bounds. In the current Go
implementation, the timeout has to be moved inside the goroutines.
(Theoretically, Go could support cancellation of goroutines, but this
is something really thorny, carries a distributed overhead and does
not seem to be particularly attractive.)
> My analysis goes as follow:
> Due to synchronous wait, the 3 server queries have to be done in 3
> goroutines, otherwise, they would block the "main" goroutine or one
> another. Each goroutine costs something (both for memory creation and
> certainly scheduling too).
Goroutine allocation is very cheap (or it can be made so at least).
Actually, part of the allocation cost is distributed throughout the
program: segmented stacks and the increased size of the overall root
set.
The scheduling overhead is low if there is just one actual thread
available for executing goroutines. The select will switch to one of
the newly created goroutines and execute that until it blocks on the
connect. There is no preemption, so no cycles are wasted on that. It
should be possible to avoid context switches in the same way as the
leader/follower pattern does. (I have not checked if the current
implementation does that.)
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev