Hacker News new | past | comments | ask | show | jobs | submit login

Go compiler performs escape analysis, which determines whether or not a particular object "escapes" the function it was created in - and if it doesn't, the compiler allocates it on the stack instead of the heap, thereby removing the need for GC.

So, as long as you write Go in malloc-less C-style (which, admittedly, is a non-insignificant restriction), your program will be able to run just fine forever.




> So, as long as you write Go in malloc-less C-style (which, admittedly, is a non-insignificant restriction), your program will be able to run just fine forever.

What happens if you write your Go functions in this malloc-less C style and they have to grow their stack? Doesn't this mean the old stack is now leaked memory?


I see no reason why would de-allocating a stack require action from the garbage collector - afterall, once a goroutine grows its stack and copies the contents of the old stack to the new stack, there aren't any reachable objects left on the old stack, so it can be deallocated without any GC intervention.

But I don't know enough about Go internals to be 100% sure.


The purpose of escape analysis is to avoid situations where other code or data structures could potentially reference stack-allocated memory. IOW, all stack-allocated data is only referenced from the local function invocation frame, presumably using stack relative addressing, but if not at least the scope of pointer updates is substantially narrowed.

Relatedly, unlike languages like Java, Go doesn't have a moving GC--once something is allocated on the heap, the address is fixed.

I'm not sure how realistic it is to code in an entirely malloc-less style in Go, though, given the limited ability to pass references to stack-allocated objects.


Yeah, I think you’re right that stack allocated data can’t be pointed to by the heap. I don’t know what you mean about “the limited ability to pass references to stack allocated objects” though—you can always pass stack allocated references, you just can’t return them (or they will escape to the heap).


A reference can escape not only up, as a return value, but also down, as a function parameter. I'm not sure how sophisticated the static analyzer and inliners are, but escape analysis can only go so far; e.g. stopping at a method call on an interface type for which it cannot discern the concrete implementation. In fact, I believe at least in early Go releases merely passing an object reference as a parameter to a simple leaf function qualified as an escape, forcing a heap allocation.

Note that the decision to force heap allocation is done at compile time, partly because of the semantics of goroutine stack reallocation as the previous poster hinted at. In principle Go could conditionally copy to heap at runtime, but that's just not Go's style of engineering--that's more in the vein of the JVM and similar environments which push more complexity into the runtime rather than compile time. Though maybe it will or has already begun to go down that road.


Yeah, good point--I wasn't thinking about interface types.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: