In Linux, how to tell how much memory processes are using?

I think I may have a memory leak in my LAMP application (memory gets used up, swap starts getting used, etc.). If I could see how much memory the various processes are using, it might help me resolve my problem. Is there a way for me to see this information in *nix?

133897 次浏览

Use top or htop and pay attention to the "RES" (resident memory size) column.

Use ps to find the process id for the application, then use top -p1010 (substitute 1010 for the real process id). The RES column is the used physical memory and the VIRT column is the used virtual memory - including libraries and swapped memory.

More info can be found using "man top"

Getting right memory usage is trickier than one may think. The best way I could find is:

echo 0 $(awk '/TYPE/ {print "+", $2}' /proc/`pidof PROCESS`/smaps) | bc

Where "PROCESS" is the name of the process you want to inspect and "TYPE" is one of:

  • Rss: resident memory usage, all memory the process uses, including all memory this process shares with other processes. It does not include swap;
  • Shared: memory that this process shares with other processes;
  • Private: private memory used by this process, you can look for memory leaks here;
  • Swap: swap memory used by the process;
  • Pss: Proportional Set Size, a good overall memory indicator. It is the Rss adjusted for sharing: if a process has 1MiB private and 20MiB shared between other 10 processes, Pss is 1 + 20/10 = 3MiB

Other valid values are Size (i.e. virtual size, which is almost meaningless) and Referenced (the amount of memory currently marked as referenced or accessed).

You can use watch or some other bash-script-fu to keep an eye on those values for processes that you want to monitor.

For more informations about smaps: http://www.kernel.org/doc/Documentation/filesystems/proc.txt.

Thanks. I used this to create this simple bash script that can be used to watch a process and its memory usage:

$ watch watchmypid.sh

#!/bin/bash
#


PROCESSNAME=changethistoyourprocessname
MYPID=`pidof $PROCESSNAME`


echo "=======";
echo PID:$MYPID
echo "--------"
Rss=`echo 0 $(cat /proc/$MYPID/smaps  | grep Rss | awk '{print $2}' | sed 's#^#+#') | bc;`
Shared=`echo 0 $(cat /proc/$MYPID/smaps  | grep Shared | awk '{print $2}' | sed 's#^#+#') | bc;`
Private=`echo 0 $(cat /proc/$MYPID/smaps  | grep Private | awk '{print $2}' | sed 's#^#+#') | bc;`
Swap=`echo 0 $(cat /proc/$MYPID/smaps  | grep Swap | awk '{print $2}' | sed 's#^#+#') | bc;`
Pss=`echo 0 $(cat /proc/$MYPID/smaps  | grep Pss | awk '{print $2}' | sed 's#^#+#') | bc;`


Mem=`echo "$Rss + $Shared + $Private + $Swap + $Pss"|bc -l`


echo "Rss     " $Rss
echo "Shared  " $Shared
echo "Private " $Private
echo "Swap    " $Swap
echo "Pss     " $Pss
echo "=================";
echo "Mem     " $Mem
echo "=================";

The tool you want is ps. To get information about what java programs are doing:

ps -F -C java

To get information about http:

ps -F -C httpd

If your program is ending before you get a chance to run these, open another terminal and run:

while true; do ps -F -C myCoolCode ; sleep 0.5s ; done

You can use pmap to report memory usage.

Synopsis:

pmap [ -x | -d ] [ -q ] pids...

First get the pid:

ps ax | grep [process name]

And then:

top -p PID

You can watch various processes in the same time:

top -p PID1 -p PID2

You can use pmap + awk.

Most likely, we're interested in the RSS memory which is the 3rd column in the last line of the example pmap output below (82564).

$ pmap -x <pid>


Address           Kbytes     RSS   Dirty Mode   Mapping


....


00007f9caf3e7000       4       4       4 r----  ld-2.17.so
00007f9caf3e8000       8       8       8 rw---  ld-2.17.so
00007fffe8931000     132      12      12 rw---    [ stack ]
00007fffe89fe000       8       8       0 r-x--    [ anon ]
ffffffffff600000       4       0       0 r-x--    [ anon ]
----------------  ------  ------  ------
total kB          688584   82564    9592

Awk is then used to extract that value.

$ pmap -x <pid> | awk '/total/ { print $4 "K" }'

The pmap values are in kilobytes. If we wanted it in megabytes, we could do something like this.

$ pmap -x <pid> | awk '/total/ { print $4 / 1024 "M" }'

I don't know why the answer seem so complicated... It seems pretty simple to do this with ps:

mem()
{
ps -eo rss,pid,euser,args:100 --sort %mem | grep -v grep | grep -i $@ | awk '{printf $1/1024 "MB"; $1=""; print }'
}

Example usage:

$ mem mysql
0.511719MB 781 root /bin/sh /usr/bin/mysqld_safe
0.511719MB 1124 root logger -t mysqld -p daemon.error
2.53516MB 1123 mysql /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306

Use

  • ps u `pidof $TASKS_LIST` or ps u -C $TASK
  • ps xu --sort %mem
  • ps h -o pmem -C $TASK

Example:

ps-of()
{
ps u `pidof "$@"`
}


$ ps-of firefox
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
const    18464  5.9  9.4 1190224 372496 ?      Sl   11:28   0:33 /usr/lib/firefox/firefox


$ alias ps-mem="ps xu --sort %mem | sed -e :a -e '1p;\$q;N;6,\$D;ba'"
$ ps-mem
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
const     3656  0.0  0.4 565728 18648 ?        Sl   Nov21   0:56 /usr/bin/python /usr/lib/ubuntuone-client/ubuntuone-syncdaemon
const    11361  0.3  0.5 1054156 20372 ?       Sl   Nov25  43:50 /usr/bin/python /usr/bin/ubuntuone-control-panel-qt
const     3402  0.0  0.5 1415848 23328 ?       Sl   Nov21   1:16 nautilus -n
const     3577  2.3  2.0 1534020 79844 ?       Sl   Nov21 410:02 konsole
const    18464  6.6 12.7 1317832 501580 ?      Sl   11:28   1:34 /usr/lib/firefox/firefox


$ ps h -o pmem -C firefox
12.7

More elegant approach:

echo "Memory usage for PID <>:"; for mem in {Private,Rss,Shared,Swap,Pss};do grep $mem /proc/<pid>/smaps | awk -v mem_type="$mem" '{i=i+$2} END {print mem_type,"memory usage:"i}' ;done

Why all these complicated answers with various shell scripts? Use htop, it automatically changes the sizes and you can select which info you want shown and it works in the terminal, so it does not require a desktop. Example: htop -d8

In case you don't have a current or long running process to track, you can use /usr/bin/time.

This is not the same as Bash time (as you will see).

Eg

# /usr/bin/time -f "%M" echo


2028

This is "Maximum resident set size of the process during its lifetime, in Kilobytes" (quoted from the man page). That is, the same as RES in top et al.

There are a lot more you can get from /usr/bin/time.

# /usr/bin/time -v echo


Command being timed: "echo"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 0%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 1988
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 77
Voluntary context switches: 1
Involuntary context switches: 0
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0