44

I need to test a process for memory management.

  • I do not have the source, so I need to do all the testing from the OS side.
  • I want to be able to say something like limitmemory 400k -p <pid>

Is there a way to do this in unix? Any common unix utility would be excellent.

3
  • Some Unixes (Solaris, for example) do support more fine-grained control of resources on processes, process groups, project groups, etc. But I mention this only as a comment because you've tagged this 'linux' although you say 'in unix'.
    – jrg
    Sep 2, 2010 at 20:11
  • 2
    Your question is extremely vague about what you actually want to do. Do you want to limit the amount of address space the process can use? Do you want to limit how many physical pages of memory it can have resident? Oct 23, 2011 at 6:01
  • Consider running it under e.g. valgrind.
    – vonbrand
    Oct 25, 2015 at 13:21

7 Answers 7

28

ulimit -v, it's a shell builtin, but it should do what you want.

I use that in init scripts sometimes:

ulimit -v 128k
command
ulimit -v unlimited

It seems however, that you want ways of manipulating the maximum allocatable memory while the program is running, is that correct? Probably something like renice for manipulating the Priority.

There is, however, no such tool to my knowledge.

4
  • 5
    but ulimit will change the resource limit to all the process strted by that shell not just on pid. it limits the use of system-wide resources.
    – Hemant
    Aug 31, 2010 at 16:28
  • 1
    @Hemant: then ulimit is not going to be as useful as I thought. Is there some other option?
    – Lazer
    Aug 31, 2010 at 18:44
  • 12
    @Lazer: start the program with something like (ulimit -v 400; exec myprogram) or bash -c 'ulimit -v 400; myprogram'. Aug 31, 2010 at 22:58
  • 5
    128k does not work on Bash 4.3.11 . But it is not needed either as it is in multiple of 1024 by default, so 128 should be the same. Oct 24, 2015 at 20:35
15

On Linux systems with kernel >=2.6.36 and util-linux >=2.21, you can use the prlimit command to set a process resource limits:

prlimit --as=400000 --pid <pid>

This will restrict the max amount of virtual memory the process can use to 400000. You can find the full list of resources you can limit for a given process in man 2 prlimit.

As noted in the comments and in the manpage, limiting the amount of RSS does not work in kernels >2.4.0 and <2.4.30.

4
  • 3
    This only works in Linux 2.4.x where x < 30, cf. RLIMIT_RSS in man (2) setrlimit. Said differently: it doesn't work.
    – Totor
    Jul 28, 2017 at 10:28
  • Why so many upvotes if it doesn't work on recent Linux?
    – ks1322
    Aug 28, 2020 at 15:32
  • 1
    only the example was wrong (corrected), the answer itself is correct and still valid today: the command to set resource limits on a running process is prlimit. You just have to choose the right option depending on what you want limit and which kernel you are using. Aug 29, 2020 at 10:41
  • 3
    Also note, the OP asked how to limit the memory of a running process and provided as an example of what he wants to do "limitmemory -p <pid>". None of the other upvoted answers allows this, they all explain how to limit the memory of a process that has not been started yet or require restarting the process. That is not what OP asked for. Aug 29, 2020 at 10:52
14

On Linux systems you can use the memory controller from Control Groups version 1 or version 2.

systemd makes it easy to control resource usage, especially on systems with cgroups-v2:

MemoryHigh=bytes

  Specify the throttling limit on memory usage of the executed processes in this unit. Memory usage may go above the limit if unavoidable, but the processes are heavily slowed down and memory is taken away aggressively in such cases. This is the main mechanism to control memory usage of a unit. […]

MemoryMax=bytes

  Specify the absolute limit on memory usage of the executed processes in this unit. If memory usage cannot be contained under the limit, out-of-memory killer is invoked inside the unit. It is recommended to use MemoryHigh= as the main control mechanism and use MemoryMax= as the last line of defense. […]

MemoryLimit=bytes

  Specify the limit on maximum memory usage of the executed processes. […]

  This setting is deprecated. Use MemoryMax= instead.

If instead of creating and customizing a full blown service, you just want to run an ad-hoc command, then you can use the systemd-run utility as suggested by user Hi-Angel:

systemd-run --scope -p MemoryMax=1G firefox

--scope

  Create a transient .scope unit instead of the default transient .service unit (see above).

--property=, -p

  Sets a property on the scope or service unit that is created. This option takes an assignment in the same format as systemctl(1)'s set-property command.

