تحسين أداء ميزات تسهيل الاستخدام في Chromium

هذه المشاركة من المطوّر المشارِك في Chromium، ​​أحمد الواسفي، الذي يشارك كيف أصبح مشارِكًا من خلال برنامج Google Summer of Code، ومشاكل الأداء المتعلّقة بتسهيل الاستخدام التي رصدها وأصلحها.

عندما اقتربت من السنة الأخيرة من هندسة الكمبيوتر في الجامعة الألمانية بالقاهرة، قرّرت استكشاف فرص المساهمة في البرامج مفتوحة المصدر. بدأت في تصفُّح قائمة Chromium بالمشاكل المناسبة للمبتدئين، ولفتت انتباهي بشكلٍ خاص ميزات تسهيل الاستخدام. قادني بحثي عن إرشادات إلى "آرون ليفنثال"، الذي ألهمتني خبرته واستعداده للمساعدة في التعاون معه في مشروع. وقد أصبح هذا التعاون تجربتي في Google Summer of Code، حيث تم قبولي للعمل مع فريق Chromium Accessibility.

بعد إكمال برنامج Google Summer of Code بنجاح، واصلت العمل على حلّ مشكلة عدم التمرير الناجح، وذلك بدافع الرغبة في تحسين الأداء. بفضل منحتين من برنامج OpenCollective في Google، تمكّنت من مواصلة العمل على هذا المشروع مع تولي مهام إضافية تركّز على تبسيط الرمز البرمجي لتحسين الأداء.

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

تأثير رمز تسهيل الاستخدام في الأداء في Chrome

يساعد رمز تسهيل الاستخدام في Chrome التقنيات المساعدة، مثل برامج قراءة الشاشة، في الوصول إلى الويب. ومع ذلك، عند تفعيل هذه الميزة، يمكن أن تؤثّر في أوقات التحميل والأداء وعمر البطارية. لذلك، يظل هذا الرمز غير نشط إذا لم يكن مطلوبًا لتجنُّب تباطؤ الأداء. يُفعّل ما يتراوح بين %5 و%10 من المستخدمين رمز تسهيل الاستخدام، ويعود ذلك غالبًا إلى أدوات مثل أدوات إدارة كلمات المرور وبرامج مكافحة الفيروسات التي تستخدم واجهات برمجة التطبيقات الخاصة بتسهيل الاستخدام على النظام الأساسي. تعتمد هذه الأدوات على واجهات برمجة التطبيقات هذه للتفاعل مع محتوى الصفحة وتعديله، مثل تحديد حقول كلمات المرور لمدراء كلمات المرور وملء النماذج.

لا يُعرف بعد إجمالي الانخفاض في المقاييس الأساسية، ولكن أظهرت تجربة حديثة تُسمى "إيقاف ميزة تسهيل الاستخدام تلقائيًا" (إيقاف ميزة تسهيل الاستخدام عندما لا يتم استخدامها) أنّه مرتفع جدًا. تحدث المشكلة بسبب الأعداد الهائلة من العمليات الحسابية وعمليات الاتصال في مجالَين رئيسيَّين من قاعدة بيانات ميزات تسهيل الاستخدام في Chrome: وحدة المعالجة والتصفّح. يجمع أداة الربط معلومات عن محتويات الويب والتغييرات التي تطرأ على المحتوى، ويحسب سمات تسهيل الاستخدام لسلسلة من العقد. بعد ذلك، يتم تسلسل أيّ عقد غير محدَّثة وإرسالها من خلال قناة إلى سلسلة مهام واجهة المستخدم الرئيسية لعملية المتصفّح. تتلقّى سلسلة المحادثات هذه هذه المعلومات وتُعيد تسلسلها إلى الشجرة المتطابقة للعقد، ثم تحوّلها أخيرًا إلى شكل مناسب للتكنولوجيات المساعِدة التابعة لجهات خارجية، مثل برامج قراءة الشاشة.

تحسينات على تسهيل الاستخدام في Chromium

تم الانتهاء من المشاريع التالية خلال حملة Summer of Code، ثم بعد ذلك، تم تمويلها من خلال برنامج Google OpenCollective.

تحسين ذاكرة التخزين المؤقت

في Chrome، تتوفّر بنية بيانات خاصة تُعرف باسم شجرة تسهيل الاستخدام والتي تعكس شجرة DOM. ويتم استخدامه لمساعدة التقنيات المساعدة في الوصول إلى محتوى الويب. في بعض الأحيان، عندما يحتاج جهاز إلى معلومات من هذه الشجرة، قد لا تكون جاهزة، لذا على المتصفّح جدولة هذه الطلبات لوقت لاحق.

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

لتحسين ذلك، انتقلنا إلى نظام يستخدم قوائم القيم المحدّدة. يتم تعيين قيمة فهرس معيّنة لكل مهمة، وبعد أن تصبح شجرة تسهيل الاستخدام جاهزة، يتم استدعاء القيمة الصحيحة لتلك المهمة. وقد سهّل هذا التغيير فهم الرمز المبرمَج وساهم في تحسين الأداء بنسبة تزيد عن %20.

الرسوم البيانية لاختبار الأداء أثناء التشغيل
رسم بياني لأوقات التشغيل لعدة اختبارات أداء يُظهر انخفاضًا ملحوظًا بنسبة% 20 تقريبًا في جميع الاختبارات

العثور على مشاكل الأداء في الانتقال في الصفحة وحلّها

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

لاختبار ذلك، أزلنا مؤقتًا الرمز البرمجي الذي يعالج المربّعات الحدودية و أجرينا اختبارات الأداء لمعرفة التأثير. أظهر أحد الاختبارات، وهو focus-links.html، تحسّنًا كبيرًا بنسبة %1618 تقريبًا. وأصبح هذا الاكتشاف أساسًا لمزيد من العمل.

التحقيق في اختبار السرعة البطيئة

بدأت التحقيق في سبب بطء هذا الاختبار المحدّد باستخدام المربّعات الحدودية. كل ما فعله الاختبار هو التركيز على عدة روابط تلو الأخرى. لذلك، يجب أن تكون المشكلة الرئيسية هي التركيز على العناصر أو الانتقال إلى الأسفل أو الأعلى الذي حدث مع إجراء التركيز. لاختبار ذلك، أضفت {preventScroll: true} إلى focus() في اختبار الأداء، ما أدّى إلى إيقاف الانتقال للأعلى أو للأسفل.

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

نتائج الاختبار مع إيقاف التمرير
ينخفض وقت تشغيل اختبار روابط التركيز من 20 ملي ثانية إلى 1.1 ملي ثانية عند إيقاف الانتقال للأعلى أو للأسفل أو عند إزالة تسلسل مربّع الحدود.

لقد أنشأت اختبارًا جديدًا باسم scroll-in-page.html لإعادة اختبار focus-links، ولكن بدلاً من استخدام التركيز، يتم الانتقال بين العناصر باستخدام scrollIntoView(). لقد اختبرتُ الانتقال السلس والمرّ الفوري للمحتوى، مع وبدون عمليات حسابية للحدود المربّعة.

نتائج الاختبار الجديد.
يستغرق معالجة التمريرات في ميزة "التمرير الفوري" 65 ملي ثانية، في حين يستغرق التمرير السلس 123 ملي ثانية.

أظهرت النتائج أنّه باستخدام مربّعات الالتفاف الفوري والحدود، استغرقت العملية حوالي 66 ملي ثانية. كان التمرير السلس أبطأ بكثير، حيث بلغ معدّله حوالي 124 ملي ثانية. عندما أوقفنا استخدام المربّعات الحدودية، لم يستغرق ذلك أيّ وقت على الإطلاق لأنّه لم يتم بدء أي أحداث.

لقد عرفنا المشكلة، ولكن ما سبب حدوثها؟

لقد تبيّن لنا الآن أنّ الانتقال للأعلى أو للأسفل هو مصدر الكثير من البطء في تسلسل تسهيل الاستخدام، ولكن كان علينا معرفة السبب. لتحليل ذلك، تم استخدام أداتين تُسمى perf وpprof لتقسيم العمل الذي تم تنفيذه في عملية المتصفّح. غالبًا ما تُستخدَم هذه الأدوات في C++ لإنشاء ملفّات الأداء. تعرض الرسوم البيانية التالية مقتطفًا من الجزء المثير للاهتمام.

رسم بياني لاختبارات الانتقال السريع التي تم تحليلها
مخطّط بياني تم إنشاؤه من خلال تحليل اختبارات الانتقال للأعلى أو للأسفل تعرِض هذه البطاقة الوقت الذي يتم خلاله الاستدعاء بشكل أساسي لدالة تُسمى Unserialize بالإضافة إلى دالة أخرى تُسمى IsChildOfLeaf.

بعد التحقيق في المشكلة، تبيّن لنا أنّها لم تكن في رمز فك التشفير نفسه، بل في معدّل تكرار طلبات استخدامه. لفهم ذلك، علينا الاطّلاع على طريقة عمل تحديثات تسهيل الاستخدام في Chromium. لا يتم إرسال التعديلات بشكل فردي، وبدلاً من ذلك، هناك موقع مركزي يُسمى AXObjectCache يخزّن كل الخصائص. عند تغيير إحدى العقد، تُرسِل طرق مختلفة إشعارًا إلى ذاكرة التخزين المؤقت لتصنيف تلك العقدة على أنّها غير محفوظة لتسلسلها لاحقًا. بعد ذلك، يتم تسلسل جميع سمات الملاحظات غير المحفوظة، بما في ذلك السمات التي لم تتغيّر، وإرسالها إلى المتصفّح. على الرغم من أنّ هذا التصميم يبسط الرمز البرمجي ويقلل من التعقيد من خلال توفير مسار تعديل واحد، إلا أنّه يصبح بطيئًا عند حدوث أحداث "وضع علامة على المحتوى على أنّه غير محدَّث" بشكل سريع، مثل تلك التي تتم من خلال الانتقال للأعلى أو للأسفل. إنّ الشيء الوحيد الذي يتغيّر هو قيم scrollX وscrollY ، ومع ذلك، فإنّنا نسلسل بقية السمات معها في كل مرة. وبلغ معدل التحديثات هنا أكثر من عشرين مرة في الثانية.

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

حلّ مشكلة الانتقال

كان الحل واضحًا: تضمين Offsets التمرير الحالية مع ترميز مربع الحدود. ويضمن ذلك معالجة تعديلات الانتقال إلى الأسفل أو الأعلى من خلال المسار السريع، ما يعزّز الأداء بدون تأخيرات غير ضرورية. من خلال تجميع Offsets للانتقال إلى أعلى أو أسفل الشاشة مع بيانات مربّع الحدود، نُحسِّن العملية لإجراء تعديلات أكثر سلاسة وفعالية، ما يمنح المستخدمين الذين فعّلوا ميزات تسهيل الاستخدام تجربة أكثر سلاسة. بعد تنفيذ الإصلاح، تحسّن الأداء بنسبة تصل إلى%825 في اختبارات الانتقال للأعلى أو للأسفل.

تبسيط الرموز

خلال هذه الفترة، ركّزت على جودة الرموز البرمجية كجزء من مشروع يُسمى Onion Soup، الذي يبسط الرموز البرمجية عن طريق تقليل أو إزالة الرموز البرمجية المُوزّعة بلا داعٍ على جميع الطبقات.

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

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

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

الخاتمة

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

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

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

بالنسبة إلى أولئك الذين يريدون المساهمة في مشروع ذي مغزى وتطوير مهاراتهم، أنصحهم بشدة بالمشاركة في Chromium. إنّها طريقة رائعة ل التعلم، وتقدّم برامج مثل Google Summer of Code نقطة انطلاق ممتازة لرحلتك.