heap limits: mmap(2) vs. break(2) on i386

Maxim Sobolev sobomax at sippysoft.com
Fri Nov 27 21:32:58 UTC 2009


Hi,

I am trying to figure out why java fails to start with 1024MB of heap on 
i386 with 4GB of RAM and 4GB of swap. Both MAXDSIZ and DFLDSIZ are set 
to 2GB. Here is my limits:

Resource limits (current):
   cputime          infinity secs
   filesize         infinity kB
   datasize          2097152 kB
   stacksize           65536 kB
   coredumpsize     infinity kB
   memoryuse        infinity kB
   memorylocked     infinity kB
   maxprocesses         5547
   openfiles           20000
   sbsize           infinity bytes
   vmemoryuse       infinity kB

Running ktrace I see:

   9154 java     CALL 
mmap(0,0x44000000,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_NORESERVE|MAP_ANON,0xffffffff,0,0)
   9154 java     RET   mmap -1 errno 12 Cannot allocate memory
   9154 java     CALL  write(0x1,0xbf9fe378,0x2b)
   9154 java     GIO   fd 1 wrote 43 bytes
        "Error occurred during initialization of VM

I made a small program that uses malloc(3) to allocate the same amount 
of memory, and that works nicely, ktrace reveals why:

  10108 a.out    CALL 
mmap(0,0x44000000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,0xffffffff,0,0)
  10108 a.out    RET   mmap -1 errno 12 Cannot allocate memory
  10108 a.out    CALL  break(0x4c100000)
  10108 a.out    RET   break 0

So the question is: why does mmap() fails while essentially the same 
sbrk() request succeeds? This is really bad since, while native FreeBSD 
programs can work around this by using malloc(3), Linux programs and 
software that knows nothing about intricate details of the FreeBSD VM 
(i.e. Java) will fail miserably.

I tried increasing vm.max_proc_mmap to 2147483647 from default 49344, 
but it did not do any good. mmap() still fails with the request of this 
size.

I have seen several threads on the issue over the years, but still no 
resolution. It seems that only plausible solution is to limit heap size 
in java, which may not work for all cases.

Funny thing is that the first sentence of the sbrk(2) manual page says:

      The brk() and sbrk() functions are legacy interfaces from before
      the advent of modern virtual memory management.

Yet, "legacy interfaces" seems to do much better job than "modern 
virtual memory management interfaces"!

-Maxim


More information about the freebsd-current mailing list