يقوم Golang بتعطيل خوارزمية Nagle افتراضيًا

تبدأ هذه المغامرة بـ git-lfs. لقد كان يومًا عاديًا وأضفت أصلًا ثنائيًا بسعة 500 ميجابايت إلى قوالب الخادم الخاص بي. عندما ذهبت لدفعه ، وجدت أنه من المثير للاهتمام أن git-lfs كان يتم تنزيله بسرعة 50 كيلوبايت في الثانية. نظرًا لأن لدي بعض وقت الفراغ الذي أفضل إنفاقه على شيء آخر غير انتظار تنزيل ملف دائمًا ، فقد قررت الصعود إلى الطابق العلوي والاتصال بشبكة إيثرنت. شاهدته على الفور يقفز بسرعة تصل إلى 2.5 ميغا بايت في الثانية. ما زلت غير سريع جدًا ، لكنني الآن فضولي بشدة.

نظرًا لأنني اعتقدت أنني كنت سأنتظر دائمًا حتى يتم نشر هذا ، قررت استخدام هذا الوقت والتحقيق في ما كان يحدث. على الرغم من أنني أتوقع أن تكون شبكة إيثرنت السلكية أسرع قليلاً من شبكة wifi ، إلا أنني لم أتوقع أن تكون الأوامر (مع s) أسرع من حيث الحجم. فقط للتحقق من سلامة عقلي ، أجريت اختبار سرعة ورأيت سرعة التنزيل عبر شبكة Wi-Fi بسرعة 40 ميجابايت في الثانية وسلكيًا بسرعة 60 ميجابايت في الثانية.

بعد إجراء بعض الأبحاث باستخدام WireShark وأدوات أخرى ، علمت أن قنوات Wi-Fi الخاصة بي بها الكثير من التداخل في النطاق 2 غيغاهرتز ، وقليلًا في النطاق 5 غيغاهرتز. خلال هذا الوقت ، علمت أيضًا أن جهاز التوجيه الخاص بي لن يقبل عميلًا واحدًا بسرعة 5 جيجاهرتز بسبب التهيئة الخاطئة من جانبي. لذلك كان تمكين "وقت الاستيقاظ المستهدف" غير المتسلسل ، على ما يبدو مهمًا للغاية (ليس لدي أي فكرة عما يفعله ذلك). بمجرد إصلاح ذلك ، رأيت 600 ميجابايت في الثانية على شبكتي الداخلية ، وكان معدل النقل الخارجي هو نفسه تقريبًا مثل السلكي.

لكن ، لماذا كانت بوابة git-lfs بطيئة جدًا ، حتى على 5 جيجا هرتز؟ بعد النظر إلى Wireshark أثناء التحميل إلى git-lfs ، لاحظت أن حوالي 30-50 ٪ من حركة المرور كانت معطلة / مزدوجة ACK مما تسبب في إعادة الإرسال. لقد وجدتها غريبة بشكل خاص ، وليست غريبة بشكل رهيب لأن تذكر أن شبكة wifi هذه "تمتص" مع جميع جيراني المزعجين. تبين أن هناك تأخيرًا عشوائيًا من 50 إلى 100 مللي ثانية في كل مكان. ربما بسبب التدخل. ومع ذلك ، عندما أجريت اختبار سرعة أو جلسة تصفح ، كانت أقل من 1٪! في الواقع ، لم يكن git-lfs يرسل أي حزم تقريبًا ، كما لو كان عالقًا إلى الأبد في البداية البطيئة لبروتوكول TCP.

 رسم بياني يوضح الحزم في الثانية (الإجمالي) وأخطاء الحزمة لـ git-lfs

