Kodama's home / tips.

Linux のメモリー管理(メモリ−が足りない?,メモリーリークの検出/防止)

サ−バ等に使っているPC のメモリが十分かどうか気になる事は多いと思う. 調べ出すと フリーメモリーの不足や SWAP にメモリーがはみだしている様子など 心配な事がいろいろでて来る.

PC の動作が遅くなる原因は様々な要因が絡み合っているので, 表面に現れた症状だけでは効果的な対策が分からない事もある. 以下では, メモリ−関連にしぼって解説する.

  1. メモリの状況を調べる
  2. メモリ−は十分なはずなのに 余裕が無い?
  3. どのプロセスがメモリを消費しているのか?
  4. メモリーのリークを検出する方法? 防止する方法?
  5. メモリ−は十分なはずなのに SWAP を使ってる?
  6. じゃ, 本当のメモリ−不足はどうしたら分かるの?
  7. メモリーと SWAP 領域はどのくらい確保すると良いのか

メモリの状況を調べる

メモリの利用状況を調べる方法は, free, top, ps, vmstat, /proc/meminfo 等がある. xosview や ProcMeter を使うと X 上でグラフィカルに状況を見る事ができる. これらでメモリ−の利用状況を調べた場合, 慢性的なメモリ−不足のようにみえて, 戸惑うかも知れない. だが, メモリーが不足しているかどうか, 何が原因か, などの判断は単純にはゆかない.

メモリ−は十分なはずなのに 余裕が無い?

おや? 残りメモリ−が 1.6M(free が 1628) しかない? free の表示単位は 1k ブロックだから, 1.6M の余裕しかないように見える. ピンチなのか?
$ free
             total       used       free     shared    buffers     cached
Mem:        192572     190944       1628      54912      20112     126848
....略

-/+ buffers/chche を見よう

Linux(っていうか UNIX かな?) では, 各プロセスにメモリを割り振った残りを バッファ(buffer)とキャッシュ(cache)に利用して, ディスク入出力の負荷を減らしている. そのため, free コマンド等で見える残りメモリ−(free)は 1M 程度の 瞬間的な使いまわしに対処する程度しか残っていない事が多い.

$ free
             total       used       free     shared    buffers     cached
Mem:        192572     190944       1628      54912      20112     126848
-/+ buffers/cache:      43984     148588  <----ここを見る
Swap:        96384          0      96384

この例では, 実質的な残りメモリ−は, バッファとキャッシュに転用された分も考慮すると free+buffers+cached で計算できる. 上の例で云うと free+buffers+cached = 1628+20112+126848 = 148588. まだまだ, メモリ−には余裕がある.

どのプロセスがメモリを消費しているのか?

個々のプログラムがメモリを浪費しているかどうか, 大雑把に観察する場合どうするか.

free コマンドでは全体のメモリーの使用状況しか分からない. 個々のプロセスのメモリーの使用状況を調べるには top や ps を用いる.

メモリーのリークを検出する方法? 防止する方法?

メモリー関連の問題の分類

メモリー リークの検出

メモリーリークを検出する方法としては以下の様なものがある.

malloc と free の検証が重要となるのは, 長期間動作を続けるようなプログラム(サーバソフトなど)で 小量のメモリーリークが積み重なって動作不良の原因とならないかということだ. ゆっくりしたメモリーリークは, 検出用のツールを使わないと確認が難しい.

短い時間の処理で終了するようなプログラムでは, メモリーリークを放っておいても終了時にシステムに回収されるので気にする必要はない. ...というのを学校の課題提出とか, 顧客に納品するソフトで表だって云うと問題だが, OS をメモリー管理ソフトと思えば良いのだ. (注. ANSI/ISO C の規格では, このような場合にちゃんと領域を開放するかどうかは OS 依存らしい.) ただし, こういう考えでルーズに組まれたソフトを再利用しようとすると大変なことになる. このようなプログラムで問題となる程の "急速な" メモリーリークなら, 特別なツールを使わなくても, top コマンドで, 観察するだけで確認できる.

