1. 概要

Linuxは、その設計により、利用可能なすべての物理メモリを可能な限り効率的に使用することを目的としています。 ただし、システムリソースの制限により、サーバー側で突然の動作が発生する場合があります。 通常、これらの制限により、CPUとメモリの使用率が高くなります。 いずれにせよ、プロセスのメモリ使用率を観察することで、このような突然の動作を実際に回避することができます。

このチュートリアルでは、プロセスのピークメモリ使用量を認識するのに役立つ、いくつかのよく知られたLinuxコマンドを使用していくつかのヒントとコツを実装する方法を学びます。

2. メモリを監視するための従来のコマンド

ほとんどの場合、 top / htop /atopのようなコマンドでプロセスの概要がわかります。 特定のケースでは、特定のプロセスを監視するために使用することもできます。 ここでは、プロセスのチェックに焦点を当てて、そのピークメモリ使用率を特定します。

トップの結果を調査して、プロセスの概要を確認することから始めます。 これにより、すべてのプロセスが何を使用しているかがわかります。

特定のプロセスに焦点を合わせる必要があり、そのプロセスID(PID)がわかっているとします。

$ top -p 7
top - 10:25:53 up 19 min,  0 users,  load average: 0.52, 0.58, 0.59
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 16.0 us,  6.2 sy,  0.0 ni, 77.1 id,  0.0 wa,  0.7 hi,  0.0 si,  0.0 st
MiB Mem :   3961.1 total,    665.1 free,   3072.0 used,    224.0 buff/cache
MiB Swap:  12288.0 total,  11806.3 free,    481.7 used.    758.5 avail Mem
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    7 user1     20   0   18076   3632   3528 S   0.0   0.1   0:00.19 bash

次に、bashの使用法を見ていきます。

$ top | grep bash
    7 user1     20   0   18076   3632   3528 S   0.0   0.1   0:00.19 bash
   73 root      20   0   18076   3604   3540 S   0.0   0.1   0:00.17 bash

htoptop、に似ていますが、プロセスに関するより多くのデータを表示します。 プロセスパスを認識するのに便利なコマンド列があります。

atop も、tophtopのようなコマンドです。 その利点は、出力をファイルに記録するという非常に便利な機能です。

特定の時間枠で何度も発生する問題について考えてみます。 記録を保持するために、出力をファイルに書き込むためのcronジョブをスケジュールできるため、後で再生できるようになります。 出力をファイルに記録する必要がある場合は、 atop-wを使用します。

$ atop -w filename

また、そのファイルからの出力を再生する必要がある場合は、 atop-rを使用します。

$ atop -r filename
  PID      SYSCPU       USRCPU        VGROW        RGROW       RUID           EUID           ST       EXC        THR       S       CPUNR        CPU       CMD        1/1   73       0.17s        0.03s       481.1G        3604K       root           root           N-         -          1       S           0         0%       bash
    7       0.10s        0.09s       591.0G        3632K       user1          user1          N-         -          1       S           0         0%       bash
    1       0.15s        0.00s       376.9G         316K       root           root           N-         -          2       S           0         0%       init
   71       0.04s        0.00s       716.4G        2908K       root           root           N-         -          1       S           0         0%       sudo
   72       0.03s        0.00s       820.0G        2092K       root           root           N-         -          1       S           0         0%       su
  109       0.01s        0.00s         1.0T        2136K       root           root           N-         -          1       R           0         0%       atop
    6       0.00s        0.01s       376.9G         224K       root           root           N-         -          1       S           0         0%       init

これらの3つのコマンドは、継続的な調査に最適なツールです。 私たちの状況では、プロセスが設定された制限に達する前に、プロセスのピークメモリ使用量を特定できます。

3. grepワンライナー

/ proc仮想ファイルシステムは、Linuxカーネルの現在の状態を表すファイルの階層を含むディレクトリです。 また、現在実行中のプロセスに関する情報も含まれています。

これは、プロセスID(PID)113を持つそのようなプロセスのピークメモリ使用量を決定するワンライナーです。

$ grep ^VmPeak /proc/113/status 
VmPeak: 2252 kB

また、RAM使用量を測定するために「VmHWM:ピーク常駐セットサイズ」を探すこともできます。 VmPeakは、仮想メモリを含む最大合計メモリ使用量であり、VmHWMはピークRAM使用量です

ご存知のように、 / proc は仮想ファイルシステムであるため、そのファイルからの読み取りは、通常のファイルシステムからの読み取りと同じではありません。 プロセスに関する情報は、実際のファイルシステムの場合よりもはるかに高速に / proc から削除されます(ダーティキャッシュフラッシングがここに含まれます)。

これを念頭に置いて、まだバッファリングされていないプロセスの次の行を読み取る必要があると想像してください。 この場合、それに関する情報はすでに削除されている可能性があります。 存在しなくなったプロセスに関する情報は必要ない場合があります。 解決策は、ファイルの損失を考慮するか、ファイル全体をバッファリングしてから解析することです。

4. GNU時間

いくつかの例を見て、与えられたコンテキストでのGNU timeを理解しましょう。

top‘プロセスのピークメモリ使用量を知りたいとします。 この場合、次のように通知するのは「最大常駐セットサイズ」です。

$ /usr/bin/time -v top | grep "Maximum resident set size"
Maximum resident set size (kbytes): 2252

GNU timeはフォーマットオプションをサポートしています。 メモリ使用量とは別に、%Pオプションを指定したGNU time は、無関係な統計(%CPU)を提供します。これは、スケジューラーに依存するため、非常に変動します。

$ /usr/bin/time -f "%P %M" top
2% 2248

bashでは、/ usr / bin / timeなどのフルパスを指定する必要があります。これは、bashの組み込みtimeキーワードが-fオプションをサポートしていないためです

$ /usr/bin/time -f '%M' top 
2248

また、エイリアスを作成したり、GNU timeを使用して平均および最大のメモリ情報を取得するように環境を調整したりすることもできます。

alias time="$(which time) -f '\t%E real,\t%U user,\t%S sys,\t%K amem,\t%M mmem'"
export TIME="$(which time) -f '\t%E real,\t%U user,\t%S sys,\t%K amem,\t%M mmem'"

メモリセグメントに格納されているこの情報は、プロセスの平均合計(データ+スタック+テキスト)メモリ使用量(K)と最大常駐セットサイズ(M)を表します。

4.1. 議論と考察

time コマンドのファクトチェックを実行して、既知の問題のいくつかについて説明します。

最初の問題は、一部のLinuxシステムでメモリレポートの時間が壊れている可能性があることです。 / usr / bin / time -v ls を使用して「最大常駐セットサイズ」を決定すると、ほとんどの場合、0が返されることがわかります。 timewait3(2)システムコールからほとんどの情報を取得するため、常に0を返します。

wait3(2)コールがないシステムでは、代わりに time(2)システムコールを使用してください。 ただし、 wait3(2)よりもはるかに少ない情報を提供します。 したがって、このようなシステムは、リソースの大部分を0として報告します。

または、CPUを集中的に使用するコマンドを試してみるとうまくいく場合があります。

2番目の問題は、 time -v を呼び出すと、出力「bash:-v:コマンドが見つかりません」は、bashがtimeをインターセプトして独自のビルドを使用することを意味します-time関数で。 / bin / time-vを使用すると問題が解決します。

第三に、GNU時間にはバグがあります。 実際のメモリ使用量の4倍を報告します。 Ubuntu14.4のtime1.7-24およびバージョン1.7-3のFedoraのtimeパッケージには、メモリレポートの修正が組み込まれています。

4.2. ビルトイン時間対。 GNU時間

上記のように、bashでは、GNU time へのフルパスを指定する必要があります(例: / usr / bin / time )。 または、コマンド時間-lを使用することもできます。

コマンドはプレースホルダーではないことに注意してください。 コマンド時間は、時間とは異なります。 コマンドtime-lはシェルを呼び出して、組み込み関数の代わりにtimeと呼ばれるバイナリを呼び出します。

5. Valgrindワンライナー

Valgrind は、ユーザースペースバイナリにインストルメンテーションを提供するフレームワークです。 プログラムのパフォーマンスのプロファイリングと分析に使用できるいくつかのツールが付属しています。

Valgrind ツールの1つであるMassifは、特定のプログラムによって使用されるヒープメモリを測定します。 ‘top‘プロセスのピークメモリ使用量を表す単純なvalgrindmassifワンライナーは次のようになります。

$ valgrind --tool=massif --pages-as-heap=yes --massif-out-file=massif.out top; grep mem_heap_B massif.out | sed -e 's/mem_heap_B=\(.*\)/\1/' | sort -g | tail -n 1
==746== Massif, a heap profiler
==746== Copyright (C) 2003-2017, and GNU GPL'd, by Nicholas Nethercote
==746== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==746== Command: top
==746==
==746== error calling PR_SET_PTRACER, vgdb might block
top - 21:47:03 up 23 min,  0 users,  load average: 0.52, 0.58, 0.59
Tasks:   8 total,   1 running,   6 sleeping,   1 stopped,   0 zombie
%Cpu(s):  2.8 us,  1.9 sy,  0.0 ni, 95.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3961.1 total,	408.3 free,   3328.8 used,	224.0 buff/cache
MiB Swap:  12288.0 total,  12014.8 free,	273.2 used.	501.7 avail Mem

  PID USER  	PR  NI	VIRT	RES	SHR S  %CPU  %MEM 	TIME+ COMMAND
	1 root  	20   0	8940	308	268 S   0.0   0.0   0:00.20 init
	6 root  	20   0	8940	220	180 S   0.0   0.0   0:00.01 init
	7 user1 	20   0   18080   3456   3348 S   0.0   0.1   0:00.27 bash
   72 root  	20   0   18924   2900   2800 S   0.0   0.1   0:00.10 sudo
   73 root  	20   0   18048   2080   2056 S   0.0   0.1   0:00.07 su
   74 root  	20   0   18076   3608   3516 S   0.0   0.1   0:00.41 bash
  366 root  	20   0   18444   1784   1324 T   0.0   0.0   0:00.01 top
  746 root  	20   0   70528  26284   3072 R   0.0   0.6   0:01.24 massif-amd64-li

==746==
15691776

出力15691776は、「top」プロセスのピークメモリ使用量です。

デフォルトでは、Massifはヒープメモリのみを測定します。 ただし、プログラムで使用される all メモリを測定する場合は、— pages-as-heap =yesを使用できます。

Massif は、プロファイリングデータをmassif.outファイルに出力します。 ms_print ツールは、このプロファイリングデータをグラフ化して、プログラムの実行中のメモリ消費量を示します。 また、メモリ割り当てのピーク時に割り当てを担当するサイトに関する詳細情報も表示されます。 次のコマンドを使用して、massif.outファイルのデータをグラフ化できます。

ms_print massif.out

6. その他の最新ツール:HeaptrackとBusybox

Heaptrack は、GUIとテキストの両方のインターフェースを備えたKDEツールです。 フレームグラフとしてピークメモリ使用量を提供します。 Valgrind よりもチェックが少ないため、高速です。

/ proc / [pid] / smaps でPSSの量を追跡するか、 pmap を使用することで、ピークメモリを決定できます。 heaptrackをすでに実行中のプロセスにアタッチすることもできます。

heaptrack --pid $(pid of <your application>)

heaptrack出力は/tmp/heaptrack.APP.PID.gzに書き込まれます。

Busybox は、多くの一般的なUNIXユーティリティの小さなバージョンを1つの小さな実行可能ファイルに結合します。 これは、GNU Coreutils、まで、Linuxなどで通常見られるほとんどのユーティリティの最小限の代替品を提供します。

Busybox は、DebianやUbuntuを含むほとんどのLinuxディストリビューションにプリインストールされています。 最近の多くのディストリビューションにはないコマンドの代わりに使用できます。 同様に、ピークメモリ使用量を知るために、[X58X]-v引数を指定したbusyboxtime実装を使用できます。

$ /usr/bin/time busybox time -v uname -r | grep "Maximum resident set size"
Maximum resident set size (kbytes): 1792

その出力は、GNU time出力に似ています。

7. 結論

この記事では、プロセスのピークメモリ使用量を特定するためのコマンドとツールについて説明しました。

これらのコマンドは、プロセスのメモリ使用率をリアルタイムで視覚化するのに役立ち、必要なアクションを実行できます。 さらに、アプリケーションのメモリ使用量を減らすための測定アクティビティを支援することができます。