windows - كيفية الحصول على أداء قراءة متزامن جيد من القرص




multithreading file-io (4)

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

أود أن أطرح سؤالًا ثم أتبعه بإجابتي الخاصة ، ولكن أيضًا انظر ما هي الإجابات التي يمتلكها الآخرون.

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

تجربتنا مع هذا الإعداد على ويندوز سيئة للغاية. الإنتاجية المشتركة للخيوط اثنين في ترتيب 2-3 MiB / ثانية. يبدو أن محرك الأقراص يقضي معظم وقته في البحث عن الخلف وإلى الأمام بين الملفين ، ويفترض أنه يقرأ القليل بعد كل محاولة.

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

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

بعض التفاصيل:

الملفات في ترتيب 2 GiB على كل جهاز مع 2 غيغابايت من ذاكرة الوصول العشوائي. لغرض هذا السؤال ، نعتبرها غير قابلة للتخزين المؤقت والتجزئة تمامًا. لقد استخدمنا أدوات defrag وتم إعادة تشغيلها للتأكد من أن هذه هي الحالة.

لا نستخدم واجهات برمجة تطبيقات خاصة لقراءة هذه الملفات. السلوك قابل للتكرار عبر العديد من واجهات برمجة التطبيقات القياسية ، مثل Win32's CreateFile ، C fopen ، C ++ 's std :: ifstream ، Java FileInputStream ، إلخ.

يدور كل مؤشر ترابط في حلقة إجراء مكالمات إلى وظيفة القراءة. لقد قمنا بتغيير عدد وحدات البايت المطلوبة من API كل عملية تكرار من القيم بين 1KiB حتى 128MiB. لم يكن هناك أي تأثير لذلك ، لذا فمن الواضح أن المبلغ الذي يقرأه نظام التشغيل فعليًا بعد كل طلب قرص لا يحدده هذا الرقم. هذا هو بالضبط ما ينبغي توقعه.

إن الفرق الدراماتيكي بين أداء الخيط الواحد ومؤشر الترابط هو متكرر عبر Windows 2000 ، و Windows XP (32 بت و 64 بت) ، و Windows Server 2003 ، وأيضًا مع الجهاز RAID5 أو بدونه.


أود إضافة بعض الملاحظات الإضافية في ردي. جميع أنظمة التشغيل الأخرى غير Microsoft التي اختبرناها لا تعاني من هذه المشكلة. يتناقص كل من Linux و FreeBSD و Mac OS X (هذا الأخير على أجهزة مختلفة) بأمان أكبر من حيث عرض النطاق الترددي الكلي عند الانتقال من مؤشر ترابط إلى آخر. على سبيل المثال ، تراجعت لينكس من ~ 45 ميجابت / ثانية إلى ~ 42 ميجابت / ثانية. يجب أن تكون أنظمة التشغيل الأخرى هذه تقرأ أجزاء أكبر من الملف بين كل طلب ، وبالتالي لا تقضي كل وقتهم في انتظار البحث عن القرص.

الحل الخاص بنا لـ Windows هو تمرير FILE_FLAG_NO_BUFFERING إلى CreateFile واستخدام كبير (~ 16 ميغا بايت) يقرأ في كل استدعاء ReadFile . هذا هو دون المستوى الأمثل لعدة أسباب:

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

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

عدل لإضافة المزيد من التفاصيل عن Will Dean:

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

  • العديد من محطات العمل من Dell (Intel Xeon) من مختلف الأعمار التي تعمل بنظام Windows 2000 و Windows XP (32 بت) و Windows XP (64 بت) مع محرك أقراص واحد.
  • خادم Dell 1U (Intel Xeon) يعمل بنظام التشغيل Windows Server 2003 (64 بت) مع RAID 1 + 0.
  • محطة عمل HP (AMD Opteron) مع Windows XP (64 بت) و Windows Server 2003 والأجهزة RAID 5.
  • جهاز الكمبيوتر المنزلي بدون علامة تجارية (AMD Athlon64) يعمل بنظام التشغيل Windows XP (32 بت) و FreeBSD (64 بت) و Linux (64 بت) مع محرك واحد.
  • My Home MacBook (Intel Core1) يعمل بنظام Mac OS X ، محرك أقراص SATA واحد.
  • بيتي Koolu كمبيوتر يعمل بنظام Linux. قوّة ضعيفة مقارنةً بالأنظمة الأخرى ، لكنني أثبتت أن هذا الجهاز يمكن أن يتفوق على خادم Windows باستخدام RAID5 عند قراءة الأقراص متعددة الخيوط.

كان استخدام وحدة المعالجة المركزية على جميع هذه الأنظمة منخفضًا جدًا أثناء الاختبارات وتم تعطيل مكافحة الفيروسات.

لقد نسيت أن أذكر من قبل ولكن حاولنا أيضا Win32 CreateFile API العادي مع مجموعة FILE_FLAG_SEQUENTIAL_SCAN . هذه العلامة لم تحل المشكلة.



يبدو أن المشكلة في نهج جدولة Windows I / O. وفقا لما وجدته here هناك العديد من الطرق لنظام التشغيل لجدولة طلبات القرص. في حين أن Linux وغيرهم يمكنهم الاختيار بين السياسات المختلفة ، قبل أن يتم تثبيت Windows Vista في نهج واحد: قائمة انتظار FIFO ، حيث يتم حظر كافة الطلبات التي تم تقسيمها في 64 كيلو بايت. أعتقد أن هذه السياسة هي سبب المشكلة التي تواجهها: سيقوم المجدول بخلط الطلبات من السائرين ، مما يؤدي إلى السعي المستمر بين مناطق مختلفة من القرص.
الآن ، والخبر السار هو أنه وفقا لهذا here here ، قدم فيستا جدولة قرص أكثر ذكاء ، حيث يمكنك تعيين أولوية طلباتك وأيضا تخصيص الحد الأدنى من badwidth للعملية الخاصة بك.
الأخبار السيئة هي أنني لم أجد طريقة لتغيير سياسة القرص أو حجم المخازن المؤقتة في الإصدارات السابقة من Windows. بالإضافة إلى ذلك ، حتى إذا كان رفع أولوية الإدخال / الإخراج على القرص في العملية الخاصة بك سيعزز الأداء مقارنةً بالعمليات الأخرى ، فلا تزال تواجه مشاكل مؤشرات الترابط الخاصة بك المنافسة بعضها مع بعض.
ما يمكنني اقتراحه هو تعديل البرنامج الخاص بك عن طريق إدخال سياسة الوصول للقرص ذاتيًا.
على سبيل المثال ، يمكنك استخدام سياسة مثل هذه في مؤشر الترابط B (مشابه للخيوط A):

if THREAD A is reading from disk then wait for THREAD A to stop reading or wait for X ms
Read for X ms (or Y MB)
Stop reading and check status of thread A again  

يمكنك استخدام الإشارات المرجعية لفحص الحالة أو يمكنك استخدام عدادات perfmon للحصول على حالة قائمة انتظار القرص الفعلي. يمكن أيضًا ضبط قيم X و / أو Y تلقائيًا عن طريق التحقق من معدّلات trasfer الفعلية وتعديلها ببطء ، وبالتالي تعظيم عملية النقل أثناء تشغيل التطبيق على أجهزة مختلفة و / أو نظام التشغيل يمكنك العثور على ذاكرة التخزين المؤقت أو الذاكرة أو مستويات RAID تؤثر عليهم بطريقة أو أخرى ، ولكن مع الضبط التلقائي ، ستحصل دائمًا على أفضل أداء في كل سيناريو.





file-io