メモリー管理の障害の防止

メモリーリークの防止策としては, garbage collector である Boehm GC を用いて領域の開放を自動的に行うことが考えられる. 手書きで free しないで, 自動 GC に任せる事にすると メモリー リークと ダングリング リファレンス の2つの問題をほぼ解消する事ができる. C, C++ のポインタの扱いで悩んでいるなら, GC の実行効率とのトレードオフを考慮したうえで, 採用を検討すると良い. GCC のソースが Boehm GC を標準で含んでいるので(GNU/Ada に使用), C, C++ のついでに GC もインストールしてしまうと良い.

究極的には, プロジェクトで使用する言語として, 自動 GC や 配列の添字範囲の検証機能などがある言語を使う. DJB のように, buffer overflow を防止するライブラリなどを作りこんでしまっても良い. ただし, 一般に, こういうわがままが通じるかどうかは怪しいが...

メモリ−は十分なはずなのに SWAP を使ってる?

free では swap の使用量も観察できる. 起動後しばらくすると, swap にはみ出しているようにみえる事がある. これは,今あるメモリ−では不足しているという事なのか?

$ free
             total       used       free     shared    buffers     cached
...略
Swap:       151192      48628     102564

swap にはみ出していること自体を気にする人もいるが,要点を取り違えている. 前節でメモリの空きを入出力のバッファとキャッシュに利用していると書いたが, 更に, 活動が少ない部分をメモリから排除して swap に追い出し, バッファやキャッシュに転用する. つまり, 通常, swap を使っているというのは, プログラムやライブラリのうちで実際にはほとんど使われていない部分を, カ−ネルがうまく検出してメモリ−から排除している様子を表しているのだ. これだけでは, メモリ−の不足とは云えない. free コマンドで swap が出ているのもそれだけなら全く問題無しだ.

注: swap とは何か?

PCに載せたメモリでは足りなくなった場合でも, メモリ−の一部をディスクに退避させて計算を続ける事ができる. この様にしてメモリ−の容量を実際よりも大きく見せるメカニズムを仮想メモリという. そのためにディスクにメモリを退避させるための領域を swap という. Linux では swap はディスク領域として取ることもできるし, 通常のファイルの形式で(swap ファイル)確保することもできる.

メモリー容量に問題の無い例

メモリーは 700M(702888) も余っていて, 余裕分を入出力のキャッシュに転用している. swap を 50M(48628) 使っているが, まったく問題が無い.
$ free
             total       used       free     shared    buffers     cached
Mem:       1024764     960812      63952          0     162580     476356
-/+ buffers/cache:     321876     702888
Swap:       151192      48628     102564

$ vmstat 30
   procs                      memory    swap          io     system         cpu
 r  b  w   swpd   free   buff  cache  si  so    bi    bo   in    cs  us  sy  id
 2  0  0  48628  64124 162532 476356   0   0     0     0    1     4  11   3  11
 1  0  0  48628  64112 162540 476356   0   0     0     4  102  1768  98   2   0
 1  0  0  48628  64112 162540 476356   0   0     0    11  104  1576  97   3   0
 2  0  0  48628  64104 162548 476356   0   0     0    13  101  1605  98   2   0
 1  0  0  48628  64092 162560 476356   0   0     0     5  104  1674  98   2   0
 2  0  0  48628  64088 162564 476356   0   0     0     7  102  1796  97   3   0
 2  0  0  48628  64084 162568 476356   0   0     0     4  103  1572  98   2   0
 3  0  0  48628  64052 162568 476356   0   0     0     3  102  1705  97   3   0
 1  0  0  48628  64048 162572 476356   0   0     0     7  110  1786  98   2   0
emacs, TeX, Mozilla などに常用しているPCの様子.
  1. このマシンは 1ヶ月以上, 数学関係のプログラムを計算し続けていて, CPU の US の項が定常的に高い. CPU は ”熱々” である. 同時に細かな作業もしているので, procs の r(wait for run) の項にも多少の変化が見られる.
  2. 入出力は多くはないので, free も 60M(63952) と余裕を見せている.
  3. CPU の id が 0 で procs の b, w の項が無く, swap の si,so の項も活動が無いのも, メモリーやディスクが問題ではなく CPU を目一杯使っていることを表している.
この例で, あえて増強するなら, CPU だろう.

じゃ, 本当のメモリ−不足はどうしたら分かるの?

もともとメモリー不足でプログラムが動かない事を回避するための SAWP なので, そのような場合には SWAP を増やすと良い. または. 資金が許せばメモリーを増設する.

そこで問題となるのは, メモリーとディスクの動作速度の違いで, メモリー不足を SWAP で補うと, その分, 動作が遅くなってしまうという問題だ. ここで, メモリーのコストと実行速度の トレードオフを考慮する必要が出てくる. この点を以下で見てみる.

メモリ−不足で気になるのは次の様な影響が出ないかって事だ.

  1. メモリ不足でプログラムが動かない(これなら,すぐ分かる?).
  2. 一応動作するがペ−ジングが激しい(swapの活動が激しい)ために効率が落ちる.

"たまに" ページングが激しくて実行効率が低下したとしても, メモリー不足で実行できないよりはまし. このような緊急の場合の SWAP の動作を敵視する必要は無い. 定常的に swap の活動があるようなら, そのための入出力で動作が遅くなっていないかが問題となる. 多少の効率の低下が容認できるか確認すること.

メモリーが不足気味なら, メモリーを増強するかどうかを, 要求される速度とコストのトレードオフを含めて考慮しなければならない. それと, そもそも, メモリーの不足が起こっているのか, メモリーの増強で解決するのかを判断しなければならない.

プロセスのメモリ浪費は上で解説したように free, top, ps などでしらべる. 全体としてのメモリの活動状況としては,残りメモリ−や swap の大きさも参考にはなるけど, (つまり, 上の(1),(2) が起こる潜在的な危険性って意味で), 実行効率という面からの見所はディスク入出力の活動量ってことだ.

swap の動作は vmstat 30 で si と so の項を調べる

SWAP の大きさよりも ディスク入出力の活動量を見る.

なにかプログラムを動かしはじめたときに一時的に so が出るのは問題無しだ. そのための swap だしね? また, 定常的であっても, 少々の si, so が出るだけなら, 単に活発に活動しているというだけなので, 問題は無い. (ここまでは, メモリーに余裕がある場合でも通常おこる動作.)

ここからが, 注目だよ!

si が定常的にあるのも, swap がうまく働いている(メモリの余裕は少ないが)事を意味するだろうから, あまり問題にはならない.(要求される速度にもよるが...)

so の量が多い状態が定常的に続くなら作業用メモリの不足を疑ってみる. 大きさの基準は, どの程度の能力を期待しているかにも依るので, 一概には云えないようだ. しかし, 書き込みに使う領域は swap されにくいようにしてあるので, so が定常的に多いのはかなりピンチと云える.

si や so の観察で, メモリ−が不足気味だと分かっても, CPU, I/O(ネットワ−ク, ディスク等), ネットワ−クサ−ビス(NFS, NIS, DNS 等) の問題が元にあって, その影響がメモリ−の負荷に現れている可能性もある. だから, メモリ−を増やすのが最善の対策かどうかは, まだ分からない. CPU や I/O の負荷も含めて総合的に考慮する必要がある. NFS などのネットワークサービスの問題が絡むと分析はすごく厄介な事になる.

メモリが不足気味になった例

