Question

The setup

I wrote this little program to see how threads of execution work. Here's a simplified version, you can find the full one on github

func f(from string) { // Bench
    // Loop for i < 40 -> fib(i)
}

func fib(n int64) int { // Something non-linear
    // Fibonacci implementation
}

func main() {

    go f("|||") // <- Should alternate
    go f("---") // <-

    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

As for output, the very first two lines

||| fib( 0 ): 0
--- fib( 0 ): 0

Then it's all --- up to

--- fib( 28 ): 317811

At which point ||| takes over and goes solo up to

||| fib( 29 ): 514229

And towards the end, they start executing "side-by-side", the complete test dump is here

--- fib( 36 ): 14930352
||| fib( 36 ): 14930352
--- fib( 37 ): 24157817
||| fib( 37 ): 24157817
--- fib( 38 ): 39088169
||| fib( 38 ): 39088169
--- fib( 39 ): 63245986
||| fib( 39 ): 63245986

The question

My initial assumption was - with go f() I should get a relatively random side-by-side execution, but instead it alternates in chunks of varying size that converge way after 29 calls to 'f()' to first-second. Why is that so? What could be a better test?

Was it helpful?

Solution

There are a number of things at play here.

The Go runtime is free to schedule your goroutines to run in whatever order and for whatever duration it pleases. So the assumption that you should get "side-by-side" execution isn't quite valid. Also, most likely you have not set GOMAXPROCS, which means the runtime by default uses a single core of your cpu. If you set GOMAXPROCS > 1, the runtime has the option of scheduling your goroutines on multiple kernel threads, which in turn could be scheduled by the kernel to run on multiple cores of your CPU. This may give you kind of output your are expecting.

OTHER TIPS

Further to Seth Hoenig's helpful answer, there is an important difference between concurrency and parallelism. Goroutines give you concurrency, which means you're describing activity that is notionally happaning at the same time, but only in an abstract sense. Parallelism is when things truly happen at the same time. Your assumption is that you will immediately see parallelism in action.

People who are used to working with OS threads naturally think of parallelism - faster speed is often the hoped-for objective. Goroutines are not OS threads, but instead they allow you to design concurrent systems that may or may not actually execute with parallelism. The objective is more about clarity of design than improved performance ... but you can achieve both with just a little skill.

Rob Pike gave an excellent lecture on this, and hope my summary here does him justice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top