Live data from Hacker News

Allocating on the Stack

go.dev

11–20 of 59 posts

Re: Allocating on the Stack

#11

This article is about Go, but I wonder how many C/C++ developers realize that you've always had the ability to allocate on the stack using alloca() rather than malloc(). Of course use cases are limited (variable length buffers/strings, etc) since the lifetime of anything on the stack has to match the lifetime of the stack frame (i.e the calling function), but it's super fast since it's just bumping up the stack point…

This is more of a patch/hack solution as far as I can understand. You can just as well pass a heap allocated buffer + size around and allocate by incrementing/decrementing size. Or even better use something like zig's FixedSizeAllocator. Correct me if I am wrong please

I wouldn't call it a hack, but it's not a general alternative for memory allocated on the heap since the lifetime is tied to that of the allocating function.

I think what you're referring to is an arena allocator where you allocate a big chunk of memory from the heap, then sequentially sub-allocate from that, then eventually free the entire heap chunk (arena) in one go. Arena allocators are therefore also special use case since they are for when all the sub-allocations have the same (but arbitrary) lifetime, or at least you're willing to defer deallocation of everything to the same time.

So, heap, arena and stack allocation all serve different purposes, although you can just use heap for everything if memory allocation isn't a performance issue for your program, which nowadays is typically the case.

Back in the day when memory was scarce and computers were much slower, another common technique was to keep a reuse "free list" of allocated items of a given type/size, which was faster than heap allocate and free/coalesce, and avoided the heap fragmentation of random malloc/frees.

Re: Allocating on the Stack

#14

Nice to see common and natural patterns to have their performance improved. Theoretically appending to a slice would be possible to handle with just stack growth, but that would require having large gaps between goroutine stacks and mapping them lazily upon access instead of moving goroutines to the new contiguous blocks as it's implemented right now. But given how many questionable changes it requires from runtime i…

Having big stack frames is bad for cache locality. Stack is not something magical, it's mapped to the same physical memory as heap and needs to be loaded. Pretty sure such optimization would reduce performance in most cases.

Re: Allocating on the Stack

#16

This article is about Go, but I wonder how many C/C++ developers realize that you've always had the ability to allocate on the stack using alloca() rather than malloc(). Of course use cases are limited (variable length buffers/strings, etc) since the lifetime of anything on the stack has to match the lifetime of the stack frame (i.e the calling function), but it's super fast since it's just bumping up the stack point…

alloca() is super useful, but it's also quite dangerous because you can easily overflow the stack. The obvious issue is that you can't know how much space is left on the stack, so you basically have to guess and pick an arbitrary "safe" size limit. This gets even more tricky when functions may be called recursively. The more subtle issue is that the stack memory returned by alloca() has function scope and therefore y…

> The obvious issue is that you can't know how much space is left on the stack [...]

Oh, huh. I've never actually tried it, but I always assumed it would be possible to calculate this, at least for a given OS / arch. You just need 3 quantities, right? `remaining_stack_space = $stack_address - $rsp - $system_stack_size`.

But I guess there's no API for a program to get its own stack address unless it has access to `/proc/$pid/maps` or similar?

Re: Allocating on the Stack

#18

Earlier quoted context omitted.

alloca() is super useful, but it's also quite dangerous because you can easily overflow the stack. The obvious issue is that you can't know how much space is left on the stack, so you basically have to guess and pick an arbitrary "safe" size limit. This gets even more tricky when functions may be called recursively. The more subtle issue is that the stack memory returned by alloca() has function scope and therefore y…

> The obvious issue is that you can't know how much space is left on the stack [...] Oh, huh. I've never actually tried it, but I always assumed it would be possible to calculate this, at least for a given OS / arch. You just need 3 quantities, right? `remaining_stack_space = $stack_address - $rsp - $system_stack_size`. But I guess there's no API for a program to get its own stack address unless it has access to `/pr…

[deleted]

Re: Allocating on the Stack

#19

This article is about Go, but I wonder how many C/C++ developers realize that you've always had the ability to allocate on the stack using alloca() rather than malloc(). Of course use cases are limited (variable length buffers/strings, etc) since the lifetime of anything on the stack has to match the lifetime of the stack frame (i.e the calling function), but it's super fast since it's just bumping up the stack point…

alloca() is super useful, but it's also quite dangerous because you can easily overflow the stack. The obvious issue is that you can't know how much space is left on the stack, so you basically have to guess and pick an arbitrary "safe" size limit. This gets even more tricky when functions may be called recursively. The more subtle issue is that the stack memory returned by alloca() has function scope and therefore y…

If you have well defined boundaries, you can move the stack to an arbitrarily large chunk of memory before the recursive call and restore it to the system stack upon completion.
Post reply on HN