コンテナアプリケーションでは、メモリの過剰使用による問題を特定するのが難しいことがあります。メモリ使用量がコンテナの制限を超えると、アプリケーションが痕跡も残さずに静かに失敗する可能性があります。
本記事では、Javaコンテナアプリケーションでメモリ消費の原因を特定するために使用できるいくつかの手法について説明します。
メモリタイプ
典型的なJavaアプリケーションのメモリは、ヒープとノンヒープに大別されます。ヒープメモリは、Javaアプリケーションを起動する際に関連するJVMパラメータを指定することで設定できます。
ノンヒープメモリは、JVM自体や、JNI(Java Native Interface)を使用してアプリケーション内で使用されるライブラリによって使用されるネイティブメモリです。
方法
ヒープメモリの場合、ヒープダンプを取り込んで、ヒープダンプ分析ツールを使用して分析できます。ヒープダンプ分析に最適なツールの1つがeclipseMATです。
Javaは、ネイティブメモリトラッキングを有効にすることで、ネイティブメモリの割り当てを追跡する仕組みを提供していますが、ネイティブライブラリによって割り当てられたすべてのメモリを明らかにするわけではありません。
Jemallocは、ネイティブライブラリによって割り当てられたメモリを追跡するために使用できるユーティリティです。ネイティブメモリは、mallocと呼ばれる既定のメモリ割り当てシステムを使用して割り当てられます。Jemallocは、メモリ割り当ての追跡を有効にできる汎用のmalloc実装です。これは、すべてのネイティブメモリの割り当てを追跡し、ヒーププロファイルのダンプを生成します。
これらのヒーププロファイルは、Jeprofユーティリティを使用して分析できます。Jeprofは、アプリケーション内の関数によって使用されるメモリを強調表示するヒープ割り当てレポートを生成します。
分析
以下は、サンプルコンテナJavaアプリケーションのメモリ分析です。このアプリケーションは、ネイティブメモリの利用を可能にするためにサンプルTensorflowモデルをロードし、Dockerコンテナ内で実行されます。
以下はDockerのメモリ消費量です。254MBです。メモリ消費の原因を突き止めてみましょう。
総メモリ
アプリケーションプロセスによって使用されている総メモリを把握するために、Resident Set Size(RSS)をチェックできます。これは、主メモリまたはRAMに存在する総コミットメモリです。top、ps、pmapなど、これをチェックするための複数のユーティリティがあります。
RSSのチェックで使用状況の根本的な原因を特定するのは難しい。サンプルアプリケーションでは、以下のコマンドを使用すると、合計RSSは376MBでした。
ps --no-header -o rss $(pidof java)
ヒープ分析
以下は、eclipse MATツールによって生成されたヒープメモリの消費量です。総保持ヒープは2.2MBと表示されており、これはDockerによって示された総メモリ消費量よりも大幅に低く、消費の大部分がヒープ以外の領域から来ていることを示しています。
ネイティブメモリ分析
以下のコマンドを使用してネイティブメモリの概要を確認すると、合計メモリ使用量は約99MBのように見えます。しかし、この値は総メモリ消費量よりも少なく、問題の根本的原因を正確に特定していません。
jcmd $(pidof java) VM.native_memory \
| grep -P "Total.*committed=" \
| grep -o -P "(?<=committed=)[0-9]+(?=KB)"
オフヒープメモリ分析
JemallocとJeprofを使用した分析では、ネイティブメモリの使用は主にTensorflowライブラリに帰属し、合計消費量は約112MBでした。
この洞察は、ネイティブメモリ使用の源泉を明確に示しており、過剰な消費を最小限に抑えるためにさらに調査できます。
結論
Javaメモリ分析は、特にコンテナベースのアプリケーションにとって重要です。アプリケーション内のメモリ消費の源泉を知ることで、メモリ要件を理解し、不要な消費を排除することでアプリケーションコストを削減できます。
メモリ消費をチェックする際には、すべてのタイプのメモリとその源泉を特定する必要があります。ヒープダンプ分析はヒープメモリ消費源を特定するのに役立ち、JemallocとJeprofはネイティブメモリ消費源を特定するのに役立ちます。
Sample Application Code Link
Source:
https://dzone.com/articles/java-container-application-memory-analysis