Linuxのメモリ使用量を正しく決定する


63

psfreeから見た結果のいくつかで少し混乱しています。

私のサーバーでは、これは次の結果です free -m

[root@server ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          2048       2033         14          0         73       1398
-/+ buffers/cache:        561       1486
Swap:         2047         11       2036

Linuxがメモリを管理する方法についての私の理解は、ディスクの使用量をRAMに保存することであり、その結果、以降の各アクセスがより高速になります。これは「キャッシュされた」列で示されると思います。さらに、さまざまなバッファがRAMに格納され、「バッファ」列に示されます。

したがって、正しく理解すれば、「実際の」使用量は「-/ + buffers / cache」の「使用済み」値、またはこの場合は561であると想定されます。

したがって、すべてが正しいと仮定すると、私を投げるのはの結果ですps aux

ps結果についての私の理解では、6番目の列(RSS)は、プロセスがメモリに使用するサイズをキロバイト単位で表しています。

したがって、このコマンドを実行すると:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

結果は、「-/ + buffers / cache」の「used」列ではありfree -mませんか?

それでは、Linuxでプロセスのメモリ使用量を適切に判断するにはどうすればよいですか?どうやら私のロジックに欠陥があります。


この質問は非常に人気があり、私は私がの答えを共有すべきだと思うhtop...私は他の日だった1つの同様の質問には、著者を(htopのような)は/ proc / meminfoのからメモリ使用量を計算する方法
tgogos

回答:


57

このまったく同じ質問が先日、serverfaultで尋ねられました:-)

Linux仮想メモリシステムはそれほど単純ではありません。すべてのRSSフィールドを加算して、usedによって報告された値を取得することはできませんfree。これには多くの理由がありますが、私はいくつかの最大の理由を見つけます。

  • プロセスが分岐すると、親と子の両方が同じRSSで表示されます。ただし、Linuxではcopy-on-write両方のプロセスが実際に同じメモリを使用するようにしています。プロセスの1つがメモリを変更したときにのみ、実際に複製されます。そのため、このfree数はtopRSSの合計よりも小さくなります。

  • RSS値には共有メモリは含まれません。共有メモリはどのプロセスにも所有されてtopいないため、RSSに含めないでください。そのため、このfree数はtopRSSの合計よりも大きくなります。


1
これは、これまでにスタック交換サイトで得た最高の答えです。具体的には、私が知りたいこと。プロセスのフォークを書いたプログラムを扱っているので、私の状況では特に正確ですが、フットプリントの大部分はそれらが使用するライブラリにあります。
-GoldenNewby

この答えの問題は、RSSとSHRの合計を計算すると、使用されるメモリよりもはるかに少ないことが多いことです。たとえば、私が持っているVPSでは、使用されているメモリは380MBですが、すべてのRSSとSHRの合計は90MBです。
user239558

2
@ user239558答えで述べたように、数字が加算されない多くの理由があり、そのうちの2つだけをリストしました。他にもたくさんの数字があります。キャッシュ、スラブ、巨大なページなど
パトリック

2
おそらくあなたがこれに答えてから数年後、私はまだ(少なくとも)1つの混乱を抱えています。RSS値には共有メモリは含まれていないとおっしゃいましたが、この回答では「共有ライブラリのページが実際にメモリにある限り、共有ライブラリのメモリも含まれます」と答えました。今、私はどちらを信じるべきかわかりません...たぶん私はここでいくつかの微妙な違いを見逃しています
...- Naitree

1
@Naitree "共有ライブラリ"!= "共有メモリ"。共有メモリのようなものですshmgetmmap。メモリに関する言葉遣いは非常に注意が必要です。間違った場所で間違った単語を使用すると、文の意味が完全に台無しになります。
パトリック

30

合計するメモリ番号を探している場合はsmemを見てください

smemは、Linuxシステムでのメモリ使用量に関する多数のレポートを提供できるツールです。既存のツールとは異なり、smemはプロポーショナルセットサイズ(PSS)を報告できます。PSSは、仮想メモリシステム内のライブラリとアプリケーションが使用するメモリ量をより意味のある形で表しています。

通常、物理メモリの大部分は複数のアプリケーション間で共有されるため、常駐セットサイズ(RSS)として知られるメモリ使用量の標準的な尺度では、メモリ使用量が大幅に過大評価されます。代わりに、PSSは、各共有エリアの各アプリケーションの「フェアシェア」を測定して、現実的な測定値を提供します。

以下に例を示します。

# smem -t
  PID User     Command                         Swap      USS      PSS      RSS
...
10593 root     /usr/lib/chromium-browser/c        0    22868    26439    49364 
11500 root     /usr/lib/chromium-browser/c        0    22612    26486    49732 
10474 browser  /usr/lib/chromium-browser/c        0    39232    43806    61560 
 7777 user     /usr/lib/thunderbird/thunde        0    89652    91118   102756 
-------------------------------------------------------------------------------
  118 4                                       40364   594228   653873  1153092 

だから、PSSそれは考慮に共有メモリを要するため、ここで興味深いの列です。それ
とは異なり、RSSそれを加算することは意味があります。ここでは、ユーザーランドプロセスの合計654Mbを取得します。

システム全体の出力は、残りについて通知します。

# smem -tw
Area                           Used      Cache   Noncache 
firmware/hardware                 0          0          0 
kernel image                      0          0          0 
kernel dynamic memory        345784     297092      48692 
userspace memory             654056     181076     472980 
free memory                   15828      15828          0 
----------------------------------------------------------
                            1015668     493996     521672 

そのため、1Gb RAMの合計 = 654Mb ユーザーランドプロセス + 346Mb カーネルメモリ+ 16Mb 空き
(提供または数MB使用)

全体として、メモリの約半分がキャッシュに使用されます(494Mb)。

ボーナス質問:ここでのユーザーランドキャッシュとカーネルキャッシュとは何ですか?


何か視覚的な試みのために

# smem  --pie=name

ここに画像の説明を入力してください


14

本当に良いツールはpmap、特定のプロセスの現在のメモリ使用量をリストするものです:

pmap -d PID

詳細については、manページman pmapを参照してください。また、SysAdminが知っておくべき20のLinuxシステム監視ツールをご覧ください。Linuxボックスに関する情報を取得するために常に使用する優れたツールがリストされています。


これは非常に便利なツールですが、実際には私の問題を解決できません。サーバー上の「実際の」メモリ使用量を効果的に判断する方法を見つけようとしています。
-GoldenNewby

3
@GoldenNewbyプロセスの「実際の」メモリ使用量などはありません。システムの実際のメモリ使用量がfreeわかります。
ジル「SO-悪であるのをやめる」

pmap -x PIDまた、プロセスのRSS合計がどこにあるのかを把握するのに非常に役立つRSS列も含まれます(たとえば、viaからtop来ます)。
maxschlepzig 14

10

topを実行し、ヒットhしてfからフィールドを追加します。次のフィールドを追加できます。

  • RSS アプリケーションが使用している物理メモリの量
  • CODE プロセスの実行可能コードが使用しているメモリの総量
  • DATA -プロセスのデータとスタック専用のメモリの総量(kb)

これら3つの間で、かなり正確な結果が得られるはずです。また、私が推奨するトップhtopまたはに、より詳細な代替品を使用することもできatopます。

編集:本当に詳細な情報が必要な場合、ほとんど忘れていました。PIDを見つけて、次のファイルをcatします。

PID=123

cat /proc/123/status

編集2:あなたがそれを見つけることができるか、本を持っている場合:

Linuxパフォーマンスの最適化:Linuxパフォーマンスツールの実践ガイド

-セクション5章:パフォーマンスツール:プロセス固有のメモリセクションがあります-必要以上の情報があります。


デフォルトでは、Well topにはプロセスのRSSサイズがあります。Topは、私の例の「ps aux」と同じ結果をもたらします。私の質問は、すべてのプロセスの結合RSSが、サーバー全体の「アクティブな」メモリ使用量よりもはるかに多いということです。
-GoldenNewby

5

ps各プロセスが使用するメモリ量を示します。そのメモリの一部は、キャッシュ下でカウントされるmmappedファイルです。そのメモリの一部(特にコード)は他のプロセスと共有されるため、RSS値を合計すると、複数回カウントされます。

「このプロセスが使用するメモリ量」に対する正しい答えはありません。プロセスだけに依存せず、環境にも依存するためです。プロセスの「メモリ使用量」と呼ばれるさまざまな値がありますが、それらは異なるものをカウントしているため一致または合計しません。


4

他の人が正しく指摘しているように、プロセスが使用する実際のメモリ、共有領域のあるもの、mmapされたファイルなどを把握するのは困難です。

あなたが実験者なら、valgrindとmassifを実行できます。これは、カジュアルなユーザーにとっては少し重くなるかもしれませんが、時間の経過に伴うアプリケーションのメモリの振る舞いを知ることができます。アプリケーションのmalloc()がまさに必要なものである場合、これによりプロセスの実際の動的メモリ使用量を適切に表すことができます。しかし、この実験は「中毒」になる可能性があります。

