مجموعة كبيرة جدا في .NET تسبب استثناء خارج الذاكرة

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

سؤال

أنا أختبر كم يمكن أن تكون المجموعة كبيرة في .NET. من الناحية الفنية ، يمكن أن ينمو أي كائن جمع إلى حجم الذاكرة الفعلية.

ثم اختبرت الكود التالي في Sever ، والذي يحتوي على ذاكرة 16 جيجابايت ، وتشغيل Windows 2003 Server و Visual Studio 2008. لقد اختبرت كل من كود F# و C# ، ونظرت إلى مدير المهام أثناء التشغيل. أستطيع أن أرى أنه بعد زراعة ذاكرة 2GB ، تحطمت البرنامج باستثناء الذاكرة. قمت بتعيين النظام الأساسي المستهدف على X64 في صفحة الممتلكات.

open System.Collections.Generic

let d = new Dictionary<int, int>()

for i=1 to 1000000000 do
    d.Add(i,i)

لقد أجريت نفس الاختبار إلى C5 مكتبة التجميع. والنتيجة هي أن القاموس في C5 يمكن أن يستخدم الذاكرة بأكملها. يستخدم الرمز C5:

let d = C5.HashDictionary<int, int> ()
for i=1 to 1000000000 do
    d.Add(i,i)

أحد يعرف لماذا؟

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

المحلول

يحتوي Microsoft CLR على حد أقصى حجم كائن 2 جيجابايت ، حتى إصدار 64 بت. (لست متأكدًا مما إذا كان هذا الحد موجودًا أيضًا في تطبيقات أخرى مثل Mono.)

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

هناك مناقشة وبعض مثال رمز هنا ...

يبدو أن هناك القليل من الوثائق الرسمية التي تشير إلى هذا الحد. إنه ، بعد كل شيء ، مجرد تفاصيل تنفيذ لـ CLR الحالي. الإشارة الوحيدة التي أدركها هي على هذه الصفحة:

عندما تقوم بتشغيل تطبيق مُدار 64 بت على نظام تشغيل Windows 64 بت ، يمكنك إنشاء كائن لا يزيد عن 2 غيغابايت (GB).

نصائح أخرى

في إصدارات .NET قبل 4.5 ، فإن حجم الكائن الأقصى هو 2 جيجابايت. من 4.5 فصاعدًا ، يمكنك تخصيص كائنات أكبر إذا gcallowverylargeObjects تم تمكين. لاحظ أن الحد string لا يتأثر ، ولكن "المصفوفات" يجب أن تغطي "قوائم" أيضًا ، نظرًا لأن القوائم مدعومة بالمصفوفات.

ولكي نكون واضحين ، يستخدم القاموس صفيفًا واحدًا لإضافة الأزواج. يزرع (مضاعفة؟) في كل مرة يكون ممتلئًا. عندما يكون هناك 512 مليون كائن ، يكون حجمه 2GBYTE (مع مؤشر كائن 32 بت ، وتواصل توزيع مثالي). إضافة عنصر آخر يجعل القاموس يحاول مضاعفة حجم الصفيف مرة أخرى. فقاعة.

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

"السماح للكائنات الكبيرة" سوف يساعد فقط على التخلص من استثناء OOM.

عندما يحتاج المرء إلى تخزين العديد من الكائنات ، فإن المشكلة التي سترىها هي أكشاك GC (توقف مؤقت). ما فعلناه هو "إخفاء" البيانات من GC ، والتي تحولت إلى حل عملي للغاية.

انظر الى هذا: https://www.infoq.com/articles/big-memory-bart-3

يمكنك استخدام ذاكرة التخزين المؤقت التي تعمل كقاموس:https://github.com/aumcode/nfx/tree/master/source/nfx/applicationmodel/pile

انظر قسم التخزين المؤقت

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