سؤال

أنا بناء لعبة قاعدة البيانات في C# لمعرفة المزيد عن مترجم, محسن, و الفهرسة التكنولوجيا.

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

وهنا بعض الخيارات و المشاكل التي كنت تأتي عبر مع بعضها:

  1. استخدام System.IO.FileStream و BeginRead طريقة

    ولكن الموقف في الملف ليس حجة BeginRead, هو خاصية من FileStream (مجموعة عبر Seek طريقة) ، لذلك لا يسعني إلا أن مسألة طلب واحد في كل مرة و نقفل تيار مدة.(أم أنا ؟ الوثائق هو واضح على ما يمكن أن يحدث إذا عقدت القفل فقط بين Seek و BeginRead المكالمات ولكن أفرج عنه قبل الاتصال EndRead.لا أحد يعرف؟) أنا أعرف كيف أفعل هذا, أنا فقط لم تكن متأكدا فإنه هو أفضل وسيلة.

  2. يبدو أن هناك طريقة أخرى ، تتمحور حول System.Threading.Overlapped هيكل P\تحتج إلى ReadFileEx وظيفة في kernel32.dll.

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

  3. شيء آخر ؟

  4. في تعليق يعقوب يشير إلى خلق جديد FileStream لكل قراءة في الرحلة.

  5. قراءة كامل الملف في الذاكرة.

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

تحرير

توضيح لماذا أنا المشبوهة مع الحل 1:عقد واحد قفل على طول الطريق من BeginRead إلى EndRead يعني أنني بحاجة إلى كتلة من يريد الشروع في قراءة لمجرد قراءة آخر هو في التقدم.يبدو خاطئ لأن الموضوع الشروع في قراءة جديدة قد تكون قادرة على (بشكل عام) أن تفعل المزيد من العمل قبل أن تصبح النتائج متاحة.(في الواقع, فقط كتابة هذا أدى بي إلى التفكير في حل جديد, أنا وضعت إجابة جديدة.)

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

المحلول

ما فعلناه كان يكتب طبقة صغيرة حول إكمال الإدخال/الإخراج الموانئ طلب & readfile ، GetQueuedCompletion الوضع في C++/CLI, ومن ثم الاتصال مرة أخرى في C# عندما أكملت العملية.اخترنا هذا الطريق أكثر من BeginRead و c# المتزامن نمط التشغيل إلى تقديم المزيد من السيطرة على مخازن تستخدم للقراءة من الملف (أو مقبس).هذا كان كبير جدا كسب الأداء على بحتة تمكنت النهج الذي يخصص new byte[] على كومة مع كل قراءة.

بالإضافة إلى أن هناك الكثير أكثر اكتمالا C++ أمثلة على استخدام IO الانتهاء الموانئ على interwebs

نصائح أخرى

أنا لست متأكدا من أنني أرى لماذا الخيار 1 لن تعمل من أجلك.نضع في اعتبارنا أن كنت لا يمكن أن يكون اثنين من المواضيع المختلفة تحاول استخدام نفس FileStream في نفس الوقت القيام بذلك بالتأكيد سوف يسبب لك المشاكل.BeginRead/EndRead المفترض أن اسمحوا الخاص بك رمز مواصلة تنفيذ في حين يحتمل أن تكون مكلفة IO العملية تستغرق أماكن لا لتمكين نوعا من متعدد الخيوط الوصول إلى ملف.

لذلك أود أن أقترح عليك أن تسعى ومن ثم القيام beginread.

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

استخدام النهج #1, ولكن

  1. عندما يأتي الطلب ، واتخاذ قفل A.استخدامه لحماية طابور انتظار قراءة الطلبات.إضافة إلى انتظار عودة بعض المتزامن النتيجة.إن هذه النتائج في أول بالإضافة إلى انتظار استدعاء الخطوة 2 قبل العودة.الافراج عن قفل قبل العودة.

  2. عندما يكمل قراءة (أو ما يسمى بخطوة 1), تأخذ قفل A.استخدامه لحماية ظهرت طلب قراءة من الانتظار.تأخذ قفل B.استخدامه لحماية Seek -> BeginRead -> EndRead التسلسل.الافراج عن قفل B.التحديث المتزامن النتيجة التي أنشأتها الخطوة 1 من أجل هذه العملية.(منذ عملية قراءة الانتهاء نسمي هذا مرة أخرى.)

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

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