There is an interesting forum post explaining how you can get Gentoo to emerge essential packages on VPSlink‘s basic VPS with only 64Mb of memory! I originally thought it would be impossible, but by mangling GCC’s garbage collection parameters it indeed can be done.

The parameters ggc-min-expand, ggc-min-heapsize are used to determine when gcc should clean up and dealloc it’s unused memory and their defaults are percentages of the total system memory (4gigs) so it’s no wonder gcc is having problems.

Setting both to 0, causes compilation to be way too slow, however setting ggc-min-heapsize to 8MB and ggc-min-expand to 0 works pretty well on a VPSLINK1 and I haven’t had problems emerging anything with -O2 since.

One issue with OpenVZ and Virtuozzo VPS running on UBC parameters is, that each VPS can see how much RAM the host node has. On my VPS there it has only 256Mb guaranteed, but typing in free shows the node has 4Gb available, which causes applications that allocate heap space according to the total memory available to ill-behave (Java, for example). Apparently GCC is also the case.

From the GCC info file:

'ggc-min-expand'

GCC uses a garbage collector to manage its own memory allocation. This parameter specifies the minimum percentage by which the garbage collector’s heap should be allowed to expand between collections. Tuning this may improve compilation speed; it has no effect on code generation.

The default is 30% + 70% * (RAM/1GB) with an upper bound of 100% when RAM >= 1GB. If 'getrlimit' is available, the notion of “RAM” is the smallest of actual RAM, RLIMIT_RSS, RLIMIT_DATA and RLIMIT_AS. If GCC is not able to calculate RAM on a particular platform, the lower bound of 30% is used. Setting this parameter and ‘ggc-min-heapsize’ to zero causes a full collection to occur at every opportunity. This is extremely slow, but can be useful for debugging.

'ggc-min-heapsize'

Minimum size of the garbage collector’s heap before it begins bothering to collect garbage. The first collection occurs after the heap expands by 'ggc-min-expand'% beyond 'ggc-min-heapsize'. Again, tuning this may improve compilation speed, and has no effect on code generation.

The default is RAM/8, with a lower bound of 4096 (four megabytes) and an upper bound of 131072 (128 megabytes). If 'getrlimit' is available, the notion of “RAM” is the smallest of actual RAM, RLIMIT_RSS, RLIMIT_DATA and RLIMIT_AS. If GCC is not able to calculate RAM on a particular platform, the lower bound is used. Setting this parameter very large effectively disables garbage collection. Setting this parameter and ‘ggc-min-expand’ to zero causes a full collection to occur at every opportunity.

As GCC checks ulimit (RLIMIT_AS in specific), in some sense you can use:

$ ulimit -v 65536
$ emerge world

To force the maximum virtual memory to be 64Mb. In the case of VPS with smaller guaranteed memory, you’ll need to set this value even smaller so the memory usage of the entire tool-chain does not grow more than you have been allocated. However,

  1. You need to remember setting it before compiling/emerging anything.
  2. This limit applies to all child processes. Setting it too low might have other undesirable results.

Using GCC’s garbage collection parameters on the other hand, is a nice way to alter just how GCC uses memory. To force GCC to use no more than 8Mb of heap, and never increase after every collection, add the following line to /etc/make.conf:

CFLAGS="$CFLAGS --param ggc-min-expand=0 --param ggc-min-heapsize=8192"

Now, there should have no problem getting ebuilds compiled on VPS with low memory!