Getting an accurate view of process memory usage on Linux hosts

Having debugged a number of memory-related issues on Linux, one thing I’ve always wanted was a tool to display proportional memory usage. Specifically, I wanted to be able to see how much memory was unique to a process, and have an equal portion of shared memory (libraries, SMS, etc.) added to this value. My wish came true a while back when I discovered the smem utility. When run without any arguments, smem will give you the resident set size (RSS), the unique set size (USS) and the proportional set size (PSS) which is the unique set size plus a portion of the shared memory that is being used by this process. This results in output similar to the following:

$ smem -r

  PID User     Command                         Swap      USS      PSS      RSS 
 3636 root     /usr/lib/virtualbox/Virtual        0  1151596  1153670  1165568 
 3678 matty    /usr/lib64/firefox-3.5.9/fi        0   189628   191483   203028 
 5779 root     /usr/bin/python /usr/bin/sm        0    38584    39114    40368 
 1847 root     /usr/bin/Xorg :0 -nr -verbo        0    34024    35874    92504 
 4103 matty    pidgin                             0    19364    21072    32412 
 3825 matty    gnome-terminal                     0    12388    13242    21992 
 3404 matty    python /usr/share/system-co        0    11596    12622    19216 
 3710 matty    gnome-screensaver                  0     9872    10287    14640 
 3283 matty    nautilus                           0     7104     8373    18484 
 3263 matty    gnome-panel                        0     5828     6731    15780 

To calculate the portion of shared memory that is being used by each process, you can add up the shared memory per process (you would probably index this by the type of shared resource), the number of processes using these pages, and then divide the two values to get a proportional value of shared memory per process. This is a very cool utility, and one that gets installed on all of my systems now!

Getting DNS ping (aka nsping) to compile on Linux hosts

While debugging a DNS issue this week, I wanted to run my trusty old friend nsping on my Linux desktop. I grabbed the source from the FreeBSD source site, checked to make sure the bits were legit, then proceeded to compile it:

$ make
cc -g -c -o nsping.o nsping.c
In file included from nsping.c:13:
nsping.h:45: error: conflicting types for ‘dprintf’
/usr/include/stdio.h:399: note: previous declaration of ‘dprintf’ was here
nsping.c:613: error: conflicting types for ‘dprintf’
/usr/include/stdio.h:399: note: previous declaration of ‘dprintf’ was here
make: *** [nsping.o] Error 1

Erf! The source archive I downloaded didn’t compile, and from the error message it appears the function definition for dprintf conflicts with a function definition in libc. Instead of mucking around with map files, I changed all occurrences of dprintf to ddprintf. When I ran make again I got a new error:

$ make
cc -g -c -o nsping.o nsping.c
cc -g -c -o dns-lib.o dns-lib.c
dns-lib.c: In function ‘dns_query’:
dns-lib.c:22: warning: incompatible implicit declaration of built-in function ‘memset’
cc -g -c -o dns-rr.o dns-rr.c
dns-rr.c: In function ‘dns_rr_query’:
dns-rr.c:26: warning: return makes integer from pointer without a cast
cc -g -o nsping nsping.o dns-lib.o dns-rr.o
dns-rr.o: In function `dns_string’:
/home/matty/Download/nsping-0.8/dns-rr.c:63: undefined reference to `__dn_comp’
collect2: ld returned 1 exit status
make: *** [nsping] Error 1

This error message indicates that the dn_comp symbol couldn’t be resolved. This function typically resides in the resolver library, so working around this was as easy as assing “-lresolv” to the LIBS variable in the nsping Makefile:

LIBS = -lresolv

Once this change was made, everything compiled and ran flawlessly:

$ make
cc -g -o nsping nsping.o dns-lib.o dns-rr.o -lresolv

$ ./nsping -h
./nsping: option requires an argument — ‘h’
nsping [ -z | -h ] -p -t
-a -P
-T <-r | -R, recurse?>

Debugging this issue was a bunch of fun, and reading through the nsping source code was extremely educational. Not only did I learn more about how libresolv works, but I found out sys5 sucks:

#ifdef sys5
#warning “YOUR OPERATING SYSTEM SUCKS.”

You gotta love developers who are straight and to the point! ;)