GCC compilation performance under RAM starvation

Simon Richter Simon.Richter@hogyros.de
Sat Jun 28 00:54:59 GMT 2025


Hi,

On 27.06.25 02:01, Krystian Kazmierczak (Nokia) via Gcc-help wrote:

> What I observe is that when all compilation which run on certain container cause memory pressure (memory utilization hits memory limit defined by cgroupv2 for container, swap is disabled) then cpu load for cc1 processes significantly increase (container looks like hanged) and all compilations may last indefinitely.

Compiling is pretty much the worst case scenario for a system with paged 
memory, because the program being compiled is represented as a tree-like 
data structure, so we have lots of indirection through chains of 
pointers, and each pointer target has the risk of being on a page that 
has been paged out.

So in a memory pressure scenario, when a page is not present, it will 
have to be fetched from its backing storage, and another page evicted 
instead. Then, we retrieve the information we actually want, which often 
is another pointer that we have to follow, and the process repeats.

Having no swap space does not mean that no swapping occurs: swap space 
is space for "anonymous" memory that has no other file backing. However, 
loaded programs do have their executable files as backing, and anything 
loaded using mmap() is also fair game, so it is possible to evict them 
-- so the compiler pushes out other processes.

Because things are pulled back into memory on-demand, one page for each 
access, it takes a really long time to recover after memory pressure has 
been resolved.

You can avoid that by disabling memory overcommit, this enforces that 
every allocated memory page has a physical memory location. The downside 
of that is that on process startup, physical memory needs to be reserved 
for a copy of all unshared pages of the parent process between the 
fork() that starts the process, and the execve() that replaces the 
process image, so it makes starting a new process more expensive and 
introduces a failure mode where fork() fails because the parent process 
is too large.

For traditional Unix, that is usually not a problem (just less 
efficient) because processes tend to be fairly small, but modern desktop 
environments usually deal badly with overcommit being disabled, so it's 
not a general solution. If you have a dedicated machine or VM for 
compiling, I'd definitely go that route, though.

The only proper solution can come from the kernel here: this is where 
resources are directed. GCC can only use what it is assigned.

    Simon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://gcc.gnu.org/pipermail/gcc-help/attachments/20250628/af773ca3/attachment.sig>


More information about the Gcc-help mailing list