عندما ألقيت نظرة على الحزم ، تم إرسالها في قطع حمولة 50 بايت تقريبًا (إجمالي 100 بايت تقريبًا ، MTU هو 1500). لقد وجدت هذا مثيرًا للاهتمام لأنني أتوقع أن تقوم خوارزمية Nagle بدمج الحزم بحيث يكون هناك عدد أقل من الحزم المادية لإرسالها. هذا عندما حدث لي ، يجب تعيين TCP_NODELAY.

بين هذا والتأخيرات العادية للغاية التي تصل إلى 100 مللي ثانية ، يمكنها فقط استخراج بضع حزم قبل الحصول على "حزمة مفقودة" ، ناهيك عن أن ما يقرب من 50٪ من كل حزمة كانت عبارة عن رؤوس حزم حرفيًا. لقد كنت عالقًا بشكل دائم في برنامج TCP Slow Start.

TCP بدون تأخير من الذاكرة

تمت كتابة خوارزمية Nagle منذ حوالي 4 عقود لحل مشكلة "microgram" ، حيث ترسل مجموعة كاملة من الحزم الصغيرة ، وإغراق الشبكة ، وتقليل إنتاجية الشبكة. تجمع خوارزمية Nagle بشكل أساسي جميع الحزم الصغيرة في حزمة واحدة كبيرة ، في انتظار إنشاء ACK أو حزمة كاملة ، أيهما يأتي أولاً.

نظريًا

C'est un peu plus complexe que cela en raison de décennies de changements pour rendre le Web meilleur et plus performant... mais activer TCP_NODELAY signifierait que chacun de ces 50 octets est envoyé en un seul paquet au lieu de quelques paquets أضخم. يؤدي هذا إلى زيادة حمل الشبكة ، وعندما تكون هناك فرصة لإعادة إرسال الحزمة ، سترى العديد من عمليات إعادة الإرسال.

إذا كنت تريد معرفة المزيد ، فاستخدم Google

الغوص في الكود

من هناك انتقلت إلى قاعدة كود git-lfs. لم أر أي مكالمة لـ setNoDelay وعندما نظرت إليها قالت إنها كانت الافتراضي. في الواقع:

يقوم Golang بتعطيل خوارزمية Nagle افتراضيًا

تبدأ هذه المغامرة بـ git-lfs. لقد كان يومًا عاديًا وأضفت أصلًا ثنائيًا بسعة 500 ميجابايت إلى قوالب الخادم الخاص بي. عندما ذهبت لدفعه ، وجدت أنه من المثير للاهتمام أن git-lfs كان يتم تنزيله بسرعة 50 كيلوبايت في الثانية. نظرًا لأن لدي بعض وقت الفراغ الذي أفضل إنفاقه على شيء آخر غير انتظار تنزيل ملف دائمًا ، فقد قررت الصعود إلى الطابق العلوي والاتصال بشبكة إيثرنت. شاهدته على الفور يقفز بسرعة تصل إلى 2.5 ميغا بايت في الثانية. ما زلت غير سريع جدًا ، لكنني الآن فضولي بشدة.

نظرًا لأنني اعتقدت أنني كنت سأنتظر دائمًا حتى يتم نشر هذا ، قررت استخدام هذا الوقت والتحقيق في ما كان يحدث. على الرغم من أنني أتوقع أن تكون شبكة إيثرنت السلكية أسرع قليلاً من شبكة wifi ، إلا أنني لم أتوقع أن تكون الأوامر (مع s) أسرع من حيث الحجم. فقط للتحقق من سلامة عقلي ، أجريت اختبار سرعة ورأيت سرعة التنزيل عبر شبكة Wi-Fi بسرعة 40 ميجابايت في الثانية وسلكيًا بسرعة 60 ميجابايت في الثانية.

