HeadlinesBriefing favicon HeadlinesBriefing.com

أداء الخيط الرئيسي للمتصفح

Hacker News •
×

ما الذي يتبادر إلى ذهنك عندما تسمع "تحسين الواجهة الأمامية"؟ بالنسبة لمعظمنا، إنه أشياء مثل تقليل طلبات الشبكة، وتقليل حجم الحزمة، أو الاستفادة الجيدة من ذاكرة التخزين المؤقت. بالإضافة إلى ذلك، ربما تقليل إعادة العرض أو ضبط وقت تحميل الموارد. الخيط الرئيسي لا يُذكر عادةً، وهناك سبب لذلك: على معظم الشاشات لا يصبح مشكلة أبدًا. لكن على الشاشات التي تحتوي على الكثير من التفاعل، حيث تتدفق البيانات مباشرة ويتشابك التمرير والرسوم المتحركة والإدخال معًا، تتغير الصورة. مهما وفرت على الشبكة وحجم الحزمة، تتجمد الشاشة في اللحظة التي يتم فيها حظر الخيط الرئيسي. ربما صادفت موقعًا ويب حيث يتعثر التمرير بين الحين والآخر، أو يستجيب زر بتأخير طفيف، أو تظهر الحروف التي تكتبها في مربع البحث بعد نصف نبضة. إنه ليس سيئًا بما يكفي ليكون مزعجًا، لكنه يثير أعصابك بطريقة خفية. هذا النوع من التقطيع (jank) هو ما يبدو عليه الخيط الرئيسي المحظور. عندما نواجه تقطيعًا كهذا كمطورين، يكون رد الفعل المعتاد هو التساؤل "هل كودي بطيء؟" والبدء في تفكيك الخوارزميات أو البحث عن الحسابات المهدرة. في معظم الحالات، ومع ذلك، سرعة الكود ليست المشكلة. الكود ليس بطيئًا. إنه فقط يحدث أن يكون الكود الذي يمسك بالخيط الرئيسي. المتصفح لديه عدد من الخيوط، لكن كل شيء يمكننا لمسه من الكود يتركز تقريبًا على الخيط الرئيسي. الحساب، العرض، معالجة الأحداث، معالجة استجابة الشبكة، وأجزاء إطار العمل الداخلية كلها تتم معالجتها هناك. مورد واحد، جبل من العمل. خيط المتصفح الرئيسي مكلف. معظم الوقت لا يسبب مشاكل، ولكن بمجرد أن تحاول فعل شيء طموح، يصبح التعامل مع الخيط الرئيسي هو الجزء المهم. هذه المقالة عن كيفية التعامل مع ذلك المورد المكلف. لنبدأ بما يفعله الخيط الرئيسي فعليًا. يقع عمله في فئتين واسعتين. الأولى هي تشغيل JavaScript. الكود الذي نكتبه، مع معالجات الأحداث، والمهلة الزمنية، واستدعاءات استجابة الشبكة، وأجزاء إطار العمل الداخلية، كلها تعمل هنا. تنفذ هذه المهام بالترتيب الذي تدخل به الطابور، كلما كان هناك فجوة، دون علاقة بدورة تحديث الشاشة. الثانية هي رسم الشاشة. عندما يتغير DOM أو الأنماط وتحتاج الشاشة إلى التحديث، يمر المتصفح تقريبًا عبر هذه الخطوات، بالترتيب، لإنتاج إطار. تشغيل استدعاءات requestAnimationFrame — JavaScript مسجل للتشغيل قبل رسم الإطار مباشرة حساب النمط — حساب قيم CSS النهائية لكل عنصر التخطيط — حساب موضع وحجم كل عنصر (يُسمى أيضًا إعادة التدفق) الطلاء — إنشاء أوامر الطلاء التي تصف ما يجب رسمه وبأي ألوان إذا لم يتغير شيء، يتم تخطي هذه الخطوات بالكامل، لذا فهي لا تعمل بالضرورة كل إطار. فقط خطوة التركيب النهائية، التي تأخذ المخرجات المنتجة وتجمعها على الشاشة، يتم تسليمها إلى خيط المُركب. بمعنى آخر، معظم النصف الأول من خط الأنابيب الذي يرسم الشاشة هو مسؤولية الخيط الرئيسي. خط أنابيب العرض لتحديث الشاشة لكي تبدو الشاشة سلسة، يجب رسم الإطارات بمعدل تحديث الشاشة. على شاشة 60Hz الأكثر شيوعًا، يعني ذلك 60 إطارًا في الثانية، أو حوالي 16.6 مللي ثانية لكل إطار. ولا يمكنك استخدام كل ذلك. بمجرد طرح تكلفة معالجة المتصفح الخاصة، عادة ما تُعتبر الميزانية العملية حوالي 10 مللي ثانية، وعلى جهاز 120Hz يتم تقليل الميزانية نفسها إلى النصف. المشكلة هي أن نوعي العمل أعلاه يقفان في صف واحد على نفس الخيط. تم تصميم JavaScript حول نموذج حلقة أحداث أحادية الخيط. يعالج الخيط الرئيسي مهمة واحدة في كل مرة، وبينما تعمل تلك المهمة، لا يمكن أن يحدث أي شيء آخر. إذا دارت دالة JavaScript لمدة 200 مللي ثانية، فعندئذٍ لمدة 200 مللي ثانية لا يستطيع المتصفح إعادة رسم الشاشة أو استقبال نقرة من المستخدم. مقابل ميزانية إطار تبلغ حوالي 10 مللي ثانية، هذه كمية وقت قاتلة. مهمة ت...