https://bugs.winehq.org/show_bug.cgi?id=53217
--- Comment #7 from Zeb Figura z.figura12@gmail.com --- (In reply to Zeb Figura from comment #6)
I've been trying to dump /proc/self/maps to see where all the space is being taken up. By analyzing the size of mapped ranges, I notice a lot more areas with mapped sizes of 0x800000, which I believe is the default pthread stack size. These aren't Wine threads; there's only three of those around at the time of the crash. On my local machine there are 25 pthreads; on gitlab there are a whole 65.
So what are these pthreads? One thing I notice is that llvmpipe will, by default, spawn $(nproc) threads for rasterization. I have 12 CPUs on this machine; I don't know how many are on gitlab. But that's capped at 32, so that can't explain all of it. Something else in Mesa, perhaps?
The other 12 pthreads are lp_cs_tpool_worker, which for some reason doesn't name itself. That number is calculated the same way, so I suspect the gitlab ci machine has at least 32 threads.
So:
* The upper address space, of course, is all blocked out.
* llvmpipe creates 64 threads, each with the default stack size of 8 MB. That adds up to 512 MB.
* mesa's threads all call free() first thing which triggers glibc to create a thread-specific heap. I'm not actually sure about how much memory this takes up but I *think* it's 64 MB.
* 310 MB of shared libraries. (On my machine it's more). 121 MB of this is libLLVM-15, which, what the hell. The next worst offender is one *fourth* of that: libicudata at 31 MB.
* wined3d chunk buffers seem to be taking up about 256 MB, mainly because the test manages to do a lot of memory allocation without hitting any of the points where wined3d would normally free unused memory.
* About 230 more MB of anonymous memory that I don't immediately know how to account for. Possibly most of it is PE library .data, (and Unix library .bss?) that doesn't show up in /proc/self/maps.
* 493 MB of unallocated address space that Wine has reserved.
* Another 240 MB of address space that's free, but too fragmented to allocate another 64 MB wined3d chunk buffer.
And there you have it! Out of address space!
So here are some things we can do:
(1) Limit the number of threads that we are using in CI. This is relatively easy; there's a LP_NUM_THREADS for this.
(2) Mesa probably doesn't need 8 MB of stack for its threads. Get a change upstream to use less.
(3) Reduce wined3d chunk buffer size for 32-bit programs, probably.
(4) Try to submit fences more often so we don't allocate so many chunk buffers.
(5) Mark Wine tests as large address aware?
(6) Write, implement, and upstream a GL extension to allow controlling mapped buffer placement (which we need anyway, for new wow64). Use it even in old wow64 too, to forcibly allocate buffers into the low 2 GiB. Reserve the entire low 2 GiB, and stop reserving the upper 2 GiB. That'll alleviate some of the memory pressure from Unix libraries.
(7) Investigate why the hell libllvm is so enormous. I cannot believe for a second that it needs all of that data loaded. Also, why is libicudata even being *loaded*?
In practice, this is for unit tests, so we'll probably just turn down the thread count and call it a day. Or mark the tests as large address aware. One of those two things for sure.