أمر git status يزحف فوق SSHFS عبر VPN: انقل العمل
ملف كبير يُنسخ بسرعة بينما يزحف git status. إذا كانت الشجرة على SSHFS عبر VPN، فالكلفة رحلات ذهاب وعودة لكل ملف، لا عرض النطاق. انقل العمل.
انسخ ملفًا بحجم 200 ميغابايت وسيمضي بسرعة. شغّل git status في الدليل نفسه وستطول الانتظار بما يكفي للانتقال إلى مهمة أخرى. هاتان الملاحظتان لا تتناقضان، لأن النقل الكمي يقيس الإنتاجية بينما يقيس Git عدد أسئلة نظام الملفات الصغيرة التي يستطيع طرحها في الثانية، بينما الشجرة البعيدة المثبّتة تحوّل كل سؤال إلى رحلة ذهاب وعودة. ضبط إعدادات VPN لن يصلح عملًا مصممًا بشكل خاطئ.
لماذا يُعدّ status مقياسًا خاطئًا
على Git أن يتعرّف على ملفات كثيرة: أيها معدّل، وأيها غير متعقّب، وهل ما زالت بيانات الفهرس المخزّنة تطابق ما هو موجود على القرص. عبر SSHFS قد تكون كل ملاحظة من هذه عمليات شبكة. وحدة العمل هنا هي عدد الملفات، لا الميغابايتات.
لهذا يكون أول status بعد الاستنساخ بطيئًا، ولهذا قد تكون اللاحقة أبطأ في شجرة مليئة بمخرجات البناء. فمسح الملفات غير المتعقّبة يمشي في أدلة قد لا تهمّك، وكل خطوة مشي هي طلب آخر عبر الرابط. على مسار بزمن 40 ms تصبح شجرة فيها بضعة آلاف من المدخلات بضعة آلاف من الرحلات. ولا حاجة إلى التقاط الحزم لتأكيد هذه الحسابات.
مقياس التنزيل يخبرك أن الرابط جيد؛ لكنه لا يقول شيئًا عن إمكانية انتهاء ألف قراءة صغيرة هذا العصر.
انقل شجرة العمل، لا مقابض الضبط
الاستنساخ المحلي يضع شجرة العمل والفهرس وعمليات Git على الجهاز نفسه. فيصبح السحب خطوة شبكة مرئية بدلًا من أن تصبح كل مراجعة ملف خطوة كذلك.
هذا يناسب كل حالة يستطيع فيها المطوّر الاحتفاظ بالمصدر المطلوب محليًا، وهي معظم الحالات. كما أنه يحدّد حدود الالتزام والنشر بدقة أكبر، لأن تعديل ملف محلي لم يعد يغيّر خدمة بعيدة قيد التشغيل عن غير قصد؛ بل يجب دفع التغيير ونشره كأي شيء آخر. المقابل هو أن الشيفرة موجودة في مكانين، فقرّر أي نسخة هي المرجعية وكيف يعود إصلاح عاجل على الخادم إلى المستودع. تلك المحاورة أرخص من أمر status لا يريد أحد تشغيله.
إذا وجب أن تبقى مساحة العمل بعيدة، فشغّل Git هناك
أحيانًا لا تستطيع مساحة العمل أن تنتقل: البناء يحتاج تلك البيئة، أو البيانات أكبر من أن تُنقل، أو تفرض السياسة بقاء المصدر على المضيف. عندئذ شغّل Git وأدوات التطوير المعنية بجانب الملفات، عبر صدَفة بعيدة معتمدة أو بيئة تطوير بعيدة. ويمكن للمحرّر أن يبقى على الحاسوب المحمول بينما يعمل طرفه الخلفي بجانب شجرة العمل.
تحدث العمليات المكلفة عندئذ محليًا على المضيف البعيد، وتحمل الشبكة حركة المحرّر بدلًا من آلاف نداءات stat. وهو الإصلاح نفسه الذي يقدمه الاستنساخ المحلي، معبّرًا عنه كخيار نشر لا كترحيل.
المزامنة سير عمل له مالكون، لا ذاكرة مخبئية
يمكن لمساحة عمل متزامنة أن تقلّل القراءات البعيدة المتكررة، لكنها ليست ذاكرة مخبئية شفافة. فهي تحتاج مالكًا لكل تغيير، وقاعدة للنزاعات، واتفاقًا على الملفات المولّدة التي يظن الطرفان أنهما يملكانها. وبدون تلك القواعد يخلق الترتيب خلافًا لا راحة.
مزامِن ثنائي الاتجاه بدونها ينتج مشكلة مختلفة عن التي حلّها، وغالبًا دمجًا لا يستطيع أحد نسبته. تجنّب تشغيل عمليتي Git على شجرة عمل مشتركة واحدة إلا إذا فهمت كيف تنسّقان.
ثم اضبط، وأبقِ SSH معقولًا
بعد أن يصبح الترتيب صحيحًا، يغيّر إعدادان عدد الملفات التي على Git أن يسأل عنها: status.showUntrackedFiles والذاكرة المخبئية للملفات غير المتعقّبة خلف core.untrackedCache. لا يغيّر أي منهما كلفة كل سؤال عبر 40 ms؛ إنهما يغيّران فقط عدد الأسئلة. لا تدر مقبضًا إلا بعد أن تصبح الرحلات محلية.
قِس الزمن للأمر الذي يضايقك بدلًا من الاستدلال بمقياس ينسخ ملفًا واحدًا كبيرًا، واترك تشفير SSH المدعوم كما هو. الشيفرة القديمة لا تقصّر رحلة ذهاب وعودة؛ بل تضيف مشكلة ثانية تعمّر أطول من الأولى. مرجع Git status يستحق قراءة واحدة، لأن الأمر يقوم بعمل أكبر بكثير مما يوحي اسمه.