問題を複雑にするために、Linuxではメモリをオーバーコミットできます。メモリをmalloc()すると、メモリを消費する意図が表明されます。しかし、割り当てられた「RAM」の新しいページにバイトを書き込むまで、割り当ては実際には起こりません。次のような小さなCプログラムを作成して実行することで、これを自分で証明できます。

// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    void *p;
    sleep(5)
    p = malloc(16ULL*1024*1024*1024);
    printf("p = %p\n", p);
    sleep(30);
    return 0;
}

# Shell:
cc test.c -o test && ./test &
top -p $!

16GB未満のRAMを搭載したマシンでこれを実行すると、16GBのメモリを獲得しました!(いいえ、そうではありません)。

top「VIRT」は16.004Gと表示されますが、%MEMは0.0 であることに注意してください。

valgrindでこれを再度実行します。

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

そして、massifは「すべてのallocs()の合計= 16GB」と言います。だからそれはあまり面白くない。

ただし、正常なプロセスで実行する場合:

# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30

--------------------------------------------------------------------------------
Command:            cc test.c -o test
Massif arguments:   (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------


    KB
77.33^                                                                       :
     |                                                                      #:
     |                                                                :@::@:#:
     |                                                           :::::@@::@:#:
     |                                                         @:: :::@@::@:#:
     |                                                     ::::@:: :::@@::@:#:
     |                                             ::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                      :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
     |                      :@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |              :@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |          :::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |        :::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
   0 +----------------------------------------------------------------------->Mi
     0                                                                   1.140

そして、ここでは、コンパイラーが77KBのヒープを割り当てていることがわかります(非常に経験的に、非常に高い信頼性で)。

なぜヒープ使用量を取得するために一生懸命努力するのですか プロセスが使用するすべての共有オブジェクトとテキストセクション(この例ではコンパイラー)はそれほど興味深いものではないためです。それらはプロセスの一定のオーバーヘッドです。実際、プロセスの後続の呼び出しはほとんど「無料」で行われます。

また、以下を比較対照します。

MMAP()1GBファイル。VMSizeは1 + GBです。ただし、Resident Set Sizeは、(その領域へのポインターを逆参照することにより)ページングされる原因となったファイルの部分のみです。そして、ファイル全体を「読む」場合、最後に到達するまでに、カーネルはすでにページの先頭をページアウトしている可能性があります(これは簡単に行うことができます。 )。どちらの場合でも、VMSizeもRSSもメモリの「使用量」の良い指標ではありません。実際にmalloc()したものはありません。

対照的に、Malloc()とメモリの多くに触れる-メモリがディスクにスワップされるまで。したがって、割り当てられたメモリはRSSを超えています。ここで、VMSizeが何かを伝え始めるかもしれません(プロセスは実際にRAMにあるメモリよりも多くのメモリを所有しています)。しかし、共有ページであるVMとスワップされたデータであるVMを区別することは依然として困難です。

これは、valgrind / massifが興味深いところです。(ページの状態に関係なく)意図的に割り当てたものを表示します。


質問があります。すべてのmmapされたファイルをmlock()するプロセスがあります。このメモリのどれだけがアクティブに使用されているかを判断する方法はありますか?
マイケルマルティネス

2

これを試してください:MBで実行されているすべてのプロセスで実際に使用される合計RAMが表示されます

ps -eo size,pid,user,command --sort -size | awk '
  { hr=$1/1024 ; printf("%13.2f Mb ",hr) } 
  { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
  ' | awk '{total=total + $1} END {print total}'

size報告されたps実際のメモリ使用量にはほとんど関係を持っています。必ずしもメモリが割り当てられるとは限らないのは、各プロセスの仮想サイズです。また、割り当てられている一部のセグメントも含まれていません。
マット

-2

ユーザーごとのメモリ量が表示されます。

#!/bin/bash
total_mem=0

printf "%-10s%-10s\n" User MemUsage

while read u m
do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;
                                    total_mem=0; }
        total_mem="$(echo $m + $total_mem | bc)"
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)

#EOF

-3

このコマンドを使用して、メモリ使用率を%で検索します。

使用メモリ:

grep Mem | awk '{print $3/$2 * 100.0}'

空きメモリ

grep Mem | awk '{print $4/$2 * 100.0}'

3
エラー、これは何もしません。grepただそこに座って入力を待っています。
mattdm

1
これは、はずだったはずですfree -m | grep Mem | awk '{print $3/$2 * 100.0}'
-vjangus
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.