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

Re: More than 2, but less than 3 GiB per process memory?


Am Montag, 26. September 2005 20:29 schrieb Hendrik Boom:
> On Mon, Sep 26, 2005 at 11:34:15AM -0600, Bob Proulx wrote:
> > Hendrik Boom wrote:
> > > > Malte Cornils wrote:
> > > > > Does anyone have a clue why 2 GiB is the limit?
> >
> > It is not for me.  I can malloc() up to 2.9G.
> [...]
> I've heard that the kernel allocates memory "optimistically".
> That is, when it allocates it it only allocates address space.
> It commits real storage (whether RAM or swap space) to the allocated
> storage only when the storage is actually used.
> Could it be that just mallocing the storage is not enough for it to count
> as being "used?"  Would you need actually to write something in each page?

Indeed, I get up to 3058 M; that on a system with 8 GiB swap and on a system 
with 512 MB RAM and 1 GiB swap. At least on the latter, this has to be 
overcommitting since that much virtual memory is definitely not available.

From the malloc(3) man page:
> By  default,  Linux  follows  an optimistic memory allocation strategy.
> This means that when malloc() returns non-NULL there  is  no  guarantee
> that the memory really is available. This is a really bad bug.  In case
> it turns out that the system is out of memory, one  or  more  processes
> will  be  killed by the infamous OOM killer.  In case Linux is employed
> under circumstances where it would be less desirable to  suddenly  lose
> some randomly picked processes, and moreover the kernel version is suf-
> ficiently recent, one can switch off this overcommitting behavior using
> a command like
>               # echo 2 > /proc/sys/vm/overcommit_memory
> See  also  the  kernel  Documentation  directory,  files vm/overcommit-
> accounting and sysctl/vm.txt.

There is a /proc/sys/vm/overcommit_memory file, but no matter whether I put 
"2", "1" or "0" in there, the behaviour of your test program does not change 

My 2 GiB limit could be caused by using the brk() system call in the malloc 
implementation: The brk() system call uses a signed 32bit integer for the 
size, and this obviously cannot go above 2 Gig. Which might explain why my 
test program fails when allocating that much memory at once.

However, glibc's malloc documentation says that it uses the brk system call 
for smaller amounts of memory only and mmap for larger amounts. Hmm. Lots of 
questions, few answers :-)

From glibc-2.3.2's source code (malloc/malloc.c, line 129ff):
>   Maximum allocated size:  4-byte size_t: 2^32 minus about two pages
>                            8-byte size_t: 2^64 minus about two pages
>        It is assumed that (possibly signed) size_t values suffice to
>        represent chunk sizes. `Possibly signed' is due to the fact
>        that `size_t' may be defined on a system as either a signed or
>        an unsigned type. The ISO C standard says that it must be
>        unsigned, but a few systems are known not to adhere to this.
>        Additionally, even when size_t is unsigned, sbrk (which is by
>        default used to obtain memory from system) accepts signed
>        arguments, and may not be able to handle size_t-wide arguments
>        with negative sign bit.  Generally, values that would
>        appear as negative after accounting for overhead and alignment
>        are supported only via mmap(), which does not have this
>        limitation.

There is also the question whether the limits (set with the ulimit command) 
have an influence here, from setrmlimit man page:
> The maximum size of the process's virtual memory (address space)
> in  bytes.   This  limit  affects  calls  to brk(2), mmap(2) and
> mremap(2), which fail with the error ENOMEM upon exceeding  this
> limit.  Also automatic stack expansion will fail (and generate a
> SIGSEGV that kills the process if no alternate  stack  has  been
> made  available via sigaltstack(2)).  Since the value is a long,
> on machines with a 32-bit long either this limit is  at  most  2
> GiB, or this resource is unlimited.

However, ulimit -a says the limits important for memory allocation are set to 
unlimited on my systems.


Reply to: