كيفية توفير الموارد في المتصفح وعدم كسر الويب. تقرير ياندكس

على الرغم من نمو أداء الجهاز ، أصبحت شبكة الويب أكثر وأكثر تطلبًا على الذاكرة والمعالج. يعد التقديم السليم والتخصيص الذكي للموارد عبر علامات التبويب جزءًا مهمًا من حل هذه المشكلة. كرس قسطنطين Kramlikh PurplePowder خطابه في مؤتمر "I Frontend" للخوارزميات التي تعمل على تحسين الإنتاجية وتوفير الموارد في كل من مشروع Chromium و Yandex.Browser.

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

في النهاية ، يمكن لمطوري واجهة الويب تعلم كيفية تحديد وحل مشكلات أداء موقع الويب.


- اسمي كوستيا ، أنا رئيس مجموعة تطوير المكونات الداخلية في فريق Yandex.Browser. في المتصفح ، كنت أقوم بأشياء مختلفة منذ ما يزيد قليلاً عن خمس سنوات: بدءًا من جميع عمليات فك التشفير في المتصفح ، بدءًا من جميع مقاطع فيديو HTML5 ، وحتى العرض ، والعرض ، وغيرها من العمليات المماثلة.

على مدار العام ونصف العام الماضيين ، شاركت في مشاريع متعلقة بتوفير الموارد في المتصفح: وحدة المعالجة المركزية والذاكرة والبطارية.

أنت تقول - كوستيا ، في الفناء عام 2019 ، أين هي مشاكل الموارد؟ يمكنك شراء أي جهاز تريده مع أي موارد. ولكن إذا انتقلنا إلى إحصائيات Mozilla المفتوحة ، فسوف نرى أن نصف المستخدمين لديهم ذاكرة 4 جيجابايت أو أقل. والعديد من المستخدمين الذين لديهم واحد أو اثنين من النوى المادية ، يشكلون نسبة كبيرة من جمهورك. في هذا العالم الذي نعيش فيه.



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



ما يجب القيام به المشكلة ليست سرا لأحد ، فقد بدأوا في القتال معها بنشاط منذ حوالي ثلاث سنوات. منذ ذلك الحين ، تم تشديد المكسرات تدريجياً بطرق مختلفة. اسمح لي أن أريك مثالاً ذهب حول Stack Overflow حوالي عام 2016. هنا مقتطف بسيط جدا. يقوم هذا الشيء بتحديث العنوان وتحديد الوقت الذي انقضى منذ الإطلاق الأخير لهذه الوظيفة. ما ينبغي الحصول عليها بشكل مثالي؟ يجب كتابة كل 100 مللي ثانية في العنوان + -100. كيف الحظ.



ولكن ماذا لو فتحنا ونفعل ذلك؟ وقد أي شخص واجه هذا؟ تم توجيه السؤال إلى Stack Overflow: ماذا بحق الجحيم الذي يتوقف فيه ملف تعريف الارتباط عن العمل في علامات تبويب الخلفية الخاصة بي؟ كانت هذه واحدة من مبادرات Chromium الأولى التي تهدف إلى تقليل استخدام وحدة المعالجة المركزية في المتصفح. كانت الفكرة أنه إذا لم يكن المستخدم يستخدم علامة التبويب الآن ، فهو لا يحتاجها الآن - فلنضع JS عليها.

يحاول المستعرض الحفاظ على تحميل وحدة المعالجة المركزية في علامة التبويب هذه بنسبة 1٪ تقريبًا - يبدأ في إيقاف جميع أنواع المؤقتات وتنفيذ JS وما إلى ذلك. هذه هي إحدى الخطوات الأولى في المستقبل المشرق.



بعد مرور بعض الوقت في المتصفح ، ستحصل على موقف تتوقف فيه علامات تبويب الخلفية عن العمل على الإطلاق. هذا هو المستقبل المشرق الذي أتحدث عنه. وفقًا لخطط Chromium ، التي عبروا عنها في BlinkOn الأخيرة ، في عام 2020 ، يخططون للقيام بذلك: دع علامة التبويب يتم تحميلها وإذا كانت الخلفية ، فلن تفعل شيئًا. تحتاج دائما أن تكون مستعدة لهذا الغرض.



في Yandex.Browser ، اعتنينا أيضًا بمثل هذه المشكلة ، لكننا حللنا بشكل أقل وضوحًا ولم نكسر الويب بالكامل. لقد أنشأنا وضعًا موفرًا للطاقة يقوم بإيقاف تشغيل فك التشفير على المعالج ولا يترك سوى فك التشفير على بطاقة الفيديو ، كما يقلل من FPS ويعطل بعض الرسوم المتحركة التي لا تكون مطلوبة في الوقت الحالي وبدلاً من ذلك يكون المستخدم أفضل لحفظ البطارية. هذا أعطانا حوالي ساعة من عمر البطارية الإضافي. يمكن لأي شخص التحقق ، ixbt ، على سبيل المثال ، فحص .



أعتقد أن البعض سيقول: كوستيا ، "لقد كسرت" الويب ، ساعدت بعض المستخدمين ، لكنك لم تقدم أي شيء أكثر ذكاءً. أضف المتشددين! كيف تقوم المتصفحات برسم الصفحات؟



مفهوم الطبقات ، باختصار ، هو عندما يحاول المستعرض تقسيم الصفحة إلى طبقات ورسمها بشكل منفصل. يتم ذلك بحيث يتم تنفيذ بعض الرسوم المتحركة ولا تجبر على إعادة رسم ما هو ثابت. المتصفح يفعل هذا على الاستدلال مختلفة. على سبيل المثال - محاولة تحديد عنصر فيديو في طبقة منفصلة ، والتي من الواضح ، بسرعة وكثيرا ما يعيد رسم. وإذا تم عرضه في مكان ما ، فلن تحتاج إلى إعادة رسم كل شيء تحته.

بالإضافة إلى ذلك ، تنقسم كل طبقة إلى مثل هذا البلاط - 256 بواسطة 256 مستطيل ، في المفتش يمكنك رؤية شيء مثل هذا. هناك إطار ينقسم إلى مجموعة من البلاط.





ما هو ولماذا هو مطلوب؟ بادئ ذي بدء ، لتحديد أولويات التقديم. إذا كان لدينا نقانق ضخمة نرسم عليها جميعًا ، فلماذا نحتاج إلى رسم كل هذا إذا رأى المستخدم الآن ما لديه الآن فقط في ViewPort؟



باستخدام هذا النهج ، نرسم أولاً ما يراه المستخدم الآن في ViewPort ، ثم تجانب واحد ، ثم في اتجاه التمرير. إذا قام المستخدم بالتمرير لأسفل - اسحب ، إذا كان يصل لأعلى. سيتم رسم كل شيء آخر فقط إذا كانت لدينا حصة لهذه البلاط ويمكننا رسمها ، وبعد ذلك سوف يراها المستخدم. أو ربما أبدا.



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



فقط على هذا المستوى ، تم إجراء العديد من التحسينات الناجحة للغاية. على سبيل المثال ، صنع Chromium هذا التحسين في عام 2017 تقريبًا.



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



كما أنه يساعد على حفظ الذاكرة. ما هي المشكلة هنا؟ مستطيلات بيضاء كاملة. تخيل أنه سيكون 256 × 256 نسيجًا ، وأربعة بايت لكل بكسل. على الرغم من أنه يبدو أنه يمكن ترميز هذه المنطقة بخمس أرقام فقط: الإحداثيات ، العرض ، الارتفاع واللون.



في Chromium ، تم تحسين المناطق الأحادية اللون. إذا كان المستعرض يدرك أنه لا يوجد أي تجسيد في هذا المستطيل ، فهو أحادي اللون تمامًا وغير شفاف ويلبي بعض الشروط الأخرى ، فنحن نقول فقط بطاقة الفيديو - ارسم مستطيلًا أبيض ، لا تحدد الملمس بالكامل.

ماذا يمكن أن يكون الأمثل هنا؟ إذا نظرت إلى البلاط المتبقي - فهي تحتوي على القليل من المحتوى ومساحة كبيرة من اللون الأبيض. في Yandex.Browser ، فكرنا في هذا الأمر وصنعنا آلية أطلقنا عليها اسم البلاط المتكيف.



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



تبدأ الصفحة أيضًا في حفظ كل ما يتم تمييزه باللون الأحمر. في الصفحات الأكثر تعقيدًا ، يبدو الأمر كهذا.



من المهم أن نفهم أنه لا تزال هناك مجموعة من الطبقات ويتم رسم كل طبقة على هذا النحو. في كل طبقة ، يمكنك حفظ بعض الذاكرة. سمح لنا هذا النهج بحفظ حوالي 40 ٪ من ذاكرة الفيديو في المتوسط ​​لجميع المستخدمين.

أكثر المتشددين! لقد حفظوا القليل من الذاكرة هنا ، لقد "كسروا" الويب - لماذا لا "يكسرون" الويب أكثر؟

في Chromium يوجد شيء يشبه السياسة: إذا كان المستخدم لا يستخدم علامات تبويب الخلفية ، وإذا تركها ، فهو لا يحتاج إليها. إذا كنا الآن بلا ذاكرة وكان المستعرض الآن في وضع التشغيل ، فلنأخذ علامة التبويب الأقدم التي لم يستخدمها المستخدم لفترة طويلة وقتله. ستبقى في الواجهة ، لكن العملية لن تكون موجودة بعد الآن ، فكل JS سوف تموت. هل هو بخير أم لا؟ من الغريب طرح مثل هذا السؤال في الطرف الأمامي وتوقع أي إجابة بخلاف "ماذا تفعل؟"



ثم لم يذهب الكثير. إليك التعليقات الحقيقية من مدونة Chromium: لقد قطعت كل طلباتي من أجلي ، كان هناك نوع من اللعبة - وهوب ، وليس لها أي حالة. من المهم أن نفهم أن هناك معالج تفريغ لم يعمل ، كما لو أننا ببساطة وضع علامة التبويب هذه. ثم يعود المستخدم إليه ، ونعيد تحميله من الشبكة ، وكأن شيئا لم يحدث.

ثم تم التخلي عن هذا النهج مؤقتًا وتوصل إلى فكرة جادة أكثر تفكيرًا. دعوا لها تجاهل.



ما هي النقطة؟ هذا هو نفس قتل علامات التبويب ، التي تسيطر عليها فقط. يطلق عليه الكلمة الذكية Page Lifecycle API . إذا كان لديك علامة تبويب ، ولم يرها المستخدم لفترة طويلة ، فيمكنه الدخول في الحالة المجمدة. يقول المتصفح خلال الحدث: سوف أجمدك الآن. بعد معالجة الحدث ، لن يتم تنفيذ أي شيء على الإطلاق. افعل ما تحتاجه ، استعد.

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



يمكنك الآن الاشتراك بالفعل في هذه الأحداث والتقاطها بطريقة ما. إذا تم قتل علامة التبويب حقًا ، فيمكنك التحقق من الحقل المهمَل. هذا يعني أنك استعدت بعد التخلص منها. يمكنك استعادة الحالة السابقة.



لقد فكرنا في Yandex.Browser منذ بضع سنوات: لماذا لا نستخدم نهجًا كرديًا معقدًا. أطلقوا عليه السبات.



ما هي النقطة؟ هناك العديد من علامات التبويب ، وهناك نوع من JS قيد التشغيل ، نوع من الحالة. يتم إنشاء عملية منفصلة لكل علامة تبويب: هنا يمكن تشغيل مقطع فيديو ، وهنا يمكنك ترك شيء في النموذج. السبات يصل - وليس هناك عمليات. كلنا حصلنا عليها. ولكن إذا عدنا الآن إلى علامات التبويب هذه ، فستعود العملية وستصبح الحالة كاملة ، وسيستمر تشغيل الفيديو من اللحظة المناسبة ، وسيظل النص الموجود في الحقول في مكانه.



ماذا فعلنا؟ توجد ثلاثة أشياء مهمة داخل كل عارض: V8 ، الذي يدير JS بالكامل ، Blink ، الذي يخزن DOM بأكمله ، ونوعًا من ربط المستعرض ، مما يساعد على ربط كل شيء معًا بعلامات جدولة وكل شيء آخر.



على سبيل المثال ، النظر في عينة. نحن هنا ننتظر حدوث onload ، وإضافة عنصر div جديد إلى شجرة DOM. بالنسبة للمتصفح ، يبدو مثل هذا.



بطبيعة الحال ، هناك شجرة DOM ، وتحتوي على بعض الحقول ، والكائنات المرتبطة بها ، وهناك مثل هذا الكيان.



في V8 ، يتم تخزين حالة كل عقدة ، وترتبط هذه العقد بالكائنات الوامضة من خلال طبقة من المجلدات. ماذا فعلنا؟ أخذنا المسلسل من الإصدار الثامن ، وقم بإجراء تسلسل لحالة V8 بأكملها ، ووجدنا جميع الكائنات ذات الصلة في Blink ، وكتب بالإضافة إلى المسلسلات التي تحفظ شجرة DOM بأكملها ، وتسلسلها ، ثم الكتابة إلى القرص ، مضغوطة ومشفرة. وقمنا بتدريس المتصفح للتعافي من هذه اللقطة. أي عندما يذهب المستخدم إلى علامة تبويب كهذه ، فإننا نوسعها ونفك تشفيرها ونظهرها للمستخدم ، ونستعيدها تمامًا. (منشور منفصل عن سبات - تقريبا.)

في الوقت الحالي ، يتم نشر Hibernate للجميع في وضع مستقر ويسمح لكل مستخدم بحفظ علامة تبويب واحدة أو اثنتين في المتوسط. هذا هو ، لديه في المتوسط ​​علامة تبويب واحدة دائما حفظ ، أو ربما اثنين. هذا يوفر الذاكرة للمستخدمين الذين لديهم أكثر من 10 علامات تبويب - كما هو الحال معك ، لكننا لسنا ممثلين.

أخبرت كيف يحاول المستعرض المساعدة ، لكن الآن بإمكان كل واحد منك فعل شيء لتسريع الموقع ، وتحسين أدائه. يمكنك أن تأتي وتفعل اليوم.

تحتاج أولاً إلى فهم ما إذا كانت هناك مشاكل في الذاكرة.



هناك بعض الأعراض: إما أن يبدأ الموقع في التدهور ، أو يظهر التلاشي. عادة ما يعني هذا أن جامع القمامة يتم تشغيله ، والعالم كله متجمد ولا يتم سحب أي شيء. أو أن الموقع ببساطة يبطئ باستمرار - يحدث هذا أيضا.

تحتاج إلى فهم ما إذا كان هناك مشكلة. نحن ننظر إلى ما يحدث مع ذاكرة JS.



إذا كانت تقفز ذهابًا وإيابًا أو تنمو بشكل مستمر ، فهذا ليس عرضًا جيدًا. أو ينمو باستمرار.



في هذه الحالة ، يمكنك دائمًا التقاط لقطة من خلال DevTools. وقد أي شخص حتى عناء مع تسرب في JS؟ إذا كان شخص ما لا يعرف ، فمن الممكن تمامًا حدوث تسرب في JS.



على سبيل المثال ، لديك متغير عمومي حيث يمكنك إضافة العقد التي لم يتم إدراجها في الشجرة. أنت تنساهم ، ثم اتضح أنهم يتناولون مئات الكيلوبايت ، أو حتى ميغابايت.



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



يمكنك أيضًا الاطلاع على تخصيص الذاكرة في المخطط الزمني. إذا كان لديك إفرازات منهجية ولم تنظف أبدًا ، فهذه علامة سيئة أيضًا ، أعتقد أن الجميع يفهم ذلك.



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



طبقة أخرى من المشاكل هي الأداء. setTimeout هي فكرة سيئة للرسوم المتحركة. لا يعمل بالطريقة التي يريد المستعرض تقديم الصفحة بها. قد لا يعمل في المرحلة: طلب المستعرض إطارًا ، لكن لا توجد رسوم متحركة بعد ، لأن setTimeout لم يعمل. أو يمكن أن تعمل حتى عندما لا تحتاج إلى رسم أي شيء. غادر المستخدم ، لا يزال هناك بعض الأعمال الخلفية ، لكننا سنعمل معه من خلال setTimeout.

إليك الطريقة الصحيحة التي سيتصل بها رد الاتصال الخاص بك فقط عندما يحتاج المستعرض إلى رسم هذه الصفحة.



أريد أيضًا أن أذكرك بأنه إذا أراد المستعرض رسم 60 إطارًا في الثانية ، فهذا يعني أن كل إطار يحتاج إلى حوالي 16 مللي ثانية.



وإذا كنت تشغل الدفق الرئيسي لفترة أطول من 16 مللي ثانية ، فعندئذ يكون لديك تخطي إطار مضمون ، وهو أمر غير سارٍ بالنسبة للمستخدم: يبدأ الموقع في الرعشة. لذلك ، كل العمل الجاد وضع بشكل صحيح في مؤشرات الترابط في الخلفية ، والتي ببساطة ترجع النتيجة.



أو نهج آخر هو استخدام microtasking. أنشئ قائمة انتظار مهمة ، وقم بمعالجتها بعد مرور بعض الوقت ، حتى تنتهي الحصة ، ودع المستعرض يرسم الصفحة بهدوء.



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



أحدث نهج للاهتمام - يشكو. إذا كانت لديك مشاكل ، فمن المفيد دائمًا أن تأتي وتحدث. ربما يمكن علاج هذه المشكلة بسهولة ، وسنساعد بعضنا البعض.

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

لقد قمنا بالتحقيق ، ونجري اختبارًا مثاليًا ، وصنعنا نموذجًا أوليًا ، واتضح أنه يمكننا القيام بذلك إذا أخبرنا الموقع بما نرسمه أولاً. اختبرناها ونرى أنه يحسن أدائنا. الآن نحن نختبر هذا في الإنتاج لجمهور صغير. نحن ننظر ما سيأتي منه. ترقبوا.

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

أنا هنا وضعت مختلف الروابط المفيدة:

Source: https://habr.com/ru/post/ar442456/


All Articles