الحفر في مشكلة نسخ البيانات البطيئة QEMU

نُشر في 13 أكتوبر 2022

تم دفع تكاليف العمل على QEMU وهذه المقالة بواسطة Determinate Systems ، وتم نشر المقالة بشكل مشترك على مدونة Determinate Systems.

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

كنت أعمل على اختبار VM نسخ قدرًا كبيرًا جدًا من البيانات (حوالي 278000 ملف يبلغ إجماليها 5.3 جيجا بايت تقريبًا) من متجر Nix 9p المثبت ، وقد فوجئت بالمدة التي استغرقتها نسخة من هذه البيانات. على أجهزة NVMe ، أتوقع أن يستغرق هذا بضع ثوانٍ أو دقائق ، لكن الاختبار استغرق في الواقع أكثر من 2 ساعة ، تم قضاء معظمها في نسخ الملفات من 9p. نظرًا لأن هذا لا يمكن الدفاع عنه للعمل الإضافي ، فقد قررت أن أحفر أعمق قليلاً وتمكنت من تقليل وقت الاختبار إلى 7 دقائق فقط. في هذا المقال سوف أصف الرحلة بأكملها.

كمقدمة: ليست لدي خبرة كبيرة في تصحيح أخطاء الأداء! كان معظم ما استخدمته جديدًا بالنسبة لي. أول شيء أردت القيام به هو معرفة أين تم قضاء الكثير من الوقت. أعتقد أنه كان في QEMU وليس ضيفًا ، على الرغم من أن التخمين الصحيح كان مسألة حظ خالص. كان سؤال تجاوز سعة المكدس هذا يصف مشكلة في المقام الأول ولكنها لا تختلف تمامًا عن مشكلتي. قادني هذا إلى المسار الغريب لمحاولة استخدام أداة تعريف الرجل الفقير ، وهي أداة اختراق صغيرة تتكون من gdb و shell و awk.

قصص المفاجآت والفشل: ملف تعريف الرجل الفقير

واجهت على الفور عقبة بسيطة مع هذا النهج. قال gdb:

تحذير: الهدف ومصحح الأخطاء موجودان في مساحات اسم PID مختلفة ؛ ربما تكون قوائم سلاسل الرسائل والبيانات الأخرى غير موثوقة. اتصل بـ gdbserver داخل الحاوية.

يستخدم Nix مساحات أسماء Linux لتوفير إصدارات مع بعض العزلة عن النظام الذي يقوم بتشغيل البنية لتقليل التأثيرات التي يمكن أن تحدثها بيئة جهاز معين على نتيجة الإصدار ("النقاء"). يتضمن هذا مساحات أسماء PID ، والتي تمنع العمليات داخل مساحة الاسم من ملامسة العمليات خارج مساحة الاسم. لم يكن gdb سعيدًا لوجوده في مساحة اسم PID مختلفة عن العملية التي كان يستهدفها! حاولت أولاً الحصول على gdb الخاص بي داخل sandbox باستخدام nsenter. كانت المفاجأة الأولى التي واجهتها هنا هي أن إدخال مساحة اسم PID لا يفرض أدوات procps المساعدة ، مثل ps و pgrep و top ، للإبلاغ عن العمليات داخل مساحة الاسم الجديدة فقط: [الجذر @ البلوط: ~] # pgrep -a qemu 1678991 /nix/store/6shk4z9ip57p6vffm5n9imnkwiks9fsa-qemu-host-cpu-only-for-vm-tests-7.0.0/bin/qemu-kvm [...] [root @ oak: ~] # nsenter - الهدف 1678991 --pid

نُشر في 13 أكتوبر 2022

تم دفع تكاليف العمل على QEMU وهذه المقالة بواسطة Determinate Systems ، وتم نشر المقالة بشكل مشترك على مدونة Determinate Systems.

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

كنت أعمل على اختبار VM نسخ قدرًا كبيرًا جدًا من البيانات (حوالي 278000 ملف يبلغ إجماليها 5.3 جيجا بايت تقريبًا) من متجر Nix 9p المثبت ، وقد فوجئت بالمدة التي استغرقتها نسخة من هذه البيانات. على أجهزة NVMe ، أتوقع أن يستغرق هذا بضع ثوانٍ أو دقائق ، لكن الاختبار استغرق في الواقع أكثر من 2 ساعة ، تم قضاء معظمها في نسخ الملفات من 9p. نظرًا لأن هذا لا يمكن الدفاع عنه للعمل الإضافي ، فقد قررت أن أحفر أعمق قليلاً وتمكنت من تقليل وقت الاختبار إلى 7 دقائق فقط. في هذا المقال سوف أصف الرحلة بأكملها.

كمقدمة: ليست لدي خبرة كبيرة في تصحيح أخطاء الأداء! كان معظم ما استخدمته جديدًا بالنسبة لي. أول شيء أردت القيام به هو معرفة أين تم قضاء الكثير من الوقت. أعتقد أنه كان في QEMU وليس ضيفًا ، على الرغم من أن التخمين الصحيح كان مسألة حظ خالص. كان سؤال تجاوز سعة المكدس هذا يصف مشكلة في المقام الأول ولكنها لا تختلف تمامًا عن مشكلتي. قادني هذا إلى المسار الغريب لمحاولة استخدام أداة تعريف الرجل الفقير ، وهي أداة اختراق صغيرة تتكون من gdb و shell و awk.

قصص المفاجآت والفشل: ملف تعريف الرجل الفقير

واجهت على الفور عقبة بسيطة مع هذا النهج. قال gdb:

تحذير: الهدف ومصحح الأخطاء موجودان في مساحات اسم PID مختلفة ؛ ربما تكون قوائم سلاسل الرسائل والبيانات الأخرى غير موثوقة. اتصل بـ gdbserver داخل الحاوية.

يستخدم Nix مساحات أسماء Linux لتوفير إصدارات مع بعض العزلة عن النظام الذي يقوم بتشغيل البنية لتقليل التأثيرات التي يمكن أن تحدثها بيئة جهاز معين على نتيجة الإصدار ("النقاء"). يتضمن هذا مساحات أسماء PID ، والتي تمنع العمليات داخل مساحة الاسم من ملامسة العمليات خارج مساحة الاسم. لم يكن gdb سعيدًا لوجوده في مساحة اسم PID مختلفة عن العملية التي كان يستهدفها! حاولت أولاً الحصول على gdb الخاص بي داخل sandbox باستخدام nsenter. كانت المفاجأة الأولى التي واجهتها هنا هي أن إدخال مساحة اسم PID لا يفرض أدوات procps المساعدة ، مثل ps و pgrep و top ، للإبلاغ عن العمليات داخل مساحة الاسم الجديدة فقط: [الجذر @ البلوط: ~] # pgrep -a qemu 1678991 /nix/store/6shk4z9ip57p6vffm5n9imnkwiks9fsa-qemu-host-cpu-only-for-vm-tests-7.0.0/bin/qemu-kvm [...] [root @ oak: ~] # nsenter - الهدف 1678991 --pid

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow