تجنب "خطأ خارج الذاكرة" في Java (Eclipse) ، عند استخدام بنية بيانات كبيرة؟

StackOverflow https://stackoverflow.com/questions/2459972

سؤال

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

يفهرس البرنامج أولاً مجموعة كبيرة من الملفات النصية التي أقدمها. هذا يعمل بشكل جيد.

ثم يستخدم هذا الفهرس لتهيئة صفيف ثنائي الأبعاد كبير. سيكون لهذه المجموعة إدخالات n² ، حيث "N" هو عدد الكلمات الفريدة في مجموعة النص. بالنسبة للجزء الصغير نسبيًا ، أقوم باختباره على (حوالي 60 ملفًا) ، يحتاج إلى جعل حوالي 30،000 × 30،000 إدخالات. من المحتمل أن يكون هذا أكبر بمجرد تشغيله على مجموعة كاملة المقصود أيضًا.

يفشل باستمرار في كل مرة ، بعد فهارسه ، بينما يتم تهيئة بنية البيانات (ليتم العمل عليها لاحقًا).

تشمل الأشياء التي قمت بها:

  • تجديد الكود الخاص بي لاستخدام بدائي int[] بدل من TreeMap
  • القضاء على الهياكل الزائدة ، إلخ ...
  • أيضا ، لقد قمت بتشغيل البرنامج مع-Xmx2g إلى الحد الأقصى من ذاكرتي المخصصة

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

شكرا ، ب.

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

المحلول

يبدو الأمر وكأنه (وضع بعض الافتراضات حول ما تستخدمه صفيفك) سيكون معظم الإدخالات 0. إذا كان الأمر كذلك ، فقد تفكر في استخدام أ مصفوفة متناثرة التمثيل.

إذا كنت حقا لديك أن العديد من الإدخالات (صفيفك الحالي في مكان ما أكثر من 3 جيجابايت بالفعل, ، حتى على افتراض عدم وجود علوم عامة) ، فسيتعين عليك استخدام نوع من التخزين على القرص ، أو نظام التحميل/التفريغ كسول.

نصائح أخرى

هناك عدة أسباب لمشكلات الذاكرة.

أولاً ، أبسط الحالات هي أنك تحتاج ببساطة إلى المزيد من الكومة. أنت تستخدم كومة بحد أقصى 512 مترًا عندما يتمكن البرنامج بشكل صحيح مع 2G. الزيادة مع -Xmx2048m كخيار JVM وأنت بخير. كن على دراية أيضًا من 64 بت VMs ستستخدم ما يصل إلى ضعف ذاكرة VMs 32 بت اعتمادًا على تركيبة تلك البيانات.

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

في نهاية المطاف ، تأتي إلى طرق متقاطعة حيث يتعين عليك الاختيار بين فيلاش و التقسيم.

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

التقسيم يتم تقسيم بياناتك عبر خوادم متعددة (إما حقيقية أو افتراضية). على سبيل المثال ، إذا كنت تتبع صفقات الأسهم في بورصة ناسداك ، فيمكنك وضع رموز الأسهم التي تبدأ بـ "A ON Server1 ،" B "على Server2 ، إلخ أو التخلص من الحاجة إلى التواصل المتبادل لأن هذا التواصل المتبادل هو ما يحد من قابلية التوسع.

حالة بسيطة للغاية ، إذا كان ما تقوم بتخزينه هو 30 ألف كلمة و 30 ألف × 30K من الكلمات التي يمكنك تقسيمها إلى أربعة خادم:

  • أنا س
  • am x nz
  • NZ X AM
  • NZ X NZ

هذه مجرد فكرة واحدة. مرة أخرى ، من الصعب toc omment دون معرفة التفاصيل.

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

إذا لم تكن بحاجة إلى 32 بت كاملة (حجم عدد صحيح) لكل قيمة في صفيفك ثنائي الأبعاد ، فربما يكون النوع الأصغر مثل البايت سيفعل الخدعة؟ كما يجب أن تمنحها أكبر قدر ممكن من مساحة الكومة - لا يزال 2GB صغيرًا نسبيًا لنظام حديث. RAM رخيص ، خاصة إذا كنت تتوقع أن تقوم بالكثير من المعالجة في الذاكرة.

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