سؤال

أود أن أسأل عن النفقات العامة للذاكرة في Java ، ولدي قائمة كبيرة (61،770 عنصرًا) ، وأحاول حساب مقدار الذاكرة التي يتم أخذها بواسطة كل عنصر (حساب الكائن وإدخال ArrayList الخاص به) ، عن طريق تحديد التنصت على التطبيق بعد تحميل جميع البيانات ، يستغرق الكومة حوالي 25 ميجابايت. عندما يكون لدى ArrayList عن عناصر فقط ، يستغرق الكومة حوالي 1 ميجابايت ، لذلك تقريبًا:

(24*1024*1024)/61،768 = 407 بايت.

ومع ذلك, ، عندما أحسب حقول كل كائن ، أحصل على 148 بايت (لا بما في ذلك قائمة ArrayList ، وأفترض int = 4 ، تعويم = 4 ، مرجع = 4) ، أنا فضولي لمعرفة من أين جاءت كل تلك البايتات الإضافية ...

أستطيع أن أعتقد أنه نظرًا لأن الكائنات التي أقوم بتخزينها في قائمة ArrayList تقوم بتنفيذ واجهة ، فإنها تخزن قيمًا إضافية ، وربما تخزن VM مؤشر وظيفة 4Byte لكل طريقة تم تنفيذها؟ تحتوي الواجهة التي ينفذون عليها على 20 وظيفة ، لذا فإن 80 بايت إضافي ، حيث بلغ مجموعها 228 بايت ، لا تزال غير قريبة من 400 بايت تقاس.

سيكون موضع تقدير أي مساعدة.


واو ، شكرا على كل الإجابات الرائعة.

Polo: شكرًا على الرابط ، مع هذا الفئة ، أقوم بقياس ~ 350 بايت لكل كائن حتى لا يمكنني تأكيد مصدر استخدام الذاكرة الكبير.

yuval A: شكرًا لك على هذا العرض التقديمي ، مصدر قيمة للمعلومات.

@ukko: نقطة لاحظت.

jayan: في الوقت الحالي ، يعطيني NetBeans Profiler أخطاء عندما أحاول تفريغ الكومة ، سيحاول لاحقًا مرة أخرى.

هل كانت مفيدة؟

المحلول

هذه النتائج ليست مفاجئة. يضيف JVM كميات هائلة من النفقات العامة إلى كل كائن.

حول ضعف الحجم المتوقع لكائن واحد ، بسبب النفقات العامة لذاكرة JVM ، ليس من غير المألوف.

هذا العرض لديه شرح رائع ومتعمق وتفسير ونظرة عامة على استخدام ذاكرة بنية البيانات المختلفة في Java.

نصائح أخرى

قائمة ArrayList في الغالب أكبر من عدد العناصر. يستخدم getCapacity() للحصول على الحجم الحالي للصفيف الأساسي.

مشكلة كبيرة في مقاربتك هي التفاعل مع جامع القمامة. إنه يجعل أي اختبار كما اقترحت غير شفاف تمامًا من الخارج.

كتجربة فكرية إذا أردت القيام بذلك ، يجب عليك

  1. قم بإطلاق jvm الخاص بك وقم ببضع GCs عالميين للحصول على كل القمامة
  2. قياس حجم الكومة وفكرة جافا عن مقدار المساحة الحرة التي لديها.
  3. قم بتشغيل الاختبار
  4. GC عدة مرات
  5. أعد القياسات من الخطوة رقم 2

بعد كل ذلك وقليلًا من الرياضيات ، ستكون أقرب ولكن لا تزال غير صحيحة. الحل الحقيقي الوحيد هو أن نسأل في الواقع التنفيذ كما ذكر الآخرين. أو اكتشافها من معرفة التنفيذ.

الذاكرة التي تستهلكها ArrayList غامضة بعض الشيء.

خذ تفريغ الكومة من العملية في المرحلة المناسبة - بعد تعيين القيم بالكامل. ثم استخدم أدوات مثل محلل الذاكرة (من Eclipse).

تملأ العثور على أحجام الكومة الضحلة والاحتفاظ بها.

كملاحظة جانبية ، نظرًا لأنك تعرف بالضبط عدد الكائنات التي ستكون في قائمة ArrayList ، فلماذا لا تستخدم صفيفًا []؟ هل سيتغير عدد الكائنات الموجودة هناك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top