Hi Dave, thanks for the reply! It makes sense that the send c <- 0 is not guaranteed to transfer control to the receiving goroutine. But is it not guaranteed that runtime.Gosched() will at least check if another goroutine is runnable? I thought that was roughly the point of runtime.Gosched().
I see what you're saying in that when the second goroutine calls Gosched, the sleep period may not be finished. But this will only waste another 100 microseconds by design (not 100 milliseconds), so it seems like control flow should return to the main goroutine approximately when the sleep call finishes. I created a simpler example, that doesn't use channels and avoids the work length ambiguity, posted below. Now the secondary goroutine just does an infinite loop of runtime.Gosched(). It should be instantaneous to run (and is on my Mac), but it takes almost exactly 5 seconds on Ubuntu, suggesting that there is some fixed 5 millisecond delay on Gosched(). And adding a print above spin's Gosched makes it instantaneous. Thanks for your patience! I'm working on an application where the ~5ms Gosched delay is meaningful and I am very curious to figure out what's going on here. package main import ( "log" "runtime" "time" ) func spin() { for { runtime.Gosched() } } func main() { runtime.GOMAXPROCS(1) go spin() t0 := time.Now() for i := 0; i < 1000; i++ { time.Sleep(10 * time.Microsecond) runtime.Gosched() } log.Printf("Finished in %v.", time.Since(t0)) } On Tuesday, April 3, 2018 at 12:56:49 AM UTC-4, brianbl...@gmail.com wrote: > > I've run into some mysterious behavior, where Gosched() works as expected > in Mac OS X, but only works as expected in Ubuntu if I put a logging > statement before it. > > I originally posted this on Stack Overflow but was directed here. Post: > https://stackoverflow.com/questions/49617451/golang-scheduler-mystery-linux-vs-mac-os-x > > Any help would be greatly appreciated! Very curious what's going on here, > as this behavior came up while I was trying to write a websocket broadcast > server. Here's a minimal setup that reproduces the behavior: > > The main goroutine sleeps for 1000 periods of 1ms, and after each sleep > pushes a dummy message onto another goroutine via a channel. The second > goroutine listens for new messages, and every time it gets one it does 10ms > of work. So without any runtime.Gosched() calls, the program will take 10 > seconds to run. > > When I add periodic runtime.Gosched() calls in the second goroutine, as > expected the program runtime shrinks down to 1 second on my Mac. However, > when I try running the same program on Ubuntu, it still takes 10 seconds. I > made sure to set runtime.GOMAXPROCS(1) in both cases. > > Here's where it gets really strange: if I just add a logging statement > before the the runtime.Gosched() calls, then suddenly the program runs in > the expected 1 second on Ubuntu as well. > > > package main > import ( > "time" > "log" > "runtime") > > func doWork(c chan int) { > for { > <-c > > // This outer loop will take ~10ms. > for j := 0; j < 100 ; j++ { > // The following block of CPU work takes ~100 microseconds > for i := 0; i < 300000; i++ { > _ = i * 17 > } > // Somehow this print statement saves the day in Ubuntu > log.Printf("donkey") > runtime.Gosched() > } > }} > > func main() { > runtime.GOMAXPROCS(1) > c := make(chan int, 1000) > go doWork(c) > > start := time.Now().UnixNano() > for i := 0; i < 1000; i++ { > time.Sleep(1 * time.Millisecond) > > // Queue up 10ms of work in the other goroutine, which will backlog > // this goroutine without runtime.Gosched() calls. > c <- 0 > } > > // Whole program should take about 1 second to run if the Gosched() calls > // work, otherwise 10 seconds. > log.Printf("Finished in %f seconds.", float64(time.Now().UnixNano() - > start) / 1e9)} > > > -- 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.