On Thursday, January 26, 2017 at 11:15:19 PM UTC+8, Jesper Louis Andersen 
wrote:
>
> Roughly, select proceeds in two passes[0]:
>
> 1. Figure out what select-cases have events that can fire.
> 2. Pick fairly among the eligible events. Fairly means pseudo-random.
>
> What likely happens in your case is that your consumer is able to empty 
> out one of the channels which then means the other channel is then selected 
> only. This creates an erratic pattern in which part of your measurement is 
> determined by the internal schedule of goroutines and physical machine 
> characteristics.
>
> To verify this, produce 300000 messages into each channel before starting, 
> so it is only the consume loop you are measuring. 
>

Yes, it looks the cause is by starvation.

produce messages before starting, increase the channel buffer from 10 to 
1000, and sleep 1000ns in each select-loop, will all get:

pass one: 150072/149928=1.00 
pass two: 99986/200014=0.50 
pass three: 200410/99590=2.01
 
btw, increase the channel buffer from 10 to 100 still causes starvation, 
and sleep 500ns in each select-loop also still causes starvation.
So, what causes the starvation is still a mystery.



> [0] of course, the whole truth is here: 
> https://golang.org/ref/spec#Select_statements
>
> On Thu, Jan 26, 2017 at 1:06 PM T L <tapi...@gmail.com <javascript:>> 
> wrote:
>
>>
>> package main
>>
>> import "fmt"
>>
>> func main() {
>>     c0, c1 := make(chan int, 10), make(chan int, 10)
>>     
>>     go func() {
>>         for {
>>             c0 <- 0
>>         }
>>     }()
>>     
>>     go func() {
>>         for {
>>             c1 <- 1
>>         }
>>     }()
>>     
>>     var n0, n1 int
>>     
>>     f0 := func() {
>>         n0++
>>     }
>>     
>>     f1 := func() {
>>         n1++
>>     }
>>     
>>     // pass one
>>     
>>     n0, n1 = 0, 0
>>     for range [300000]struct{}{} {
>>         select {
>>         case <- c0: f0()
>>         case <- c1: f1()
>>         }
>>     }
>>     
>>     fmt.Printf("pass one: %d/%d=%.2f \n", n0, n1, float64(n0) / 
>> float64(n1))
>>     
>>     // pass two
>>     
>>     n0, n1 = 0, 0
>>     for range [300000]struct{}{} {
>>         select {
>>         case <- c0: f0()
>>         case <- c1: f1()
>>         case <- c1: f1()
>>         }
>>     }
>>     
>>     fmt.Printf("pass two: %d/%d=%.2f \n", n0, n1, float64(n0) / 
>> float64(n1))
>>     
>>     // pass three
>>     
>>     n0, n1 = 0, 0
>>     for range [300000]struct{}{} {
>>         select {
>>         case <- c0: f0()
>>         case <- c0: f0()
>>         case <- c1: f1()
>>         }
>>     }
>>     
>>     fmt.Printf("pass three: %d/%d=%.2f \n", n0, n1, float64(n0) / 
>> float64(n1))
>> }
>>
>> The output:
>>
>> pass one: 154970/145030=1.07 
>> pass two: 177853/122147=1.46 
>> pass three: 127768/172232=0.74
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to