12

I have spent 2 hours reading questions about this matter, and still there is some misunderstanding.

I have this process:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND    
root 1452 0.4 1.8 1397012 19308 ? Sl 04:23 3:48 ./transaction_server

This shows it uses 19.3MB of system resident memory (I have no swap file), and around 1.8% of the whole 1GB system memory, but the virtual size is 1.39GB?!? I have read that ulimit -m doesn't work. People use ulimit -v to set virtual memory limit for the process. Is this virtual memory is the one VSZ listed with ps? What value I should set if I want to restrict this process to use 100MB system memory at most? I have read documentation for setrlimit and this seems legit:

RLIMIT_AS
        This  is  the maximum size of a process' total available memory, 
        in bytes. If this limit is exceeded, the malloc() and mmap() 
        functions shall fail with errno set to [ENOMEM]. In addition, 
        the automatic stack growth fails with the effects outlined above.

But other versions of the documentation say this RLIMIT_AS parameter sets virtual memory size. What is the truth?

alexh
  • 109
  • 3

2 Answers2

6

Yes, VSZ is virtual memory. As to RLIMIT_AS, where did you find the paragraph quoted above? Since setrlimit(2) is a Linux system call, I do not see how it could possibly monitor malloc(3), a library function. Instead, it can only work with brk(2), sbrk(2), and mmap(2) -- this is also what its manpage (checked of Scientific Linux) suggests. However, the total amount of memory requested via these functions is virtual memory, so RLIMIT_AS indeed limits virtual memory. (This is, again, in accordance with the setrlimit(2) manpage.)

Unfortunately, you cannot limit RSS under Linux (this would be ulimit -m). You can try ulimit -d (RLIMIT_DATA), but this will include mmap(2) only since Linux 4.7, typically used for large allocations. Another possibility would be to limit virtual memory, but with such a large difference between RSS and VSZ, this might be difficult.

  • Thank you for your answer. The paragraph is from setrlimit man page IEEE/The Open Group 2003 GETRLIMIT(3P) How come ps can show me the RSS, but the kernel can't enforce limit on it? – Dragomir Ivanov Feb 22 '12 at 10:26
  • 7
    According to Alan Cox, this has historical reasons: calculating RSS used to be expensive, so enforcing the limit would put a large load on the kernel; source: http://linux.derkeiler.com/Mailing-Lists/Kernel/2006-01/msg03306.html. See also http://stackoverflow.com/questions/3043709/resident-set-size-rss-limit-has-no-effect/6365534#6365534 – Ansgar Esztermann Feb 22 '12 at 11:08
  • I see. I guess I would go with ulimit -d then. The application is written by me, and I didn't use mmap(). – Dragomir Ivanov Feb 22 '12 at 11:16
  • 2
    No, you usually don't (nor sbrk()), but malloc() might. – Ansgar Esztermann Feb 22 '12 at 11:32
  • I see. That is very unfortunate. So the solution to this question then, is either cgroups, or memory usage poll with some script language. – Dragomir Ivanov Feb 22 '12 at 15:35
  • malloc() is a library call but gets its memory from mmap or brk/sbrk. If the system call fails (e.g. due to ulimit restrictions) malloc will also report a failure. – JanKanis Dec 18 '14 at 17:02
  • 2
    Since Linux 4.7 mmap() allocated memory is included into data (RLIMIT_DATA). – Denis Nikolaenko Sep 01 '20 at 14:44
5

Many processes share some of its memory with other processes, e.g. libc is used by nearly every process but only mapped in memory once, but it counts towards the virtual memory usage of every process. Limiting memory usage that's only used by a certain process (mostly RSS) can be done using cgroups. See answers to How to limit the total resources (memory) of a process and its children for how to do it. This will limit the total memory of a process and its children.

JanKanis
  • 1,069