maehachi08 Anything Blog

2013年12月18日
LinuxでプロセスごとのSwap Sizeを確認する方法

今回はプロセス毎のswap sizeを確認する方法のお話です。

muninでMemory usageグラフを眺めていて、swap sizeが数100MB程度発生していて、どのプロセスがどの程度swappingしているのか知りたくなりました。

そこでprocファイルシステムに何か情報があるのかと調べてみたら、/proc/ [ PID ] /statusで欲しい情報が確認出来そうです。以下のコマンド結果はmysqldプロセスの情報です。

# cat /proc/1263/status
Name:   mysqld
State:  S (sleeping)
Tgid:   1263
Pid:    1263
PPid:   1161
TracerPid:      0
Uid:    27      27      27      27
Gid:    27      27      27      27
Utrace: 0
FDSize: 256
Groups: 27
VmPeak:  1234116 kB
VmSize:  1195492 kB
VmLck:         0 kB
VmHWM:     29500 kB
VmRSS:     18952 kB
VmData:  1135196 kB
VmStk:        88 kB
VmExe:      6532 kB
VmLib:      7376 kB
VmPTE:       436 kB
VmSwap:    23000 kB
Threads:        13
SigQ:   0/7817
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000087007
SigIgn: 0000000000001006
SigCgt: 00000001800066e9
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed:   3
Cpus_allowed_list:      0-1
Mems_allowed:   00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list:      0
voluntary_ctxt_switches:        233669
nonvoluntary_ctxt_switches:     29

/proc/ [ PID ] /statusVmSwapという項目がswap sizeだということが判明しました。このswap sizeの大きい順に表示するには以下コマンドで表示できました。

# grep VmSwap /proc/*/status | sort -k 2 -r | head
/proc/1416/status:VmSwap:            764 kB
/proc/1425/status:VmSwap:            632 kB
/proc/1171/status:VmSwap:            356 kB
/proc/525/status:VmSwap:             280 kB
/proc/1479/status:VmSwap:            280 kB
/proc/1448/status:VmSwap:            252 kB
/proc/1478/status:VmSwap:            248 kB
/proc/1262/status:VmSwap:            248 kB
/proc/1263/status:VmSwap:            212 kB
/proc/1440/status:VmSwap:            144 kB

Swap sizeの大きい順にプロセス名を確認するためのperlスクリプトを作りました

上記したとおり、procファイルシステムを利用してプロセスごとのswap sizeを表示できるのですが、残念ながらこれではプロセス名が分からず不便です。幸い、この/proc/ [ PID ] /statusファイルにはNameという項目でプロセス名があるので、swap sizeの大きいPID順にプロセス名も取得し、swap sizeの大きいプロセス順に表示するperlスクリプトを書きました。

#!/bin/env perl
# pachi
#
# This script find out process currently swapped by /proc/$PID/status
use strict;
use warnings;

# When you want to debug, you should exec "export SCRIPT_DEBUG=1".
my $debug = $ENV{SCRIPT_DEBUG} ? 1 : 0;

my $proc_status = `grep VmSwap /proc/*/status | sort -k 2 -r`;
my @proc_status = split m{\n}, $proc_status;
my $proc_swaps  = [];

foreach my $status_line ( @proc_status ) {
    my $process_info = {};

    chomp $status_line;
    my @status_line     = split /\s+/, $status_line;
    my $proc_path       = $status_line[0];
    my $proc_swap_value = $status_line[1];
    my $pid             = ( split( /\//,$proc_path ) )[2];

    if ( ! -f "/proc/$pid/status" ) {
        # file not found! next.
        next;
    }

    # get process name by pid
    my $process_name_line = `grep Name /proc/$pid/status`;
    chomp $process_name_line;
    my @process_name_line       = split /\s+/, $process_name_line;
    my $process_name            = $process_name_line[1];
    $process_info->{name}       = $process_name;
    $process_info->{pid}        = $pid;
    $process_info->{swap_value} = $proc_swap_value;

    # Process information is stored in hash
    push @$proc_swaps ,$process_info;

}

# Print header
printf "--------------------+----------+---------------+\n";
printf "       Swap size classified by processes       |\n";
printf "--------------------+----------+---------------+\n";
printf "    Process Name    |   PID    |   Swap Size   |\n";
printf "--------------------+----------+---------------+\n";

# Print every process info
foreach my $proc_swap ( @$proc_swaps ) {
    printf ("%-20s|", "$proc_swap->{name}");
    printf ("%10s |", "$proc_swap->{pid}");
    printf ("%15s |", "$proc_swap->{swap_value}KB");
    printf "\n";
}

# Print footer
printf "\n";

exit 0;

"grep VmSwap"しているのでswap sizeに特化しているんですけど、以下がスクリプトを実行した感じです。実行結果はプロセス名とPIDとswap sizeをprintfで整形して出力しています。

$ ./swaplist.pl | head -20
--------------------+----------+---------------+
       Swap size classified by processes       |
--------------------+----------+---------------+
    Process Name    |   PID    |   Swap Size   |
--------------------+----------+---------------+
ruby                |      7640|        70724KB|
ruby                |     28861|        29220KB|
ruby                |     10300|        28820KB|
httpd               |     25049|        27496KB|
mysqld              |      1263|        25092KB|
httpd               |     24997|        11612KB|
ruby                |     24983|         6412KB|
rsyslogd            |      1064|         6368KB|
munin-node          |      8543|         5500KB|
httpd               |     25051|         5276KB|
httpd               |     24994|         4304KB|
httpd               |     28182|         3988KB|
httpd               |     24976|         3932KB|
httpd               |     25000|         3928KB|
httpd               |     25024|         3856KB|

実行環境ではRailsアプリケーションを動かしています。そして、実行結果から、ruby、httpd、mysqldなどのプロセスがswappingしていることが分かりました!!