41

通常、ヒープまたは permgen サイズの構成の問題により、OutOfMemoryError の問題に対処します。

ただし、すべての JVM メモリが permgen またはヒープではありません。私が理解している限り、それはスレッド/スタック、ネイティブ JVM コードにも関連している可能性があります...

しかし、pmap を使用すると、3.3G のオフヒープ メモリ使用量である 9.3G がプロセスに割り当てられていることがわかります。

この余分なオフヒープ メモリの消費を監視および調整する可能性はあるのでしょうか。

オフヒープ メモリへの直接アクセスは使用しません (MaxDirectMemorySize はデフォルトで 64m です)。

Context: Load testing
Application: Solr/Lucene server
OS: Ubuntu
Thread count: 700
Virtualization: vSphere (run by us, no external hosting)

JVM

java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)

チューニング

-Xms=6g
-Xms=6g
-XX:MaxPermSize=128m

-XX:-UseGCOverheadLimit
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSClassUnloadingEnabled

-XX:+OptimizeStringConcat
-XX:+UseCompressedStrings 
-XX:+UseStringCache 

メモリ マップ:

https://gist.github.com/slorber/5629214

vmstat

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 1  0   1743    381      4   1150    1    1    60    92    2    0  1  0 99  0

自由

             total       used       free     shared    buffers     cached
Mem:          7986       7605        381          0          4       1150
-/+ buffers/cache:       6449       1536
Swap:         4091       1743       2348

top - 11:15:49 up 42 days,  1:34,  2 users,  load average: 1.44, 2.11, 2.46
Tasks: 104 total,   1 running, 103 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.5%us,  0.2%sy,  0.0%ni, 98.9%id,  0.4%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   8178412k total,  7773356k used,   405056k free,     4200k buffers
Swap:  4190204k total,  1796368k used,  2393836k free,  1179380k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                 
17833 jmxtrans  20   0 2458m 145m 2488 S    1  1.8 206:56.06 java                                                                                                                                    
 1237 logstash  20   0 2503m 142m 2468 S    1  1.8 354:23.19 java                                                                                                                                    
11348 tomcat    20   0 9184m 5.6g 2808 S    1 71.3 642:25.41 java                                                                                                                                    
    1 root      20   0 24324 1188  656 S    0  0.0   0:01.52 init                                                                                                                                    
    2 root      20   0     0    0    0 S    0  0.0   0:00.26 kthreadd             
...

df -> tmpfs

Filesystem                1K-blocks     Used Available Use% Mounted on
tmpfs                       1635684      272   1635412   1% /run

私たちが抱えている主な問題:

  • サーバーには 8G の物理メモリがあります
  • Solr のヒープは 6G しか必要としません
  • 1.5Gのスワップがあります
  • スワップネス=0
  • ヒープ消費量は適切に調整されているようです
  • サーバー上で実行: Solr といくつかの監視機能のみ
  • 正確な平均応答時間があります
  • ときどき異常に長い一時停止があり、最大 20 秒です

一時停止は、スワップされたヒープでの完全な GC である可能性があると思いますか?

なぜそんなにスワップがあるのですか?

これがサーバーをスワップさせるJVMなのか、それとも私には見えない隠されたものなのか、私にはよくわかりません。おそらくOSのページキャッシュ?しかし、それがスワップを作成する場合、OS がページ キャッシュ エントリを作成する理由がわかりません。

mlockallElasticSearch、Voldemort、Cassandra などの一般的な Java ベースのストレージ/NoSQL で使用されているトリックをテストすることを検討しています: Make JVM/Solr not swap, using mlockall をチェックします。


編集:

ここでは、最大ヒープ、使用済みヒープ (青)、使用済みスワップ (赤) を確認できます。なんか関係ありそう。

スワップとヒープ

Graphite では、多くの ParNew GC が定期的に発生していることがわかります。また、画像の大幅なヒープの減少に対応する CMS GC がいくつかあります。

一時停止はヒープの減少と相関しているようには見えませんが、10:00 から 11:30 の間に定期的に分散されているため、ParNew GC に関連している可能性があります。

ロード テスト中、ディスク アクティビティとスワップ IO アクティビティが見られますが、テストが終了すると非常に落ち着いています。

4

4 に答える 4

11

ヒープは実際に 6.5 GB の仮想メモリを使用しています (これには perm gen が含まれる場合があります)

64 MB のスタックを使用するスレッドが多数あります。デフォルトの 1 MB を使用している人もいれば、使用している人もいる理由は明らかではありません。

合計は 930 万 KB の仮想メモリです。私は居住者のサイズだけを心配します。

topプロセスの常駐サイズを見つけるために使用してみてください。

このプログラムは役に立つかもしれません

    BufferedReader br = new BufferedReader(new FileReader("C:/dev/gistfile1.txt"));
    long total = 0;
    for(String line; (line = br.readLine())!= null;) {
        String[] parts = line.split("[- ]");
        long start = new BigInteger(parts[0], 16).longValue();
        long end = new BigInteger(parts[1], 16).longValue();
        long size = end - start + 1;
        if (size > 1000000)
            System.out.printf("%,d : %s%n", size, line);
        total += size;
    }
    System.out.println("total: " + total/1024);

メモリを使用する JNI ライブラリがない限り、それぞれ独自のスタック スペースを持つスレッドがたくさんあると思います。私はあなたが持っているスレッドの数をチェックします。スレッドごとの最大スタック スペースを減らすことはできますが、スレッドの数を減らすことをお勧めします。

オフ ヒープ メモリは定義上、管理されていないため、そのように簡単に "調整" することはできません。ヒープの調整も簡単ではありません。

64 ビット JVM のデフォルトのスタック サイズは 1024K であるため、700 のスレッドが 700 MB の仮想メモリを使用します。

仮想メモリのサイズと常駐メモリのサイズを混同しないでください。64 ビット アプリケーションの仮想メモリはほとんど無料で、気にする必要があるのは常駐サイズだけです。

私の見方では、合計で 9.3 GB あります。

  • 6.0 GB ヒープ。
  • 128 MB パーマ生成
  • 700 MB スタック。
  • < 250 の共有ライブラリ
  • 2.2 GB の不明 (常駐メモリではなく仮想メモリと思われます)

前回この問題が発生したとき、必要以上に多くのスレッドがありました。仮想サイズを決定するのはピークであるため、スレッドの最大数を確認します。たとえば、3000に近かったですか?


うーん、これらのペアのそれぞれがスレッドです。

7f0cffddf000-7f0cffedd000 rw-p 00000000 00:00 0 
7f0cffedd000-7f0cffee0000 ---p 00000000 00:00 0

これらは、現在 700 スレッドをわずかに下回っていることを示しています.....

于 2013-05-22T16:49:10.387 に答える