si と so に注目だ. swpd の項が swap 領域の使用量だが, 動作効率への悪影響は si, so の方が判断しやすい.
$ vmstat 30
 procs                  memory    swap        io    system         cpu
 r b w  swpd  free  buff cache  si  so   bi   bo   in   cs  us  sy  id
 0 0 0     0  9652   788 146828   0   0   28    3  177  401   3   4  92
 0 1 0     0  1648   852 141564   0   0  520    1  120  343   1   2  97
 1 0 0     0  1628   852 119292   0   0  878    1  132  341   1   3  96
 0 1 0     0  1628   536 97160   0   0  885    1  134  340   1   3  95
 0 1 0     0  1688   356 75764   0   0  850    0  176  435   3   3  94
 0 1 0     0  1640   356 62872   0   0  510    1  194  544  10   3  87
 1 1 0     0  1640   184 40208   0   0  910    0  159  370   2   3  95
 1 0 0   104  1628   148 12612   0   3 1118    1  161  364   2   9  89
 0 1 0  5436  1640   148 12772  19 197  239   49  169  327   1   6  93
 0 1 0  9184  1656   148 13768  27 151  122   38  147  354   1   2  98
 0 0 0 12228  1720   148 14072  35 134  112   34  179  401   1   2  96
 1 0 0 14640  2160   148 12512 115  81   40   21  211  595   3   2  95
 1 0 0 18064  2444   148 12516 105 114   26   29  176  496   3   1  96
 0 0 0 21220  2448   148 12612 102 105   30   27  175  486   3   2  95
  1. procs の b の項は入出力待ちなどで動作が停滞している事を 意味する.
    一時的にこの項がでるのは問題ない. 定常的に出るなら更に検査する.
  2. si,so で swap 領域の活動を見る.
    これは動作効率/速度に影響する可能性がある.
    この例の後半では, メモリー不足が生じて swap の活動が高くなっている. so と si が組になって上昇しているので メモリの使い回しに苦労しているが分かる.

    一時的なら, 問題ない. また, 必要な能力を確保できているなら気にしない. そうで無い場合, サービスの遅延が問題になるなら, 更に検査が必要.

  3. swpd で swap 領域の使用量を見る. これが溢れる状況でメモリー不足がおこると, プログラムが動作しなくなる. 溢れないなら深刻に考える必要はない.
  4. ディスク入出力の bi,bi の動向なども考えあわせること.
    これは動作効率/速度に影響する可能性がある.
    この例の前半では, ディスクの入力の負荷が高くなっている.
    後半でも活動が見られるが, ここには swap の活動も含んでいる.
  5. ネットワークの影響.
    vmstat では良く分からない.
    これは動作効率/速度に影響する可能性がある. 特に, NFS を用いる場合. NFS, NIS の動作を調査すること.
  6. CPU の id(idle) が多いのは, この場面では CPU の速度は問題となっていないことを意味する.
    入出力待ちなどが原因で CPU が有功に使えていない可能性もある.

メモリーと SWAP 領域はどのくらい確保すると良いのか

それでは, 実メモリーと SWAP 領域はどの程度確保すると良いのだろうか.
以下のような要素を考慮する.
  1. [使用時の活動的なメモリー] < [実メモリ]

    必要メモリーの量は, マシンが要求される反応速度と, SWAP の(ディスク入出力の)活動量のトレードオフを考慮して決めると良い.

    vmstat の si と so の活動から判断する.

  2. [活動が鈍いので吐き出される部分] < [SWAP]

    空きメモリーを増やして動作を軽くする事が目的. 不活発なコードを追い出すという意味で SWAP を確保する.

    長時間動作させると, 活動が鈍い部分が SWAP に吐き出される. この吐き出された量の2〜3倍以上を考えると良いだろう.

  3. [要求するメモリの限界(安全率を含む)] < [実メモリ] + [SWAP]

    SWAP を動作中のプロセスのメモリー要求が増大した場合の逃し先,という観点で評価する. この意味では,とにかく プロセスを動かし続けることを優先する.

    古典的には SWAP はメインメモリーと同程度を確保することが推奨されている. これは, 動作に必要なメモリーを搭載したうえで, 2倍の安全率を考慮するという意味と考えて良い. SWAP が活発に使われるのは非常の場合なので, 動作が遅くなってもある程度許容する.

    実メモリーを安全率も含んで大量に確保するという選択もありうる.


Kodama's home / tips.