Cells in hardware RAM are only used to hold actual data (and some are wasted to alignment). I may claim to have reserved 512gb of ram for stacks, but unless I’m actually using the space (in which case there’s no issue) then physical ram is not being consumed.
As in write to each requested memory location to guarantee physical allocation? No, that would be really slow. It’s not like heap memory where you probably want to memset it first, with stack you have a stack pointer so you know whats been written by you and what’s random garbage.
Java just requests the memory and linux just smirks and always says “yes sure, whatever you need” - it can do that even while the OOM killer is trying to decide which process looks like it has completed the most useful work so far :-)
TLB entries dont really come into it (the size isnt an issue from our stack usage but even if it were, we could use larger pages).
TLB flushes could be an issue with that many threads floating around but that’s a different story and not really a memory usage so much as a performance and latency issue.
>> No you use the advisory bits when you map the memory.
Is that really what’s happening when we create another thread? That doesn’t fit with my understanding here. When i create a new thread, i expect its stack to be allocated before the break so mlock wouldn’t come into it. Even on a jvm with Xms smaller than Xmx (i.e. so the jvm could have to request to move the break and grow the heap to accomodate my new threads private jvm stack), I’m expecting you would have to explicitly request this behaviour somehow (because it’s quite unneighbourly and probably counter productive for most apps). I don’t know how you would do that, maybe there’s a call available under the unsafe packages?
I’m conscious I’m saying the jvm - i mean hotspot.
>> so it isn't unable to commit more memory while trying to handle an exception
Again this doesn’t fit with my understanding - you can receive a further OOME while handling an exception and that’s just bad luck.
>> Linux doesn't ignore even LOCKED does it? And it certainly can't ignore actual writes to pages
Sure but I’m going on the expectation that doesn’t apply here
> When i create a new thread, i expect its stack to be allocated before the break
Why? Stacks are just memory like any other. You can put them wherever you want.
> so the jvm could have to request to move the break and grow the heap
The JVM allocates heap space using mmap, not by moving the break.
> you can receive a further OOME while handling an exception and that’s just bad luck
If you're being reasonable you don't - the JVM maintains emergency heap storage (pre-committed!) space so it can keep allocating even when out-of-memory.
The JVM commits a suitable number of pages for the stack. Stack growth can mean new page commits to expand the stack.
After a thread is idle for some defined period of time, the JVM may release back some of the pages used to expand the stack.
If you actually want to take advantage of this behavior, you have to pay attention to which threads are being scheduled to do work -- because if you randomly choose a thread from a pool they're all doing work, and the JVM thinks none of them are idle. You need to focus on particular threads.
And at the end of the day if you're allocating a certain number of threads to do "task-like" work, you need to be prepared to deal with the expansion of thread stack/overhead.
So overall...I like this new proposal. Building cooperative scheduling deep into the libraries makes sense, as does breaking the 1:1 ratio to OS threads.
In other cooperative scheduling libraries I've seen, that 1:1 ratio is retained, and this inevitably leads to a schism in programming: Those who believe that the "lightweight" thread truly is, and those who have learned otherwise.