4 ms·
> There are, or may be, arguments for why stacks needed to be small on ancient machines. The history is fascinating, but it is not relevant to today’s systems,
by Someone 3y ago
> There are, or may be, arguments for why stacks needed to be small on ancient machines. The history is fascinating, but it is not relevant to today’s systems, other than tiny embedded ones.
An argument against that is that processes on modern machines often use a single heap but many stacks (one for each thread), and that OSes typically have better facilities for growing the heap than for growing a stack.
Also, runtimes typically have better facilities to handle ‘out of heap memory’ than ‘out of stack memory’ conditions.
A workaround for that is to give each stack lots of room up-front, but that can be seen as wasteful, even if that’s only of virtual memory.
Growable stacks have their own problems (mostly, AFAIK, because of historical baggage), and requiring programmers to specify stack size isn’t ideal, either.
- quotemstr 3y agoHaving separate special parts of the address space for "heap" and "stack" is a weird anachronism anyway. We use mmap for stacks for anything but the main thread, and many heap implementations (e.g. jemalloc, OpenBSD malloc) just use mmap for the heap too. If I had my way, we'd use mmap for literally all memory allocation in a process and get rid of sbrk() and the stack segment entirely. There's nothing intrinsic about these legacy affordances.
- ec109685 3y agoFor the cost upfront of large stack sizes, are you referring to the fact that there isn’t generally a way to release back the stack’s memory if it is ever used by a thread? Otherwise, large stack sizes seems like one of those scary things that doesn’t practically hurt you,
- Someone 3y agoLet’s say you decide to give each thread a 1 terabyte stack, on the off chance it will run a recursive algorithm where (stack frame size × iteration depth) approximates that. (Ignoring memory usage for administration, that is doable on 64-bit systems. 1 terabyte is 2⁴⁰ bytes, so you could have 2²⁴ ≈ 16 million such stacks in a 64-bit virtual address space) Setting up the MMU to know about that will take time and memory, though. It also likely (details vary between systems) will introduce another layer of indirection in the tables used to translate virtual to physical addresses (https://en.wikipedia.org/wiki/Page_table https://en.wikipedia.org/wiki/Page_table) and thus slow them down. Workaround would be to use huge page sizes, but that at is wasteful because that not only means large page sizes in virtual memory, which is plentiful, but also in physical memory, which is much scarcer (even if the hardware would support 64 address lines and had 2⁶⁴ bytes of RAM, that still would be shared between processes)
- addaon 3y ago> Setting up the MMU to know about that will take time and memory, though. Except you don't need to set it up until the page faults happen. You allocate the top-of-stack page in the MMU, probably physically map it (since it will be used when the task first executes), make a note in your memory mapping structures that all the rest is unmapped but mappable for this purpose, and when the stack-overflow page fault occurs, go in and add the page to the mapping. If you're okay with this level of overcommitment of memory (and I'm not!), the page table management side of it is in the noise for performance and resource use.