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.

Reply via email to