3
  • 3
    cgroups are the Right Way Forward for the future. Won't work in older distributions, but from basically now onward, it's the way forward. Look into libcgroup sourceforge.net/projects/libcg for utilities to control them.
    – mattdm
    Nov 26, 2010 at 15:09
  • 1
    The package is named libcgroup-tools on Fedora 17. Jul 13, 2012 at 3:21
  • 3
    Or even better systemd-run which implicitly uses cgroups, like in systemd-run --scope -p MemoryLimit=1G firefox.
    – Hi-Angel
    Aug 17, 2019 at 18:51
12

To set the limit when starting the program, use ulimit -v 400, as indicated by polemon. This sets the limit for the shell and all its descendants, so in a script you might want to use something like (ulimit -v 400; myprogram) to limit the scope.

If you need to change the limit for a running process, there's no utility for that. You have to get the process to execute the setrlimit system call. This can often be done with a debugger, although it doesn't always work reliably. Here's how you might do this with gdb (untested; 9 is the value of RLIMIT_AS on Linux):

gdb -n -pid $pid -batch -x /dev/stdin <<EOF
call setrlimit(9, {409600, -1})
detach
quit
EOF
4

If you're using systemd, you can set some additional options in a .service file. The complete list of the options you can set is described here.

Below is a short example that shows how to use this feature of systemd:

# cat /etc/systemd/system/qbittorrent-nox.service
[Unit]
Description=qbittorrent-nox
Documentation=man:qbittorrent-nox
DefaultDependencies=yes
Requires=media-Kabi.mount
After=media-Kabi.mount network-online.target
Before=multi-user.target
Conflicts=umount.target

[Service]
User=morfik
Group=p2p
Type= simple
RemainAfterExit=no
ExecStart=/usr/bin/qbittorrent-nox
Nice=19
IOSchedulingClass=idle
PrivateNetwork=no
CPUShares=256
MemoryLimit=50M
BlockIOWeight=128
Slice=p2p.slice
StandardError=null
StandardOutput=null

[Install]
WantedBy=multi-user.target

Of course, you don't need all of the options I used. If you just want to limit memory usage, add MemoryLimit=50M, which limits to 50MiB.

And this is the result:

# systemctl status qbittorrent-nox.service
● qbittorrent-nox.service - qbittorrent-nox
   Loaded: loaded (/etc/systemd/system/qbittorrent-nox.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2015-05-07 19:25:20 CEST; 1s ago
     Docs: man:qbittorrent-nox
 Main PID: 21712 (qbittorrent-nox)
   Memory: 9.4M (limit: 50.0M)
   CGroup: /p2p.slice/qbittorrent-nox.service
           └─21712 /usr/bin/qbittorrent-nox

May 07 19:25:20 morfikownia systemd[1]: Started qbittorrent-nox.
May 07 19:25:20 morfikownia systemd[1]: Starting qbittorrent-nox...

So far, this works only for system daemons/services, and you can't limit, for instance, a firefox processes as a regular user in this way. But maybe this will change some day.

2

There is the setrlimit() function, which allows to configure a process' limits in C. Write a C program to call setrlimit then to exec the command you want to be limited. setrlimit cannot change other processes' limits.

Luckily someone already wrote something similar. It can be downloaded from freshmeat. I had a quick look at the source code and it seems to be fine. Use rlimit at your own discretion. Note that rlimit also cannot change other processes' limits.

Edit: Gilles proposed a nice hack with gdb: Attach to the process with gdb then make the process call setrlimit. This would perhaps solve the problem to limit an already running process.

0

If you just want to test and measure the memory usage of your program please look at time. You can measure the resource usage of your program in many aspects including the terms of CPU Time and memory usage. Following command will give you the memory usage and CPU time usage of myProgram:

/usr/bin/time myProgram

(Be sure to give the absolute path to distinguish it from bash built-in time command.)

If you just want to limit the resources of your process, i recommend you to create a test user for this specific task. Limit the resources of this user according to your needs and run the process by the user. It seems that, in *nix world, resource management based on users is much more advanced than resource management based on processes.

You can check /etc/security/limits.conf to limit the resources of a user. Or you can use ulimit after logged in with the to-be-limited user.

1
  • On some versions of Unix/Linux, this isn't going to be helpful. (The man pages says this might be the case.) On a CentOS 5.5 box, I get "0" for maxresident every time. However, it does work on Fedora 14.
    – mattdm
    Nov 26, 2010 at 15:18

Not the answer you're looking for? Browse other questions tagged .