12

I would like to control the maximum memory, a process can use in Mac-OS X 10.8. I feel that setting ulimit -v should achieve the goals but doesn't seem to be the case. I tried following simple commands :

    ulimit -m 512

    java -Xms1024m -Xmx2048m SomeJavaProgram

I was assuming that 2nd command should fail as Java Process will start by keeping 1024MB of memory for itself but it passes peacefully. Inside my Sample program, I try allocating more than 1024MB using following code snippet:

System.out.println("Allocating 1 GB of Memory");
List<byte[]> list = new LinkedList<byte[]>();
list.add(new byte[1073741824]); //1024 MB
System.out.println("Done....");

Both these programs get executed without any issues. How can we control the max memory allocation for a program in Mac-OS X?

Narinder Kumar
  • 461
  • 1
  • 5
  • 9
  • Narinder Kumar, try to write something into your allocated data, at least one write per 4096 bytes, and check, will the ulimit limit new test. – osgx Feb 23 '14 at 05:11
  • Possible duplicate of [How to limit memory of a OS X program? ulimit -v neither -m are working](http://stackoverflow.com/questions/3274385/how-to-limit-memory-of-a-os-x-program-ulimit-v-neither-m-are-working) – hectorpal Oct 07 '15 at 22:03

1 Answers1

11

I'm not sure if you still need the question answered, but here is the answer in case anyone else happens to have the same question.

ulimit -m strictly limits resident memory, and not the amount of memory a process can request from the operating system.

ulimit -v will limit the amount of virtual memory a process can request from the operating system.

for example...

#include <stdio.h>
#include <stdlib.h>


int main(int argc, char* argv[]) {

    int size = 1 << 20;

    void* memory = NULL;

    memory = malloc(size);

    printf("allocated %i bytes...\n", size);

    return 0; 

}


ulimit -m 512
./memory
allocated 1048576 bytes...


ulimit -v 512
./memory
Segmentation fault


If you execute ulimit -a it should provide a summary of all the current limits for child processes.

As mentioned in comments below by @bikram990, the java process may not observe soft limits. To enforce java memory restrictions, you can pass arguments to the process (-Xmx, -Xss, etc...).

Warning!

You can also set hard limits via the ulimit -H command, which cannot be modified by sub-processes. However, those limits also cannot be raised again once lowered, without elevated permissions (root).

Jason
  • 3,777
  • 14
  • 27
  • 5
    This works great on Linux, but does not work for OSX, which was the reason I was supporting the question with a bounty. Thanks for providing the code to reproduce though. – pelson Feb 25 '14 at 14:10
  • `ulimit` behavior is generally governed by POSIX, and OSX is POSIX compliant so I'm somewhat shocked. The example specifies `ulimit -m` which won't affect limits on total virtual memory size. I would be curious what `ulimit -a` actually reports. – Jason Feb 25 '14 at 14:59
  • pelson> ulimit -v 512 pelson> ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) 512 open files (-n) 256 pipe size (512 bytes, -p) 1 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 709 virtual memory (kbytes, -v) 512 – pelson Feb 26 '14 at 12:19
  • Odd, it seems to report the correct virtual memory limit, 512k. If you try executing `for ((i=0;i<1<<20;i++)); do m+='x'; done` after `ulimit -v 512`, what happens? `unset m` will free the memory. – Jason Feb 26 '14 at 14:25
  • 1
    @Jason pelson is trying this on a java process. I think java may be modifying the hard limits for memory. see http://stackoverflow.com/questions/7997602/c-change-max-ram-limit – bikram990 Feb 26 '14 at 15:49
  • @bikram990 Java compiles and executes on the fly, so that might explain why the reported limits aren't being adhered to. – Jason Feb 26 '14 at 16:15
  • @Jason See https://www.ibm.com/developerworks/community/blogs/troubleshootingjava/entry/ulimit_and_xmx?lang=en i.e. why its not using ulimit. – bikram990 Feb 26 '14 at 16:31
  • @Jason our interpretation was correct. java is changing the limits. – bikram990 Feb 26 '14 at 16:32
  • @bikram990 So, it looks like limits should be explicitly set for java processes via arguments (`-Xmx`, `-Xss`)? – Jason Feb 26 '14 at 16:41
  • @Jason `sudo ulimit -H -v 512` or `sudo ulimit -H -m 512` will set the hard limit and java will not be able to increase it. That way the limits can be enforced. – bikram990 Feb 26 '14 at 16:46
  • @bikram990 I don't think a process needs elevated permissions to lower it's hard limit via [ulimit](http://ss64.com/osx/ulimit.html), but once the hard limit is set it can't be raised without elevated permissions. So, for java, specifying the limits to the process is probably the safest thing to do. – Jason Feb 26 '14 at 20:16
  • 1
    FWIW, I'm not working with Java (though the original question did). @Jason's C example demonstrates the problem nicely IMHO and this is more to do with OSX than the Java VM. – pelson Feb 28 '14 at 12:11
  • 1
    memory limits OS X doesn't work using ulimit neither the corresponding system call. Using launchd was suggested by I haven't tried. http://stackoverflow.com/questions/3274385/how-to-limit-memory-of-a-os-x-program-ulimit-v-neither-m-are-working – hectorpal Oct 07 '15 at 22:05
  • In macOS setrlimit(2), RLIMIT_AS is an alias for RLIMIT_RSS. So no, the macOS kernel apparently doesn't support limiting a process' virtual memory usage, regardless which approach (ulimit or launchd) you use: all of these are based on setrlimit(2) in the end. – Rörd Oct 10 '16 at 20:30