對于容器應用程序來說,很難發現內存過度使用導致的問題。如果使用超過了容器內存限制,應用程序可能會悄無聲息地失敗而不會留下任何痕跡。
在本文中,我將介紹一些可用于識別Java容器應用程序中內存消耗來源的技術。
內存類型
在典型的Java應用程序中,內存可以大致分為堆和非堆。堆內存可以通過在啟動任何Java應用程序時提供相關的JVM參數來設置。
非堆內存由JVM本身使用的本機內存或任何使用JNI (Java本機接口)的應用程序中使用的庫組成。
方法
對于堆內存,可以使用堆轉儲分析工具獲取和分析堆轉儲。用于堆轉儲分析的最佳工具之一是eclipseMAT。
Java通過啟用本機內存跟蹤提供了一種跟蹤本機內存分配的機制,但它可能不會顯示本機庫分配的所有內存。
Jemalloc是一個實用程序,可用于跟蹤本地庫分配的內存。使用名為malloc的默認內存分配器來分配本機內存。Jemalloc是一種通用的malloc實現,使用它可以啟用內存分配跟蹤。它跟蹤所有本機內存分配并生成堆配置文件轉儲。
然后可以使用Jeprof實用程序來分析這些堆配置文件。Jeprof生成堆分配報告,突出顯示應用程序中函數使用的內存。
分析
下面是一個示例容器Java應用程序的內存分析。該應用程序加載一個示例Tensorflow模型以實現本機內存利用率,并在Docker容器中運行。
以下是Docker內存消耗情況,它顯示254MB。讓我們試著找出內存消耗的來源。
總內存
為了了解應用程序進程正在使用的總內存,我們可以檢查常駐集大?。?/span>RSS)。它是駐留在主內存或RAM中的總提交內存。有多個實用程序可以幫助檢查這一點,如top、ps或pmap。
檢查RSS無助于確定使用的根本來源。對于示例應用程序,使用以下命令,總RSS為376MB。
堆積分析
下面是eclipse MAT工具生成的堆內存消耗??偙A舳扬@示為2.2MB,遠低于Docker顯示的總內存消耗,表明大部分消耗來自非堆區域。
本地內存分析
使用以下命令查看本機內存摘要時,總內存使用量似乎約為99MB。但是,該值小于總內存消耗,不能準確識別問題的根本原因。
堆外內存分析
使用Jemalloc和Jeprof進行的分析顯示,本機內存使用主要歸因于Tensorflow庫,總消耗約為112MB。
這種見解清楚地表明了本機內存使用的來源,可以進一步調查以最大限度地減少任何過度消耗。
結論
Java內存分析至關重要,尤其是對于基于容器的應用程序。了解應用程序中內存消耗的來源可以幫助我們了解內存需求,并通過消除不必要的消耗來降低應用程序成本。
檢查內存消耗時,需要查明所有類型的內存及其來源。堆轉儲分析可以查明堆內存消耗源,Jemalloc和Jeprof在查明本機內存消耗源方面非常有用。