تحليل ذاكرة التطبيقات المحبورة في Java

لأجهزة الحاوية، من الصعب العثور على المشاكل الناجمة عن استخدام الذاكرة المفرط. في حالة الاستخدام يتجاوز حدود ذاكرة الحاوية، يمكن أن تفشل التطبيق سراً دون ترك أي أثر.

في هذا المقال، سأقوم بمراجعة بعض التقنيات التي يمكن استخدامها لتحديد مصدر استهلاك الذاكرة في تطبيق حاوية Java.

نوع الذاكرة

في تطبيق Java نموذجي، الذاكرة يمكن تقسيمها بشكل واسع إلى كومة وغير كومة. يمكن تحديد ذاكرة الكومة من خلال توفير المعلمات المتعلقة بـ JVM عند بدء أي تطبيق Java.

تتألف ذاكرة غير الكومة من الذاكرة الأصلية المستخدمة من قبل JVM نفسه أو أي مكتبة مستخدمة في التطبيق باستخدام JNI (Java Native Interface).

طريقة

بالنسبة لذاكرة الكومة، يمكن أخذ فصل كومة وتحليله باستخدام أدوات تحليل فصل كومة. إحدى أفضل الأدوات لتحليل فصل كومة هي اكسبلر MAT.

يوفر Java آلية لتتبع تخصيص الذاكرة الأصلية عن طريق تمكين تتبع الذاكرة الأصلية، ولكن قد لا يكشف عن كل الذاكرة التي تم تخصيصها من قبل المكتبات الأصلية.

Jemalloc هو أداة يمكن استخدامها لتتبع الذاكرة المخصصة من قبل المكتبات الأصلية. الذاكرة الأصلية يتم تخصيصها باستخدام معالج تخصيص الذاكرة افتراضي يسمى malloc. Jemalloc هو تنفيذ malloc للغاية العامة يمكن تمكين تتبع تخصيص الذاكرة به. يتتبع كل تخصيص الذاكرة الأصلية ويولد فصول فراغ تفاصيل الحمل.

يمكن بعد ذلك تحليل هذه الملفات الشخصية للفراغ باستخدام أداة Jeprof. تولد Jeprof تقرير تخصيص الفراغ، مما يسلط الضوء على الذاكرة المستخدمة من قبل الوظائف في التطبيق.

تحليل

أدناه هو تحليل الذاكرة لعينة من حاوية تطبيق Java. يقوم التطبيق بتحميل نموذج عينة Tensorflow لتمكين استخدام الذاكرة الأصلية ويعمل داخل حاوية Docker.

أدناه هو استهلاك ذاكرة Docker. يظهر 254MB. دعونا نحاول تحديد مصدر استهلاك الذاكرة.

الذاكرة الإجمالية

للحصول على فكرة عن الذاكرة الإجمالية التي يستخدمها عملية التطبيق، يمكننا التحقق من حجم المجموعة السكنية (RSS). إنها الذاكرة المُلزمة الإجمالية التي تقع في الذاكرة الرئيسية أو ذاكرة الوصول العشوائي. هناك عدة وكلاء يمكن أن تساعد في التحقق من هذا مثل top, ps أو pmap.

فحص RSS لا يساعد في تحديد مصدر الاستخدام الجذري. بالنسبة للتطبيق العينة، باستخدام الأمر التالي، يكون ال RSS الإجمالي 376MB.

Shell

 

ps --no-header -o rss $(pidof java)

تحليل الكومة المخصصة

الآتي هو استهلاك ذاكرة الكومة كما تم إنتاجه بواسطة أداة مات في إكسابل. يظهر استهلاك الكومة المحتظرة إجمالاً 2.2 ميغابايت، وهو أقل بكثير من استهلاك الذاكرة الإجمالي المبين بواسطة Docker ويشير إلى أن معظم الاستهلاك من المنطقة الغير الكومية.

تحليل الذاكرة الطبيعية

بعد مراجعة ملخص الذاكرة الطبيعية باستخدام الأمر التالي، يبدو استهلاك الذاكرة الإجمالي تقريباً 99 ميغابايت. ومع ذلك، هذه القيمة أقل من استهلاك الذاكرة الإجمالي ولا تحدد بدقة مشكلة الجذر.

Shell

 

jcmd $(pidof java) VM.native_memory \
    | grep -P "Total.*committed=" \
    | grep -o -P "(?<=committed=)[0-9]+(?=KB)"

تحليل الذاكرة الخارجية الكومة

أظهر تحليل باستخدام Jemalloc و Jeprof أن استخدام الذاكرة الطبيعية يعزى بشكل أساسي إلى مكتبة Tensorflow، مع استهلاك إجمالي تقريباً 112 ميغابايت.

يوفر هذا الرؤية مؤشراً واضحاً على مصدر استخدام الذاكرة الطبيعية ويمكن تحقيقه أكثر لتقليل أي استهلاك مفرط.

الخاتمة

تحليل ذاكرة الجافا أمر حيوي، خاصة للتطبيقات الموزعة بواسطة الحاويات. معرفة مصدر استهلاك الذاكرة في تطبيق يمكن أن يساعدنا على فهم متطلبات الذاكرة وخفض تكاليف التطبيق عن طريق إزالة الاستهلاك غير الضروري.

عند فحص استهلاك الذاكرة، يجب تحديد جميع أنواع الذاكرة ومصادرها. تحليل فصل الكومة يمكن أن يحدد مصادر استهلاك ذاكرة الكومة، و Jemalloc و Jeprof مفيدان في تحديد مصادر استهلاك الذاكرة الطبيعية.

رابط كود التطبيق العينة

https://github.com/parveensaini/JavaContainerMemoryAnalysis

Source:
https://dzone.com/articles/java-container-application-memory-analysis