بعد إجراء بعض الأبحاث باستخدام WireShark وأدوات أخرى ، علمت أن قنوات Wi-Fi الخاصة بي بها الكثير من التداخل في النطاق 2 غيغاهرتز ، وقليلًا في النطاق 5 غيغاهرتز. خلال هذا الوقت ، علمت أيضًا أن جهاز التوجيه الخاص بي لن يقبل عميلًا واحدًا بسرعة 5 جيجاهرتز بسبب التهيئة الخاطئة من جانبي. لذلك كان تمكين "وقت الاستيقاظ المستهدف" غير المتسلسل ، على ما يبدو مهمًا للغاية (ليس لدي أي فكرة عما يفعله ذلك). بمجرد إصلاح ذلك ، رأيت 600 ميجابايت في الثانية على شبكتي الداخلية ، وكان معدل النقل الخارجي هو نفسه تقريبًا مثل السلكي.

لكن ، لماذا كانت بوابة git-lfs بطيئة جدًا ، حتى على 5 جيجا هرتز؟ بعد النظر إلى Wireshark أثناء التحميل إلى git-lfs ، لاحظت أن حوالي 30-50 ٪ من حركة المرور كانت معطلة / مزدوجة ACK مما تسبب في إعادة الإرسال. لقد وجدتها غريبة بشكل خاص ، وليست غريبة بشكل رهيب لأن تذكر أن شبكة wifi هذه "تمتص" مع جميع جيراني المزعجين. تبين أن هناك تأخيرًا عشوائيًا من 50 إلى 100 مللي ثانية في كل مكان. ربما بسبب التدخل. ومع ذلك ، عندما أجريت اختبار سرعة أو جلسة تصفح ، كانت أقل من 1٪! في الواقع ، لم يكن git-lfs يرسل أي حزم تقريبًا ، كما لو كان عالقًا إلى الأبد في البداية البطيئة لبروتوكول TCP.

 رسم بياني يوضح الحزم في الثانية (الإجمالي) وأخطاء الحزمة لـ git-lfs

عندما ألقيت نظرة على الحزم ، تم إرسالها في قطع حمولة 50 بايت تقريبًا (إجمالي 100 بايت تقريبًا ، MTU هو 1500). لقد وجدت هذا مثيرًا للاهتمام لأنني أتوقع أن تقوم خوارزمية Nagle بدمج الحزم بحيث يكون هناك عدد أقل من الحزم المادية لإرسالها. هذا عندما حدث لي ، يجب تعيين TCP_NODELAY.

بين هذا والتأخيرات العادية للغاية التي تصل إلى 100 مللي ثانية ، يمكنها فقط استخراج بضع حزم قبل الحصول على "حزمة مفقودة" ، ناهيك عن أن ما يقرب من 50٪ من كل حزمة كانت عبارة عن رؤوس حزم حرفيًا. لقد كنت عالقًا بشكل دائم في برنامج TCP Slow Start.

TCP بدون تأخير من الذاكرة

تمت كتابة خوارزمية Nagle منذ حوالي 4 عقود لحل مشكلة "microgram" ، حيث ترسل مجموعة كاملة من الحزم الصغيرة ، وإغراق الشبكة ، وتقليل إنتاجية الشبكة. تجمع خوارزمية Nagle بشكل أساسي جميع الحزم الصغيرة في حزمة واحدة كبيرة ، في انتظار إنشاء ACK أو حزمة كاملة ، أيهما يأتي أولاً.

نظريًا

C'est un peu plus complexe que cela en raison de décennies de changements pour rendre le Web meilleur et plus performant... mais activer TCP_NODELAY signifierait que chacun de ces 50 octets est envoyé en un seul paquet au lieu de quelques paquets أضخم. يؤدي هذا إلى زيادة حمل الشبكة ، وعندما تكون هناك فرصة لإعادة إرسال الحزمة ، سترى العديد من عمليات إعادة الإرسال.

إذا كنت تريد معرفة المزيد ، فاستخدم Google

الغوص في الكود

من هناك انتقلت إلى قاعدة كود git-lfs. لم أر أي مكالمة لـ setNoDelay وعندما نظرت إليها قالت إنها كانت الافتراضي. في الواقع:

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow