> But is it not guaranteed that runtime.Gosched() will at least check if another goroutine is runnable?
It checks, but I believe that at the time that it checks there are often no other runnable goroutines. The execution tracer will give you the answer to this. On Wednesday, 4 April 2018 04:12:40 UTC+10, brianbl...@gmail.com wrote: > > 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.