4 ms·
It's common for Go programs to have millions of stacks. A million simultaneous goroutines in a Go program is pretty common. Not so much for other languages. No
by 4ad 10y ago
It's common for Go programs to have millions of stacks. A million simultaneous goroutines in a Go program is pretty common. Not so much for other languages.
Not to mention that in Go you create and destroy stacks much more often (probably orders of magnitude compared to typical Java program).
- pron 10y agoGo stacks, however, are heap objects... The thing about stack memory is that it's constant size and easy to manage. Go stacks, however, are just heap data structures (I think they used to be linked-list of arrays, and now they're "growable" arrays, like ArrayList, but I'm not sure). It's true that Go uses a different GC algorithm for managing the stacks, but it's still not stack memory. Quasar fibers on the JVM use the same approach. You can have millions of fibers, each with their own stack, but the stack themselves are heap objects.
- 4ad 10y agoThe fact that stack segments are allocated from the heap, has absolutely no consequence whatsoever. (And in fact, they are allocated from system memory, not from GCd memory.)
- pron 10y agoThat's the main thing of consequence, because those stacks are managed like heap memory. For example, you could implement each and every object as a lightweight thread with a stack -- in fact, that's not too far from how Erlang does it -- but that doesn't change the behavior of that memory. What matters isn't what it's called or what programming abstraction is exposed to the programmer, but how it behaves, which in turn dictates how it's managed. If your program consists of millions of lightweight threads -- as it's done in Erlang, Java with Quasar, or Go -- the algorithms required to manage that "stack" memory are very similar to the algorithms for managing plain heap memory, and not at all like how (heavyweight thread) stacks are managed. So the answer to "how is memory be managed if more things are on stack" is "pretty much the same" if those stacks really behave like heap objects, and are themselves managed as such.
- 4ad 10y ago> the algorithms required to manage that "stack" memory are very similar to the algorithms for managing plain heap memory, and not at all like how (heavyweight thread) stacks are managed. No, this makes no sense. It's managed absolutely identical to how any plain stacks in C are managed. Stacks are created and destroyed when scheduling units (threads or goroutines) are created and destroyed. Whether that memory is allocated by some user level library or the kernel (albeit with POSIX threads, you can, and in fact it's common for thread memory to be allocated by the calling process beforehand) has absolutely no relevance whatsoever. All that matters is that the lifetime of the stack is 1:1 mapped to the lifetime of the schedulable entity. Of course in Go goroutine stacks are dynamic, which is an optimization that makes Go programs use less memory, but that has no semantic effect.
- pron 10y agoThe thing that makes "plain" stacks easy to manage is that they're of constant size and long lifetime. If the the stack (and its schedulable entity) may be very short lived, and the stack itself may resize, then the stack requires the same (or very similar) dynamic memory management as a heap object. It is the precisely the semantics that make no difference here, but the actual behavior and lifetime of data in memory. It doesn't matter that the lifetime of the memory is that of the thread, if the lifetime of the thread is not at all like that of a heavyweight thread. From the perspective of the programmer it's a stack; from the perspective of the runtime -- it's a heap object (or close enough; there are some assumption you can make -- which Go makes -- that makes managing that memory a little easier, but those assumptions are, as usual, tradeoffs).
- 4ad 10y ago"Managing" stacks does not matter here. That's trivial. What matters is the lifetime of the data that lives on the stack. You correctly pointed out that in Java, the data on the stack represents a small percentage of all data, so escape analysis has a limited amount of effect on decreasing memory pressure. However, in Go, this percentage is much higher because there are orders of magnitude more stacks.