سؤال

لدي 10 خيوط كتابة الآلاف من المخازن المؤقتة الصغيرة (16-30 بايت لكل منهما) إلى ملف ضخم في مواقع عشوائية. بعض الخيوط المرفقة OutofMemoryException على FileStream.Write () Opreation.

ما الذي يسبب outofmemoryException؟ عن ماذا تبحث؟

أنا أستخدم FileTream مثل هذا (لكل عنصر مكتوب - يعمل هذا الرمز من 10 مواضيع مختلفة):

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}

أظن أن جميع المخازن المؤقتة المخصصة داخل FileStream لا تصدر في الوقت المناسب من قبل GC. ما لا أفهمه هو السبب في أن CLR، بدلا من الرمي، لا يدير فقط دورة GC وتحرير كل المخازن المؤقتة غير المستخدمة؟

لا يوجد حل صحيح

نصائح أخرى

إذا كانت هناك عشرة خيوط تفتح ملفات كعروض التعليمات البرمجية الخاصة بك، فستكون لديك عشرة كائنات مغلفة بحد أقصى في أي وقت واحد. نعم، filestream هل لديك المخزن المؤقت الداخلي، وحجم تحددها مع "bigbuffersizeinbytes" في التعليمات البرمجية الخاصة بك. هل يمكن أن تكشف عن القيمة الدقيقة؟ إذا كان هذا كبيرا بما يكفي (على سبيل المثال ~ 100 ميجابايت)، فيمكن أن يكون مصدر المشكلة.

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

ومع ذلك، بالنسبة لتطبيقك المحدد، لن يكون ذلك منطقي للغاية، حيث لن يحتوي المخزن المؤقت المذكور أبدا على أكثر من 16-30 بايت تكتبها قبل أن تتخلص () كائن FileStream.

للإجابة على سؤالك، يتم إلقاء OutofMemoryException إلا عند عدم تخصيص الذاكرة المطلوبة بعد يعمل GC. مرة أخرى، إذا كان المخزن المؤقت كبيرا بالفعل، فقد يكون للنظام الكثير من الذاكرة اليسار، فقط لا مات قطعة. وذلك لأن كومة الكائن الكبير غير مضغوطة أبدا.

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

لقد واجهت هذه المسألة بشكل متكرر إلى حد ما عند القيام به تقريبا ما يكتبه هنا.

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

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

عائلي انتقل للتو ولاحظ "bigbuffersizeinbytes"، وأنا أتميل نحو كائن كائن كبير مرة أخرى ...

إذا كنت أنت، (وهذا صعب للغاية بسبب عدم وجود سياق)، أود أن أقدم إرسال صغير "MBUF"، حيث قمت بنسخ داخل وخارج بدلا من السماح بجميع الخيط المغطى بقراءة فرديا عبر دعمك الكبير Array ... (أي من الصعب عدم التسبب في تخصيصات تمييزية مع بناء جملة رمز SYTILE للغاية).

المخازن المؤقتة ليست مخصصة عموما داخل FileStream. ربما المشكلة هي الخط "كتابة الآلاف من المخازن المؤقتة الصغيرة" - هل تعني ذلك حقا؟ عادة تقوم بإعادة استخدام مخزن مؤقت كثير كثير، عدة مرات (أي على مكالمات مختلفة للقراءة / الكتابة).

أيضا - هل هذا ملف واحد؟ لم يتم ضمان FileStream واحد آمنا للخيط ... لذلك إذا كنت لا تقوم بمزامنة، فنتوقع الفوضى.

من الممكن أن تنشأ هذه القيود من نظام التشغيل الأساسي، وأن إطار .NET غير عاجز عن التغلب على هذه النوع من القيود.

ما لا يمكنني استنتاجي من عينة التعليمات البرمجية هو ما إذا كنت تفتح الكثير من هذه الكائنات FileStream في نفس الوقت، أو افتحها بسرعة حقا بالتسلسل. سيؤدي استخدامك "استخدام" الكلمة الأساسية "إلى إغلاق الملفات بعد مكالمة FS.WRite (). لا توجد دورة GC المطلوبة لإغلاق الملف.

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

تحديث: يبدو أن تعيين الملف الظاهري غير مدعوم رسميا في .NET حتى 4.0. قد ترغب في إلقاء نظرة على تطبيقات الطرف الثالث لهذه الوظيفة.

ديف

أنا أعاني من شيء مماثل وتساءلت عما إذا كنت مثبتا في جذر مشكلتك؟

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

لقد قمت بتتبع المشكلة لأسفل إلى استدعاء FileStream.Write () - عند إخراج هذا الخط، يبدو أن استخدام الذاكرة يذهب كما هو متوقع. بلدي bigbuffersizeinbytes هو الافتراضي (4K)، ولا أستطيع أن أرى في أي مكان حيث يمكن أن يكون هذا جمع ...

أي شيء اكتشفته أثناء وجوده في مشكلتك سيتم استلامها بامتنان!

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