الفرق بين المراجعتين ل"ReactNative/profiling"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
سطر 1: سطر 1:
== مراقبة الأداء Profiling ==
+
== فحص الأداء Profiling ==
استخدم مراقب أداء مبني مسبقًا للحصول على معلومات مفصلة حول العمل المنجز في خيط JavaScript والخيط thread الرئيسي معًا، حيث يمكنك الوصول إلى مراقب الأداء عن طريق تحديد الخيار Perf Monitor من قائمة Debug.
+
استخدم فاحص أداء مبني مسبقًا للحصول على معلومات مفصَّلة حول العمل المنجز في خيط JavaScript والخيط الرئيسي main thread معًا، حيث يمكنك الوصول إلى فاحص الأداء عن طريق تحديد الخيار Perf Monitor من قائمة Debug.
  
تُعَد الأداة Instruments أداةً لا تقدر بثمن في نظام iOS كالأداة <code>systrace</code> على نظام Android التي يجب أن تتعلمها. لكن تأكد أولًا من إيقاف وضع التطوير، حيث يجب أن ترى ما يلي في سجلت تطبيقك:<syntaxhighlight lang="bash">
+
تُعَد الأداة Instruments أداةً قيّمة في نظام iOS كالأداة <code>systrace</code> على نظام Android التي يجب أن تتعلمها. لكن تأكد أولًا من [[ReactNative/performance#.D8.AA.D8.B4.D8.BA.D9.8A.D9.84 .D8.A7.D9.84.D8.AA.D8.B7.D8.A8.D9.8A.D9.82 .D9.81.D9.8A .D9.88.D8.B6.D8.B9 .D8.A7.D9.84.D8.AA.D8.B7.D9.88.D9.8A.D8.B1 .28dev.3Dtrue.29|إيقاف وضع التطوير]]، حيث يجب أن ترى ما يلي في سجلات تطبيقك:<syntaxhighlight lang="bash">
 
__DEV__ === false, development-level warning are OFF, performance optimizations are ON
 
__DEV__ === false, development-level warning are OFF, performance optimizations are ON
</syntaxhighlight>هناك طريقة أخرى لمراقبة أداء شيفرة JavaScript وهي استخدام مراقب أداء Chrome أثناء التنقيح debugging. لن تمنحك هذه الطريقة نتائجًا دقيقة نظرًا لأن الشيفرة تعمل في Chrome ولكنها ستعطيك فكرة عامة عن مكان الاختناقات bottlenecks. شغّل مراقب الأداء ضمن نافذة الأداء <code>Performance</code> في Chrome، ثم سيظهر رسم بياني تحت <code>User Timing</code>. يمكنك عرض مزيد من التفاصيل بجدول من خلال النقر على تبويب <code>Bottom Up</code> في الأسفل ثم حدّد <code>DedicatedWorker Thread</code> في القائمة العلوية اليسرى.
+
</syntaxhighlight>هناك طريقة أخرى لفحص أداء شيفرة JavaScript وهي استخدام فاحص أداء Chrome أثناء تصحيح الأخطاء debugging. لن تمنحك هذه الطريقة نتائجًا دقيقة نظرًا لأن الشيفرة تعمل في Chrome ولكنها ستعطيك فكرة عامة عن مكان الاختناقات bottlenecks. شغّل فاحص الأداء ضمن تبويب الأداء <code>Performance</code> في Chrome، ثم سيظهر رسم بياني تحت <code>User Timing</code>. يمكنك عرض مزيد من التفاصيل بجدول من خلال النقر على تبويب <code>Bottom Up</code> في الأسفل ثم اختر <code>DedicatedWorker Thread</code> في القائمة العلوية اليسرى.
  
=== مراقبة أداء واجهة مستخدم Android باستخدام الأداة <code>systrace</code> ===
+
=== فحص أداء واجهة مستخدم Android باستخدام الأداة <code>systrace</code> ===
يدعم Android أكثر من 10 آلاف هاتف مختلف وقد عُمَِم لدعم تصيير البرمجيات، حيث تعني معمارية إطار العمل والحاجة إلى التعميم عبر العديد من العتاد المستهدَف للأسف أنك تحصل على مجانية أقل بالموازنة مع نظام iOS. لكن هناك أحيانًا أشياء يمكنك تحسينها، حيث ليس خطأ الشيفرة الأصيلة من بينها على الإطلاق.
+
يدعم نظام Android أكثر من 10 آلاف هاتف مختلف وقد عُمَِم لدعم تصيير rendering البرمجيات، حيث تؤدي معمارية إطار العمل والحاجة إلى التعميم عبر العديد من العتاد المستهدَف للأسف إلى الحصول على حرية أقل بالموازنة مع نظام iOS. لكن هناك أحيانًا أشياء يمكنك تحسينها وليست أخطاء الشيفرة الأصيلة من بين هذه الأشياء على الإطلاق.
  
الخطوة الأولى لتنقيح هذا الخطأ هي الإجابة على السؤال الأساسي حول المكان الذي تقضي فيه وقتك خلال كل إطار زمنه 16 ميلي ثانية. لذلك سنستخدم فاحص أداء نظام Android قياسي يسمى <code>systrace</code>.
+
الخطوة الأولى لصحيح هذا الخطأ هي الإجابة عن السؤال الأساسي حول المكان الذي تقضي فيه وقتك خلال كل إطار زمنه 16 ميلي ثانية. لذلك سنستخدم فاحص أداء نظام Android معياري يسمى <code>systrace</code>.
  
<code>systrace</code> هي أداة فحص أداء مستندة إلى معلِّم Android قياسي (وتُثبَّت عند تثبيت حزمة أدوات منصة Android). تُحاط كتل الشيفرة المفحوصة بمعلّمات البداية / النهاية والتي تُصوَّر بعد ذلك ضمن تنسيق مخطط ملون. يوفر كل من إطار عمل Android SDK و React Native معلّمات قياسية يمكنك تصورها.
+
<code>systrace</code> هي أداة فحص أداء مستندة إلى علامات Android معيارية (وتُثبَّت عند تثبيت حزمة أدوات منصة Android). تُحاط كتل الشيفرة المفحوصة بعلامات البداية / النهاية والتي تُصوَّر بعد ذلك ضمن تنسيق مخطط ملون. يوفر كلٌّ من إطار عمل Android SDK و React Native علامات معيارية يمكنك تصوّرها.
  
 
==== 1. جمع التعقّب trace ====
 
==== 1. جمع التعقّب trace ====
صِل أولًا جهازًا يُظهر التلعثم الذي تريد فحصه بحاسوبك عبر وصلة USB واجعله يصل إلى النقطة التي تسبق الانتقال أو التحرك الذي تريد فحصه مباشرةً. شغّل <code>systrace</code> كما يلي:<syntaxhighlight lang="bash">
+
صِل أولًا جهازًا يُظهر الخلل الذي تريد فحصه بحاسوبك عبر وصلة USB واجعله يصل إلى النقطة التي تسبق الانتقال أو التحرك الذي تريد فحصه مباشرةً. شغّل <code>systrace</code> كما يلي:<syntaxhighlight lang="bash">
 
$ <path_to_android_sdk>/platform-tools/systrace/systrace.py --time=10 -o trace.html sched gfx view -a <your_package_name>
 
$ <path_to_android_sdk>/platform-tools/systrace/systrace.py --time=10 -o trace.html sched gfx view -a <your_package_name>
 
</syntaxhighlight>لنفصّل الأمر السابق:
 
</syntaxhighlight>لنفصّل الأمر السابق:
  
* <code>time</code> هو طول الوقت لجمع التعقّب مقدرًا بالثواني.
+
* <code>time</code> هو طول وقت جمع التعقّب مقدرًا بالثواني.
 
* <code>sched</code> و <code>gfx</code> و <code>view</code> هي وسوم android SDK (مجموعات من الوسوم) التي يجب الاهتمام بها، حيث يمنحك الوسم <code>sched</code> معلومات حول ما يجري تشغيله على كل نواة من هاتفك، ويمنحك الوسم <code>gfx</code> معلومات عن الرسوميات مثل حدود الإطار، ويمنحك الوسم <code>view</code> معلومات حول القياس والتخطيط ورسم التمريرات.
 
* <code>sched</code> و <code>gfx</code> و <code>view</code> هي وسوم android SDK (مجموعات من الوسوم) التي يجب الاهتمام بها، حيث يمنحك الوسم <code>sched</code> معلومات حول ما يجري تشغيله على كل نواة من هاتفك، ويمنحك الوسم <code>gfx</code> معلومات عن الرسوميات مثل حدود الإطار، ويمنحك الوسم <code>view</code> معلومات حول القياس والتخطيط ورسم التمريرات.
* ‏‏تفعّل ‎<code>-a <your_package_name>‎</code>‏‏ المعلّمات markers الخاصة بالتطبيق، وتحديدًا تلك المدمَجة في إطار عمل React Native. يمكن العثور على <code>your_package_name</code> في ملف <code>AndroidManifest.xml</code> لتطبيقك الذي يشبه <code>com.example.app</code>.
+
* ‏‏تفعّل ‎<code>-a <your_package_name>‎</code>‏‏ العلامات markers الخاصة بالتطبيق، وتحديدًا تلك المدمَجة في إطار عمل React Native. يمكن العثور على اسم حزمتك <code>your_package_name</code> في ملف <code>AndroidManifest.xml</code> الخاص بتطبيقك الذي يكون بالشكل <code>com.example.app</code>.
  
أجرِ الحركة أو التفاعل الذي تريده بمجرد بدء تجميع التعقّب، ثم سيعطيك systrace في نهاية التعقّب رابطًا للتعقّب يمكنك فتحه في متصفحك.
+
أجرِ الحركة أو التفاعل الذي تريده بمجرد بدء تجميع التعقّب، ثم ستعطيك الأداة systrace في نهاية التعقّب رابطًا للتعقّب يمكنك فتحه في متصفحك.
  
 
==== 2. قراءة التعقّب ====
 
==== 2. قراءة التعقّب ====
 
يجب أن يظهر لك الشكل التالي بعد فتح التعقّب في متصفحك (يفضَّل استخدام Chrome):
 
يجب أن يظهر لك الشكل التالي بعد فتح التعقّب في متصفحك (يفضَّل استخدام Chrome):
 
[[ملف:SystraceExample1.png|بديل=Systrace Example|مركز|تصغير|354x354بك]]
 
[[ملف:SystraceExample1.png|بديل=Systrace Example|مركز|تصغير|354x354بك]]
<blockquote>'''ملاحظة''': استخدم مفاتيح WASD للرشق والتكبير.</blockquote>إن لم يُفتَح ملف التعقّب ‎.html الخاص بك بصورةٍ صحيحة، فتحقّق من وجود ما يلي في وحدة تحكم المتصفح:
+
<blockquote>'''ملاحظة''': استخدم مفاتيح WASD للتحديد والتقريب.</blockquote>إن لم يُفتَح ملف التعقّب ‎.html الخاص بك بصورةٍ صحيحة، فتحقّق من وجود ما يلي في وحدة تحكم المتصفح:
 
[[ملف:TypeError.png|بديل=Type Error|مركز|تصغير|353x353بك]]
 
[[ملف:TypeError.png|بديل=Type Error|مركز|تصغير|353x353بك]]
 
بما أن <code>Object.observe</code> اُهمِل في المتصفحات الحديثة، فقد تضطر إلى فتح الملف من أداة Google Chrome Tracing عن طريق:
 
بما أن <code>Object.observe</code> اُهمِل في المتصفحات الحديثة، فقد تضطر إلى فتح الملف من أداة Google Chrome Tracing عن طريق:
سطر 35: سطر 35:
 
* اختر ملف html المنشَأ من الأمر السابق.
 
* اختر ملف html المنشَأ من الأمر السابق.
  
<blockquote>'''تفعيل الخيار VSync highlighting'''
+
<blockquote>'''تفعيل الخيار VSync highlighting:'''
  
 
حدد مربع الاختيار التالي في أعلى يمين الشاشة لتحديد حدود الإطار الذي مدته 16 ميلي ثانية:[[ملف:EnableVSyncHighlighting.png|بديل=Enable VSync Highlighting|مركز|تصغير]]يجب أن تشاهد أشرطة مخطّطة كما في لقطة الشاشة السابقة. إن لم يظهر ذلك، فحاول فحص الأداء على جهاز مختلف، حيث تُعرَف أجهزة Samsung أنها تواجه مشكلات في عرض vsyncs بينما تكون سلاسل Nexus موثوقة.</blockquote>
 
حدد مربع الاختيار التالي في أعلى يمين الشاشة لتحديد حدود الإطار الذي مدته 16 ميلي ثانية:[[ملف:EnableVSyncHighlighting.png|بديل=Enable VSync Highlighting|مركز|تصغير]]يجب أن تشاهد أشرطة مخطّطة كما في لقطة الشاشة السابقة. إن لم يظهر ذلك، فحاول فحص الأداء على جهاز مختلف، حيث تُعرَف أجهزة Samsung أنها تواجه مشكلات في عرض vsyncs بينما تكون سلاسل Nexus موثوقة.</blockquote>
  
 
==== 3. البحث عن العملية الخاصة بك ====
 
==== 3. البحث عن العملية الخاصة بك ====
مرّر حتى ترى (جزءًا من) اسم حزمتك. قد تفحص أداء <code>com.facebook.adsmanager</code> على سبيل المثال، والذي يظهر كالاسم <code>book.adsmanager</code> بسبب حدود اسم الخيط في النواة.
+
مرّر حتى ترى (جزءًا من) اسم حزمتك. قد تفحص أداء <code>com.facebook.adsmanager</code> على سبيل المثال، والذي يظهر كالاسم <code>book.adsmanager</code> بسبب حدود اسم الخيط thread في النواة.
  
 
سترى على الجانب الأيسر مجموعة من الخيوط التي تتوافق مع صفوف الخط الزمني الموجودة على اليمين. هناك عدد قليل من الخيوط التي تهمنا مثل : خيط واجهة المستخدم (الذي يحتوي على اسم حزمتك أو الاسم UI Thread)، والخيط <code>mqt_js</code>، والخيط <code>mqt_native_modules</code>. إن استخدمت Android 5+‎ ، فيجب الاهتمام أيضًا بالخيط Render Thread.
 
سترى على الجانب الأيسر مجموعة من الخيوط التي تتوافق مع صفوف الخط الزمني الموجودة على اليمين. هناك عدد قليل من الخيوط التي تهمنا مثل : خيط واجهة المستخدم (الذي يحتوي على اسم حزمتك أو الاسم UI Thread)، والخيط <code>mqt_js</code>، والخيط <code>mqt_native_modules</code>. إن استخدمت Android 5+‎ ، فيجب الاهتمام أيضًا بالخيط Render Thread.
سطر 48: سطر 48:
 
[[ملف:UIThread.png|بديل=UI Thread|مركز|تصغير]]
 
[[ملف:UIThread.png|بديل=UI Thread|مركز|تصغير]]
  
* '''خيط JS'''.: وهو مكان تنفيذ فيه شيفرة JavaScript. سيكون اسم الخيط إما <code>mqt_js</code> أو <code><...></code> اعتمادًا على مدى تعاون النواة على جهازك. يمكن تحديد هذا الخيط إن لم يكن له اسم من خلال البحث عن أشياء مثل <code>JSCall</code> و <code>Bridge.executeJSCall</code> وما إلى ذلك:
+
* '''خيط JS'''.: وهو مكان تنفيذ شيفرة JavaScript. سيكون اسم الخيط إما <code>mqt_js</code> أو <code><...></code> اعتمادًا على مدى تعاون النواة على جهازك. يمكن تحديد هذا الخيط إن لم يكن له اسم من خلال البحث عن أشياء مثل <code>JSCall</code> و <code>Bridge.executeJSCall</code> وما إلى ذلك:
  
 
[[ملف:JSThread.png|بديل=JS Thread|مركز|تصغير]]
 
[[ملف:JSThread.png|بديل=JS Thread|مركز|تصغير]]
سطر 56: سطر 56:
 
[[ملف:NativeModulesThread.png|بديل=Native Modules Thread|مركز|تصغير|351x351بك]]
 
[[ملف:NativeModulesThread.png|بديل=Native Modules Thread|مركز|تصغير|351x351بك]]
  
* '''خيط التصيير Render Thread (خيط إضافي)''': إن استخدمت Android L (5.0) أو الإصدارات الأحدث، فسيكون لديك أيضًا خيط تصيير في تطبيقك. ينشئ هذا الخيط أوامر OpenGL الفعلية المستخدمة في رسم واجهة المستخدم الخاصة بك. سيكون اسم الخيط إما <code>RenderThread</code> أو <code><...></code>. يمكنك تحديده في الحالة الأخيرة  من خلال البحث عن أشياء مثل <code>DrawFrame</code> و <code>queueBuffer</code>:
+
* '''خيط التصيير Render Thread (خيط إضافي)''': إن استخدمت Android L (5.0) أو الأحدث، فسيكون لديك أيضًا خيط تصيير في تطبيقك. ينشئ هذا الخيط أوامر OpenGL الفعلية المستخدمة في رسم واجهة المستخدم الخاصة بك. سيكون اسم الخيط إما <code>RenderThread</code> أو <code><...></code>. يمكنك تحديده في الحالة الأخيرة  من خلال البحث عن أشياء مثل <code>DrawFrame</code> و <code>queueBuffer</code>:
  
 
[[ملف:RenderThread.png|بديل=Render Thread|مركز|تصغير|352x352بك]]
 
[[ملف:RenderThread.png|بديل=Render Thread|مركز|تصغير|352x352بك]]
  
=== تحديد الجاني ===
+
=== تحديد المسؤول عن المشكلة ===
يجب أن تبدو الحركات كما يلي:
+
يجب أن يبدو التحريك كما يلي:
 
[[ملف:1SystraceWellBehaved.png|بديل=Systrace Well Behaved|مركز|تصغير|360x360بك]]
 
[[ملف:1SystraceWellBehaved.png|بديل=Systrace Well Behaved|مركز|تصغير|360x360بك]]
كل تغيير في اللون هو عبارة عن إطار . تذكّر أنه يجب إنجاز جميع أعمال واجهة المستخدم الخاصة بك بنهاية فترة 16 ميلي ثانية من أجل عرض إطار . لاحظ أنه لا يوجد خيط يعمل بالقرب من حدود الإطار، حيث يُصيَّر مثل هذا التطبيق بمعدل 60 إطارًا في الثانية FPS.
+
كل تغيير في اللون هو عبارة عن إطار . تذكّر أنه يجب إنجاز جميع أعمال واجهة المستخدم الخاصة بك بنهاية فترة 16 ميلي ثانية من أجل عرض إطار واحد. لاحظ أنه لا يوجد خيط يعمل بالقرب من حدود الإطار، حيث يُصيَّر مثل هذا التطبيق بمعدل 60 إطارًا في الثانية FPS.
  
 
إذا لاحظت تقطيعًا chop، فقد ترى شيئًا كالشكل التالي:
 
إذا لاحظت تقطيعًا chop، فقد ترى شيئًا كالشكل التالي:
سطر 76: سطر 76:
 
إن حددت مشكلة JS ، فابحث عن أدلة في شيفرة JS المحدّدة التي تنفّذها. لاحظ في السيناريو أعلاه استدعاء <code>RCTEventEmitter</code> عدة مرات لكل إطار. يوضح الشكل التالي تكبيرًا لخيط JS من التعقّب السابق:
 
إن حددت مشكلة JS ، فابحث عن أدلة في شيفرة JS المحدّدة التي تنفّذها. لاحظ في السيناريو أعلاه استدعاء <code>RCTEventEmitter</code> عدة مرات لكل إطار. يوضح الشكل التالي تكبيرًا لخيط JS من التعقّب السابق:
 
[[ملف:1SystraceBadJS2.png|بديل=Systrace Bad JS|مركز|تصغير|338x338بك]]
 
[[ملف:1SystraceBadJS2.png|بديل=Systrace Bad JS|مركز|تصغير|338x338بك]]
هذا لا يبدو صحيحًا. لماذا يُستدعَى مرات متعددة؟ وهل هي في الواقع أحداث مختلفة؟ يُحتمَل أن تعتمد الإجابات على هذه الأسئلة على شيفرة المنتج الخاص بك، وسترغب غالبًا في الاطلاع على الدالة [https://reactjs.org/docs/react-component.html#shouldcomponentupdate shouldComponentUpdate].
+
هذا لا يبدو صحيحًا. لماذا يُستدعَى مرات متعددة؟ وهل هي في الواقع أحداث مختلفة؟ يُحتمَل أن تعتمد الإجابات عن هذه الأسئلة على شيفرة المنتج الخاصة بك، وسترغب غالبًا في الاطلاع على الدالة [[React/react component#shouldComponentUpdate.28.29|shouldComponentUpdate]].
  
 
=== حل مشاكل واجهة المستخدم الأصيلة ===
 
=== حل مشاكل واجهة المستخدم الأصيلة ===
 
إن حدّدت مشكلة في واجهة المستخدم الأصيلة، فسيكون هناك سيناريوهان عادةً هما:
 
إن حدّدت مشكلة في واجهة المستخدم الأصيلة، فسيكون هناك سيناريوهان عادةً هما:
  
# تتضمن واجهة المستخدم التي تحاول رسمها في كل إطار الكثير من العمل على وحدة معالجة الرسومياتGPU.
+
# تتضمن واجهة المستخدم التي تحاول رسمها في كل إطار الكثير من العمل على وحدة معالجة الرسوميات GPU.
 
# أو أنك تنشئ واجهة مستخدم جديدة أثناء الحركة / التفاعل (تحميل محتوى جديد أثناء التمرير مثلًا).
 
# أو أنك تنشئ واجهة مستخدم جديدة أثناء الحركة / التفاعل (تحميل محتوى جديد أثناء التمرير مثلًا).
  
 
==== الكثير من العمل على GPU ====
 
==== الكثير من العمل على GPU ====
سترى في السيناريو الأول تعقّبًا يحتوي على خيط واجهة المستخدم و / أو خيط التصيير كما يلي:
+
سترى في السيناريو الأول تعقّبًا يحتوي على خيط واجهة المستخدم و / أو خيط تصيير كما يلي:
 
[[ملف:SystraceBadUI1.png|بديل=Systrace Bad UI|مركز|تصغير|371x371بك]]
 
[[ملف:SystraceBadUI1.png|بديل=Systrace Bad UI|مركز|تصغير|371x371بك]]
لاحظ مقدار الوقت الطويل الذي يقضيه في <code>DrawFrame</code> الذي يتجاوز حدود الإطار، فهذا هو الوقت المستغرق في انتظار وحدة معالجة الرسوميات GPU لاستنزاف مخزن الأوامر المؤقت من الإطار السابق.
+
لاحظ مقدار الوقت الطويل الذي يقضيه في رسم <code>DrawFrame</code> الذي يتجاوز حدود الإطار، فهذا هو الوقت المستغرق في انتظار وحدة معالجة الرسوميات GPU لاستنزاف مخزن الأوامر المؤقت من الإطار السابق.
  
 
يمكنك التخفيف من ذلك من خلال:
 
يمكنك التخفيف من ذلك من خلال:
  
* التحقيق باستخدام <code>renderToHardwareTextureAndroid</code> للمحتوى المعقد والساكن الذي يجري تحريكه / تحويله (مثل شرائح <code>Navigator</code> أو حركات ألفا).
+
* التحقيق في استخدام <code>renderToHardwareTextureAndroid</code> للمحتوى المعقَّد والساكن الذي يجري تحريكه / تحويله (مثل شرائح <code>Navigator</code> أو حركات ألفا).
* تأكد من أنك لا تستخدم <code>needsOffscreenAlphaCompositing</code>، والذي يُعطَّل افتراضيًا، لأنه يزيد من الحمل كثيرًا لكل إطار على وحدة معالجة الرسوميات في معظم الحالات.
+
* تأكد من أنك لا تستخدم <code>needsOffscreenAlphaCompositing</code>، والتي تُعطَّل افتراضيًا، لأنها تزيد من التحميل كثيرًا لكل إطار على وحدة معالجة الرسوميات في معظم الحالات.
  
إن لم يساعدك ذلك وتريد التعمق أكثر في ما تفعله وحدة معالجة الرسوميات بالفعل، فيمكنك التحقق من [http://www.androiddocs.com/tools/help/gltracer.html Tracer for OpenGL ES].
+
إن لم يساعدك ذلك وتريد التعمق أكثر في ما تفعله وحدة معالجة الرسوميات بالفعل، فيمكنك التحقق من المتعقّب [http://www.androiddocs.com/tools/help/gltracer.html Tracer for OpenGL ES].
 
 
إنشاء عروض جديدة على خيط واجهة المستخدم
 
  
 +
==== إنشاء عروض جديدة على خيط واجهة المستخدم ====
 
سترى في السيناريو الثاني شيئًا كما يلي:
 
سترى في السيناريو الثاني شيئًا كما يلي:
 
[[ملف:SystraceBadCreateUI1.png|بديل=Systrace Bad Create UI|مركز|تصغير|426x426بك]]
 
[[ملف:SystraceBadCreateUI1.png|بديل=Systrace Bad Create UI|مركز|تصغير|426x426بك]]

مراجعة 17:16، 24 يونيو 2021

فحص الأداء Profiling

استخدم فاحص أداء مبني مسبقًا للحصول على معلومات مفصَّلة حول العمل المنجز في خيط JavaScript والخيط الرئيسي main thread معًا، حيث يمكنك الوصول إلى فاحص الأداء عن طريق تحديد الخيار Perf Monitor من قائمة Debug.

تُعَد الأداة Instruments أداةً قيّمة في نظام iOS كالأداة systrace على نظام Android التي يجب أن تتعلمها. لكن تأكد أولًا من إيقاف وضع التطوير، حيث يجب أن ترى ما يلي في سجلات تطبيقك:

__DEV__ === false, development-level warning are OFF, performance optimizations are ON

هناك طريقة أخرى لفحص أداء شيفرة JavaScript وهي استخدام فاحص أداء Chrome أثناء تصحيح الأخطاء debugging. لن تمنحك هذه الطريقة نتائجًا دقيقة نظرًا لأن الشيفرة تعمل في Chrome ولكنها ستعطيك فكرة عامة عن مكان الاختناقات bottlenecks. شغّل فاحص الأداء ضمن تبويب الأداء Performance في Chrome، ثم سيظهر رسم بياني تحت User Timing. يمكنك عرض مزيد من التفاصيل بجدول من خلال النقر على تبويب Bottom Up في الأسفل ثم اختر DedicatedWorker Thread في القائمة العلوية اليسرى.

فحص أداء واجهة مستخدم Android باستخدام الأداة systrace

يدعم نظام Android أكثر من 10 آلاف هاتف مختلف وقد عُمَِم لدعم تصيير rendering البرمجيات، حيث تؤدي معمارية إطار العمل والحاجة إلى التعميم عبر العديد من العتاد المستهدَف للأسف إلى الحصول على حرية أقل بالموازنة مع نظام iOS. لكن هناك أحيانًا أشياء يمكنك تحسينها وليست أخطاء الشيفرة الأصيلة من بين هذه الأشياء على الإطلاق.

الخطوة الأولى لصحيح هذا الخطأ هي الإجابة عن السؤال الأساسي حول المكان الذي تقضي فيه وقتك خلال كل إطار زمنه 16 ميلي ثانية. لذلك سنستخدم فاحص أداء نظام Android معياري يسمى systrace.

systrace هي أداة فحص أداء مستندة إلى علامات Android معيارية (وتُثبَّت عند تثبيت حزمة أدوات منصة Android). تُحاط كتل الشيفرة المفحوصة بعلامات البداية / النهاية والتي تُصوَّر بعد ذلك ضمن تنسيق مخطط ملون. يوفر كلٌّ من إطار عمل Android SDK و React Native علامات معيارية يمكنك تصوّرها.

1. جمع التعقّب trace

صِل أولًا جهازًا يُظهر الخلل الذي تريد فحصه بحاسوبك عبر وصلة USB واجعله يصل إلى النقطة التي تسبق الانتقال أو التحرك الذي تريد فحصه مباشرةً. شغّل systrace كما يلي:

$ <path_to_android_sdk>/platform-tools/systrace/systrace.py --time=10 -o trace.html sched gfx view -a <your_package_name>

لنفصّل الأمر السابق:

  • time هو طول وقت جمع التعقّب مقدرًا بالثواني.
  • sched و gfx و view هي وسوم android SDK (مجموعات من الوسوم) التي يجب الاهتمام بها، حيث يمنحك الوسم sched معلومات حول ما يجري تشغيله على كل نواة من هاتفك، ويمنحك الوسم gfx معلومات عن الرسوميات مثل حدود الإطار، ويمنحك الوسم view معلومات حول القياس والتخطيط ورسم التمريرات.
  • ‏‏تفعّل ‎-a <your_package_name>‎‏‏ العلامات markers الخاصة بالتطبيق، وتحديدًا تلك المدمَجة في إطار عمل React Native. يمكن العثور على اسم حزمتك your_package_name في ملف AndroidManifest.xml الخاص بتطبيقك الذي يكون بالشكل com.example.app.

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

2. قراءة التعقّب

يجب أن يظهر لك الشكل التالي بعد فتح التعقّب في متصفحك (يفضَّل استخدام Chrome):

Systrace Example

ملاحظة: استخدم مفاتيح WASD للتحديد والتقريب.

إن لم يُفتَح ملف التعقّب ‎.html الخاص بك بصورةٍ صحيحة، فتحقّق من وجود ما يلي في وحدة تحكم المتصفح:

Type Error

بما أن Object.observe اُهمِل في المتصفحات الحديثة، فقد تضطر إلى فتح الملف من أداة Google Chrome Tracing عن طريق:

  • افتح النافذة chrome://tracing في chrome.
  • اختر تحميل load.
  • اختر ملف html المنشَأ من الأمر السابق.

تفعيل الخيار VSync highlighting: حدد مربع الاختيار التالي في أعلى يمين الشاشة لتحديد حدود الإطار الذي مدته 16 ميلي ثانية:

Enable VSync Highlighting

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

3. البحث عن العملية الخاصة بك

مرّر حتى ترى (جزءًا من) اسم حزمتك. قد تفحص أداء com.facebook.adsmanager على سبيل المثال، والذي يظهر كالاسم book.adsmanager بسبب حدود اسم الخيط thread في النواة.

سترى على الجانب الأيسر مجموعة من الخيوط التي تتوافق مع صفوف الخط الزمني الموجودة على اليمين. هناك عدد قليل من الخيوط التي تهمنا مثل : خيط واجهة المستخدم (الذي يحتوي على اسم حزمتك أو الاسم UI Thread)، والخيط mqt_js، والخيط mqt_native_modules. إن استخدمت Android 5+‎ ، فيجب الاهتمام أيضًا بالخيط Render Thread.

  • خيط واجهة المستخدم UI Thread: هو المكان الذي يحدث فيه القياس / التخطيط / الرسم المعياري لنظام Android. سيكون اسم الخيط الموجود على اليمين هو اسم حزمتك (book.adsmanager على سبيل المثال) أو خيط واجهة المستخدم UI Thread. يجب أن تبدو الأحداث التي تراها في هذا الخيط كالشكل التالي، ويجب أن تكون مرتبطة بـ Choreographer و traversals و DispatchUI:
UI Thread
  • خيط JS.: وهو مكان تنفيذ شيفرة JavaScript. سيكون اسم الخيط إما mqt_js أو <...> اعتمادًا على مدى تعاون النواة على جهازك. يمكن تحديد هذا الخيط إن لم يكن له اسم من خلال البحث عن أشياء مثل JSCall و Bridge.executeJSCall وما إلى ذلك:
JS Thread
  • خيط الوحدات الأصيلة Native Modules Thread: وهو مكان تنفيذ استدعاءات الوحدة الأصيلة (مثل UIManager). سيكون اسم الخيط إما mqt_native_modules أو <...>. يمكن تحديده في الحالة الأخيرة من خلال البحث عن أشياء مثل NativeCall و callJavaModuleMethod و onBatchComplete:
Native Modules Thread
  • خيط التصيير Render Thread (خيط إضافي): إن استخدمت Android L (5.0) أو الأحدث، فسيكون لديك أيضًا خيط تصيير في تطبيقك. ينشئ هذا الخيط أوامر OpenGL الفعلية المستخدمة في رسم واجهة المستخدم الخاصة بك. سيكون اسم الخيط إما RenderThread أو <...>. يمكنك تحديده في الحالة الأخيرة من خلال البحث عن أشياء مثل DrawFrame و queueBuffer:
Render Thread

تحديد المسؤول عن المشكلة

يجب أن يبدو التحريك كما يلي:

Systrace Well Behaved

كل تغيير في اللون هو عبارة عن إطار . تذكّر أنه يجب إنجاز جميع أعمال واجهة المستخدم الخاصة بك بنهاية فترة 16 ميلي ثانية من أجل عرض إطار واحد. لاحظ أنه لا يوجد خيط يعمل بالقرب من حدود الإطار، حيث يُصيَّر مثل هذا التطبيق بمعدل 60 إطارًا في الثانية FPS.

إذا لاحظت تقطيعًا chop، فقد ترى شيئًا كالشكل التالي:

Systrace Bad JS

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

قد ترى أيضًا شيئًا كالشكل التالي:

Systrace Bad UI

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

حل مشاكل جافا سكريبت

إن حددت مشكلة JS ، فابحث عن أدلة في شيفرة JS المحدّدة التي تنفّذها. لاحظ في السيناريو أعلاه استدعاء RCTEventEmitter عدة مرات لكل إطار. يوضح الشكل التالي تكبيرًا لخيط JS من التعقّب السابق:

Systrace Bad JS

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

حل مشاكل واجهة المستخدم الأصيلة

إن حدّدت مشكلة في واجهة المستخدم الأصيلة، فسيكون هناك سيناريوهان عادةً هما:

  1. تتضمن واجهة المستخدم التي تحاول رسمها في كل إطار الكثير من العمل على وحدة معالجة الرسوميات GPU.
  2. أو أنك تنشئ واجهة مستخدم جديدة أثناء الحركة / التفاعل (تحميل محتوى جديد أثناء التمرير مثلًا).

الكثير من العمل على GPU

سترى في السيناريو الأول تعقّبًا يحتوي على خيط واجهة المستخدم و / أو خيط تصيير كما يلي:

Systrace Bad UI

لاحظ مقدار الوقت الطويل الذي يقضيه في رسم DrawFrame الذي يتجاوز حدود الإطار، فهذا هو الوقت المستغرق في انتظار وحدة معالجة الرسوميات GPU لاستنزاف مخزن الأوامر المؤقت من الإطار السابق.

يمكنك التخفيف من ذلك من خلال:

  • التحقيق في استخدام renderToHardwareTextureAndroid للمحتوى المعقَّد والساكن الذي يجري تحريكه / تحويله (مثل شرائح Navigator أو حركات ألفا).
  • تأكد من أنك لا تستخدم needsOffscreenAlphaCompositing، والتي تُعطَّل افتراضيًا، لأنها تزيد من التحميل كثيرًا لكل إطار على وحدة معالجة الرسوميات في معظم الحالات.

إن لم يساعدك ذلك وتريد التعمق أكثر في ما تفعله وحدة معالجة الرسوميات بالفعل، فيمكنك التحقق من المتعقّب Tracer for OpenGL ES.

إنشاء عروض جديدة على خيط واجهة المستخدم

سترى في السيناريو الثاني شيئًا كما يلي:

Systrace Bad Create UI

لاحظ أن خيط JS ينتظر قليلًا أولًا، ثم ترى بعض الأعمال المنجزة على خيط الوحدات الأصيلة، متبوعًا بعملية اجتياز باهظة الثمن على خيط واجهة المستخدم.

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

مصادر