malloc and 'Active' memory

Matthijs van der Klip matthijs at spill.nl
Mon Aug 8 12:40:49 UTC 2005


On Mon, 1 Aug 2005, Deron Meranda wrote:
> The malloc(3) function is entirely userspace code, part of glibc.  It's
> not a kernel feature.

Yes, I'm aware of that, but I didn't mention for simplicity's sake... ;-)


> The kernel usually allocates memory to processes via the sbrk(2) system
> call in whole pages.  From a user-process perspective this can not be
> fragmented since the pages are virtually mapped into a linear address
> space regardless of their actual physical address.  The malloc(3)
> function though will use mmap(2) instead of sbrk(2) when allocating
> very large chunks of memory; although it's still only getting whole
> pages at a time.
> 
> It is true though that the malloc(3) function in glibc is very advanced and
> is mostly imune to many forms of traditional memory fragmentation.
> For an overview of the algorithms it uses read this document by
> Doug Lea: http://gee.cs.oswego.edu/dl/html/malloc.html
> 
> It's not exactly the same as the Linux implmentation, but it's pretty
> close.  BTW the glibc version comes from ptmalloc2 by Wolfram Gloger,
> which is found here:  http://www.malloc.de/en/index.html

Actually it's not really the malloc behaviour I don't understand, it's the 
definition of 'Active' memory. What is it's use and why is it there? When 
doing a couple of rather heavy compiles the amount of Active memory keeps 
rising until malloc's requesting for large amounts of memory begin to 
fail. The memory is there, but it's being marked as Active which prevents 
it from being allocated all at once. Why is that?

This is the mmap call from a strace session by the way:

mmap(NULL, 7340052480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 
-1, 0) = -1 ENOMEM (Cannot allocate memory)

The default setting for overcommit_memory is set to 0 which means:

0       -       Heuristic overcommit handling. Obvious overcommits of
                address space are refused. Used for a typical system. It
                ensures a seriously wild allocation fails while allowing
                overcommit to reduce swap usage.  root is allowed to 
                allocate slighly more memory in this mode. This is the 
                default.

Now, with a setting of 1 (heuristics turned off) the malloc call obviously 
succeeds as it means:

1       -       Always overcommit. Appropriate for some scientific
                applications.

In other words I think the heuristics are causing my grief. It is just not
making sense to me that allocating 2GB with malloc a hundred times (total
of 200GB) works when overcommit_memory is set to 0, but a single malloc
for 7GB fails. Now which of the two is the obvious overcommitment
situation?

What I've done at the moment is the following:

A) I have set overcommit_memory to 2 (do not overcommit) and 
   overcommit_ratio to 100. This ensures the VM will never commit to more 
   than physical RAM plus swap (I have configured a very small swap 
   partition).

B) I configured MySQL to 4GB innodb_buffer_pool_size.

C) I have set max_connections to 256, which results in a maximum useage of 
   key_buffer_size+(read_buffer_size+sort_buffer_size)*max_connections 
   ~ 2GB of memory for the connecting threads.


Now after starting MySQL I get values as follows from /proc/meminfo:

CommitLimit:   8646184 kB
Committed_AS:  5283720 kB

Now, this leaves 8646184 kB - 5297108 kB ~ 3GB of memory to commit, 2GB 
will be used when max_connections is reached, leaving another 1GB for 
safety purposes.

This configuration is far more on the safe side than I'm used to, but I
think it makes kind of sense, don't you?

Interestingly enough starting MySQL in this situation is no problem, even 
with enormous amounts of 'Active' memory laying around.

Before starting MySQL:

MemTotal:      8124080 kB
MemFree:       1230808 kB
Active:        4098516 kB
Inactive:      2554808 kB
CommitLimit:   8646184 kB
Committed_AS:   240412 kB

After:

MemTotal:      8124080 kB
MemFree:        804764 kB
Active:        4515396 kB
Inactive:      2562880 kB
CommitLimit:   8646184 kB
Committed_AS:  5283720 kB


> Oh, from the malloc.c source code under the function free() we
> have this comment:
> 
>  * Unless disabled (using mallopt), freeing very large spaces will
>  * when possible, automatically trigger operations that give
>  * back unused memory to the system, thus reducing program footprint.
> 
> You can fine-tune the agressiveness when memory is released back
> to the system by using the mallopt(3) call with the option of
> M_TRIM_THRESHOLD.  Or you can manually force a release using
> the malloc_trim(3) function.  (only the non-fragmented memory is
> released).

To my understanding, calling malloc_trim would only be of benefit when a 
process releases large amounts of memory but _continues_ to run, so that 
glibc can return the memory to the OS immediately instead of waiting until 
process termination. Not so?


Regards,

-- 
Matthijs van der Klip
System Administrator
Spill E-Projects
The Netherlands











More information about the fedora-list mailing list