Linux /proc/pid/smaps proportional swap (like Pss but for swap)

1.7k views Asked by At

It seems (from looking at the Linux kernel source) that the Swap: metric in /proc/pid/smaps is the total swap accessible by the given pid.

In the case where there is shared memory involved, this seems to be an over-approximation of actual swap usage. For example when summing swap usage of a parent pid with its forked children, and if they have common shared memory in the swap, then it appears that this portion (swapped shared memory) is counted multiple times (once per pid).

My question is whether there is a way to figure out a fair swap usage metric based on the number of processes sharing it (similar to Pss:).

3

There are 3 answers

0
Jérôme Pouiller On BEST ANSWER

You just have to divide Swap value by number of process that are sharing this Virtual Memory Area.

Actually, I didn't find how to get number of process sharing a VMA. However, it is sometime possible to calculate it by dividing RSS with PSS. Sure, it only work if PSS != 0.

Finaly, you can use this perl code (pass smap file as argument):

#!/usr/bin/perl -w
my ($rss, $pss);
my $total = 0;

while(<>) {
  $rss = $1 if /Rss: *([0-9]*) kB/;
  $pss = $1 if /Pss: *([0-9]*) kB/;
  if (/Swap: *([0-9]*) kB/) {
    my $swap = $1;
    if ($swap != 0) {
      if ($pss == 0) {
        print "Cannot get number of process using this VMA\n";

      } else {
        my $swap = $swap * $rss / $pss;
        print "P-swap: $swap\n";
      }
      $total += $swap;
    }
  }
}
print "Total P-Swap: $total kB\n"
1
gj13 On

you can use the output of the tool smem. It has multiple output and filter options.

1
eddy85br On

You can adapt this script from http://northernmost.org/blog/find-out-what-is-using-your-swap/:

#!/bin/bash
# Get current swap usage for all running processes
# Erik Ljungstrom 27/05/2011
#
## I've made some modifications to match my purposes.
## PIDs that don't use swap are printed to STDERR and not STDOUT...

OVERALL=0
PROGLIST=$(ps axw -o pid,args --no-headers)

while read PID ARGS; do
    SUM=0
    if [ -f "/proc/$PID/smaps" ]; then
        for SWAP in $(fgrep 'Swap' /proc/$PID/smaps 2>/dev/null | awk '{ print $2 }') ; do
            let SUM=$SUM+$SWAP
        done
    fi
    if [[ $SUM > 0 ]]; then
        printf "PID: %-6s | Swap used: %-6s KB   => %s\n" $PID $SUM "$ARGS"
    else
        printf "Not using Swap, PID: %-6s => %s\n" $PID "$ARGS" 1>/dev/stderr
    fi
    let OVERALL=$OVERALL+$SUM

done <<<"$PROGLIST"

echo "Overall swap used: $OVERALL"
exit 0;

This link could be helpful too.