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.