pmap
tool can be used to do capacity planning. pmap
prints information about the virtual address space of a process. In other words, pmap
output represents snapshot of a running process.To calculate per user memory footprint from a process, the following simple formula can be used:
Total private memory + (Total shared memory/#instances)
-------------------------------------------------------
(Total load)
Where:
#instances
is the actual number of instances of the program/application concurrently running. It is not uncommon for large applications like Oracle, Siebel to fork multiple instances of a server, to improve concurrency.Total load
is the number of concurrent users connected to the application. In multi-threaded server applications, this should be the sum of all users connected to the forked processes of the server.Total private memory
is the total memory used exclusively by all the instances of the process.Private memory is the memory used exclusively by a single process -- it will be reported under
Anon
column of pmap -x <pid>
output.Total shared memory
is the total memory being shared by more than one process. More than one HAT mapping {in pmap
s output} indicates that more than one process is actively sharing this mapping -- shared memory can be calculated using (RSS-Anon
) from pmap
s output.Note:
- If one of the processes, sharing the page, tries to alter the shared code, a copy-on-write (COW) page fault occurs; and the kernel will make a special copy of the page containing those instruction for the modifying process, allowing everyone else to share the unchanged page. The newly created page becomes part of the private memory segment.
- RSS (Resident Set Size) column of
pmap -x <pid>
shows the amount of virtual memory touched by either read or write operation on processes' virtual memory location, and in turn, the number of physical pages brought into memory as a result of the memory touch operation.
Example:
%cat alloc.c
#include <stdlib.h>
#include <unistd.h>
int main()
{
int *bigArray;
bigArray = (int *) malloc (sizeof(int) * 100000);
sleep (30);
return (0);
}
%./alloc &
[1] 1941
%pmap -x 1941
1941: ./alloc
Address Kbytes RSS Anon Locked Mode Mapped File
00010000 8 8 - - r-x-- alloc
00020000 8 8 8 - rwx-- alloc
00022000 392 8 8 - rwx-- [ heap ]
FF280000 688 688 - - r-x-- libc.so.1
FF33C000 32 32 32 - rwx-- libc.so.1
FF390000 8 8 8 - rwx-- [ anon ]
FF3A0000 8 8 - - r-x-- libc_psr.so.1
FF3B0000 184 184 - - r-x-- ld.so.1
FF3EE000 8 8 8 - rwx-- ld.so.1
FF3F0000 8 8 8 - rwx-- ld.so.1
FF3FA000 8 8 8 - rwx-- libdl.so.1
FFBF6000 40 40 40 - rwx-- [ stack ]
-------- ------- ------- ------- -------
total Kb 1392 1008 120 -
This process is consuming 1,392 KB of virtual memory, with 1,008 KB being resident in {physical} memory. Out of 1,008 KB memory, 120 KB is private to this process; and 880 KB (=1008-120) is being shared along with other processes. So, the memory footprint of this process is (total shared memory + total private memory) = 1,008 KB. Note that in this example, #instances = 1; and total load = 1 user (since only one copy of the executable is running)
Note:
Since this is a simple example, we can directly consider the value of
RSS
as the total memory footprint of this process.The following example shows how to calculate per user memory footprint, when
sleep
is invoked by two users:% sleep 30 &
[1] 2272
% pmap -x 2272
2272: sleep 30
Address Kbytes RSS Anon Locked Mode Mapped File
00010000 8 8 - - r-x-- sleep
00020000 8 8 8 - rwx-- sleep
00022000 8 8 8 - rwx-- [ heap ]
FF280000 688 688 - - r-x-- libc.so.1
FF33C000 32 32 32 - rwx-- libc.so.1
FF390000 8 8 8 - rwx-- [ anon ]
FF3A0000 8 8 - - r-x-- libc_psr.so.1
FF3B0000 184 184 - - r-x-- ld.so.1
FF3EE000 8 8 8 - rwx-- ld.so.1
FF3F0000 8 8 8 - rwx-- ld.so.1
FF3FA000 8 8 8 - rwx-- libdl.so.1
FFBFE000 8 8 8 - rw--- [ stack ]
-------- ------- ------- ------- -------
total Kb 976 976 88 -
% sleep 30 &
[1] 2274
% pmap -x 2274
2274: sleep 30
Address Kbytes RSS Anon Locked Mode Mapped File
00010000 8 8 - - r-x-- sleep
00020000 8 8 8 - rwx-- sleep
00022000 8 8 8 - rwx-- [ heap ]
FF280000 688 688 - - r-x-- libc.so.1
FF33C000 32 32 32 - rwx-- libc.so.1
FF390000 8 8 8 - rwx-- [ anon ]
FF3A0000 8 8 - - r-x-- libc_psr.so.1
FF3B0000 184 184 - - r-x-- ld.so.1
FF3EE000 8 8 8 - rwx-- ld.so.1
FF3F0000 8 8 8 - rwx-- ld.so.1
FF3FA000 8 8 8 - rwx-- libdl.so.1
FFBFE000 8 8 8 - rw--- [ stack ]
-------- ------- ------- ------- -------
total Kb 976 976 88 -
From the above outputs:
Total private memory = (88 + 88) = 176 KB
Total RSS = (976 + 976) = 1,952 KB
Total shared memory = (1,952 - 176) = 1,776 KB
Memory consumption/user (by running
sleep
) = (176 + (1,776/2))/2 = (176 + 888)/2 = 532 KB.Shell script to calculate the per user memory footprint
The following simple script automates the above calculation (script credit: Khader Mohiuddin/Kesari Mandyam):
_________
% cat memfootprint
#!/bin/bash
#if [ $# -eq 0 ]; then
if [ $# -ne 2 ]; then
echo "Usage: memfootprint <process_name> <total_load>"
exit
fi
count=0
PIDS=`/usr/bin/ps -ef | grep $1 | grep -v "grep $1" | grep -v memfootprint | awk '{ print $2 }'`
for pid in $PIDS
do
echo 'pmap process :' $pid
count=`expr $count + 1`
done
pmap -x $PIDS | grep total | awk 'BEGIN { FS = " " } {print $1,$2,$3,$4,$5} {rss+=$4} {private+=$5} END {print "Total Private mem: "private/1024" M Total RSS mem: "rss/1024" M Total Shared mem: " (rss-private)/1024 "M **** For '$2' user load: Memory Footprint is: "((private/1024)+(((rss-private)/1024)/'$count'))/'$2'" MB/user"}'
eg., #1
% sleep 60&
[9] 3757
% sleep 60&
[4] 3758
% sh +x memfootprint sleep 2
pmap process : 3757
pmap process : 3758
total Kb 976 976 88
total Kb 976 976 88
Total Private mem: 0.171875 M Total RSS mem: 1.90625 M Total Shared mem: 1.73438M
**** For 2 user load: Memory Footprint is: 0.519531 MB/user
eg., #2
% sleep 60&
[1] 3783
% sleep 60&
[2] 3784
% sleep 60&
[3] 3785
% sleep 60&
[4] 3786
% sleep 60&
[5] 3787
% sleep 60&
[6] 3788
% sh +x memfootprint sleep 6
pmap process : 3787
pmap process : 3785
pmap process : 3783
pmap process : 3788
pmap process : 3784
pmap process : 3786
total Kb 976 976 88
total Kb 976 976 88
total Kb 976 976 88
total Kb 976 976 88
total Kb 976 976 88
total Kb 976 976 88
Total Private mem: 0.515625 M Total RSS mem: 5.71875 M Total Shared mem: 5.20312M
**** For 6 user load: Memory Footprint is: 0.230469 MB/user
[Updated 03/27/2008]
The shell script in this blog post was slightly modified to emit the output cleanly. Here is the modified script:
% memfootprint
#!/bin/sh
if [ $# -lt 2 ]; then
echo "Usage: memfootprint <Pattern> <NumOfUsers>"
exit
fi
WHOAMI=`/usr/ucb/whoami`
PIDS=`/usr/bin/ps -ef | grep $WHOAMI" " | grep $1 | grep -v "grep $1" | grep -v memfootprint | grep -v dog | awk '{ print $2 }'`
for pid in $PIDS
do
echo 'PID:' $pid
done
printf "------------------------------------------------------------------\n"
umask 0
printf "%-10s %-15s %-15s %-15s %-15s\n" PID Kbytes Resident Private Shared
printf "%-10s %-15s %-15s %-15s %-15s\n" "" "" " Kbytes" " Kbytes" Kbytes
printf "%-10s %-15s %-15s %-15s %-15s\n" --- ------ -------- ------- ------
pmap -x $PIDS | grep total | nawk -v Arg1=$2 'BEGIN { FS = " " }
{ printf "%-10s %-15s %-15s %-15s %-15s\n", "_NA_", $3, $4, $5, ""} {rss+=$4} {private+=$5} END {
printf "%-10s %-15s %-15s %-15s %-15s\n", "---", "------", "--------", "-------", "------"
printf "%-10s %-15s %-15s %-15s %-15s\n", "_NA_", "_NA", rss, private, (rss-private)
printf "------------------------------------------------------------------\n"
printf "Number of Users: %-10s\n", Arg1
printf "Per User Memory Footprint: %13.8f Mega Bytes\n", ((private/1024)+(((rss-private)/1024)/NR))/Arg1
}
Sample output from the enhanced script:
% sleep 60 &
[1] 4478
% sleep 60 &
[2] 4479
% sleep 60 &
[3] 4480
% sleep 60 &
[4] 4481
% sleep 60 &
[5] 4482
% sleep 60 &
[6] 4483
% ./memfootprint sleep 6
PID: 4480
PID: 4481
PID: 4483
PID: 4479
PID: 4478
PID: 4482
------------------------------------------------------------------
PID Kbytes Resident Private Shared
Kbytes Kbytes Kbytes
--- ------ -------- ------- ------
_NA_ 1352 1304 168
_NA_ 1352 1304 168
_NA_ 1352 1304 168
_NA_ 1352 1304 168
_NA_ 1352 1304 168
_NA_ 1352 1304 168
--- ------ -------- ------- ------
_NA_ _NA 7824 1008 6816
------------------------------------------------------------------
Number of Users: 6
Per User Memory Footprint: 0.34895833 Mega Bytes
To DO://
Fix the PIDs in the table. Currently they are represented with "_NA_".
Suggested reading:
Process Memory Requests: Process Virtual Address Space, Memory, and Swap by Hae Hirdler
________________
Technorati tag: Solaris | OpenSolaris
No comments:
Post a Comment