2

this is very simple app :

package main
import "fmt"
func main() {

    for i:= 0; i < 100000; i++ {
        go func (){
            fmt.Println("hello message.")
        }()
    }

    fmt.Scanln()
    fmt.Println("done")
}

after run application on windows, and look at the windows task manager I saw this state:

go app state

someone can say why?

Rahmat Anjirabi
  • 868
  • 13
  • 16
  • Why do you think 884mb is high memory usage? I'd say that's pretty impressive for up to 100k goroutines. – Jonathan Hall Mar 14 '19 at 15:46
  • 1
    Because I simulated this program with .NET Core using Tasks and it only 17 MB of memory consume! – Rahmat Anjirabi Mar 14 '19 at 15:49
  • How do you "simulate" goroutines in .NET? – Jonathan Hall Mar 14 '19 at 15:50
  • 2
    @RahmatAnjirabi You can only compare memory usage if you also make sure your .NET solution also doesn't end any threads before you do launch all 100,000. – icza Mar 14 '19 at 15:50
  • Check out `The Scheduler Saga` from GopherCon. It explains the Go Scheduler in depth: https://about.sourcegraph.com/go/gophercon-2018-the-scheduler-saga – Jony T Mar 14 '19 at 23:39

1 Answers1

11

Launched goroutines run concurrently, independent of each other. It's the responsibility and duty of the goroutine scheduler to handle them.

A goroutine is a lightweight thread: it costs a lot less than an OS thread, but still costs something. Initial stack for a new goroutine is a couple of KBs (around 8KB), and grows / shrinks as needed. See Goroutines 8kb and windows OS thread 1 mb.

Given that you launch 100,000 goroutines without any synchronization, it may very well be that you will have 100,000 goroutines running before any of them finishes. Estimated memory requirement for that would be:

100,000 * 8KB = 800 MB

So your app using 884MB is pretty much in line with the estimation.

icza
  • 389,944
  • 63
  • 907
  • 827
  • So why when I delete the fmt.Println line will not take up more memory? – Rahmat Anjirabi Mar 14 '19 at 15:54
  • 1
    @RahmatAnjirabi If you remove the `fmt.Pritnln()` call from the goroutines, effectively the function body becomes empty, and those goroutines will finish a lot quicker, before you could check memory usage. The compiler might even optimize those goroutine lanunches away completely. – icza Mar 14 '19 at 15:59
  • 1
    @RahmatAnjirabi Used memory is not released back to the OS immediately. See [Cannot free memory once occupied by bytes.Buffer](https://stackoverflow.com/questions/37382600/cannot-free-memory-once-occupied-by-bytes-buffer/37383604#37383604) – icza Mar 14 '19 at 16:07