Re: GCC compilation performance under RAM starvation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

On Sat, Jun 28, 2025 at 09:54:59AM +0900, Simon Richter wrote:
> 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.

Or more generally: a compiler has a lot of "active memory".  Not "paged
memory", data that is just from files on disk (like stuff read it from
source files).

> 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.

Yup, swap space is "just ram" in many ways.  But having the distinction
swap <-> ram allows the kernel to do better (heuristic!) tradeoffs
often.  And, like I try to point out all over this thread, all of the
kernel tuning for this depends on it having a reasonable amount of swap
space.  If there is *no* swap space, there are more hard edges.

> 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.

How do you disable memory overcommit?  "Just" don't run problems that
are bigger than you have memmory for?

> 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.

The only proper solution is to just have enough memory for everything
you run.  Problem solved :-)

(But yes, there is nothing GCC can do to solve this, or ameliorate this
even).


Segher



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux