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

هذا ما نريد أن نراه: نتيجة ذات دلالة إحصائية لمقارنة نسختين من التطبيق الخاص بك ببعض المقاييس المهمة. تابع القراءة لمعرفة كيف.
هناك بعض الإرشادات العامة لتحسين الأداء في Flutter:
- إشراك أقل عدد ممكن من الحاجيات عند تحديث الحالة.
- تحديث الحالة فقط عند الضرورة.
- احصل على مهام مكثفة حسابيًا من أساليب
build
الخاصة بك ومن الناحية المثالية من العزلة الرئيسية.
الحقيقة المحزنة هي أنه بالنسبة للعديد من الأسئلة حول تحسين الأداء ، سيكون الجواب "كم هو محظوظ". هل هذا التحسين المعين يستحق الجهد وتكلفة الصيانة لهذه القطعة المعينة؟ هل هذا النهج بعينه منطقي في هذا الموقف بالذات؟
الجواب الوحيد المفيد لهذه الأسئلة هو الاختبار والقياس. حدد كيف يؤثر كل اختيار على الأداء واتخاذ القرارات بناءً على هذه البيانات.
والخبر السار هو أن Flutter يوفر أدوات تعريف أداء رائعة مثل Dart DevTools (حاليًا في إصدار المعاينة) ، والذي يتضمن Flutter Inspector ، أو يمكنك استخدام Flutter Inspector مباشرة من Android Studio (مع تثبيت البرنامج المساعد Flutter). لديك Flutter Driver
لاختبار التطبيق ووضع Profile mode
لحفظ معلومات الأداء.
الأخبار السيئة هي أن الهواتف الذكية الحديثة ذكية للغاية.
المشكلة مع المنظمين
يعد قياس أداء تطبيق الرفرفة أمرًا صعبًا للغاية بالنسبة لوحدات تحكم iOS و Android. تتحكم هذه الشياطين على مستوى النظام في سرعة المعالجات المركزية والرسومات اعتمادًا على الحمل. بالطبع ، هذا جيد بشكل أساسي ، لأنه يوفر التشغيل السلس مع استهلاك أقل للبطارية.
العيب هو أنه يمكنك جعل طلبك أسرع بكثير عن طريق زيادة حجم العمل الذي يؤديه.
يمكنك أدناه رؤية كيف أدت إضافة دورة من مكالمات الطباعة التي لا معنى لها إلى التطبيق إلى جعل المنظم يقوم بتحويل وحدة المعالجة المركزية إلى تردد متزايد ، مما جعل التطبيق أسرع كثيرًا وأدائه يمكن التنبؤ به.

مشكلة المنظمين: بشكل افتراضي ، لا يمكنك الوثوق بأرقامك. في هذا المخطط التوضيحي الممتد ، لدينا تشغيلات منفصلة على المحور س (يتم تمييزه بالوقت المحدد لبدء تشغيله) ووقت الإنشاء على المحور ص. كما ترون ، عندما نقدم بعض عبارات الطباعة غير الضرورية تمامًا ، فإن هذا يؤدي إلى حقيقة أن وقت البناء ينخفض لكن ليس فوق.
في هذه التجربة ، أسفر أسوأ رمز عن وقت بناء أسرع (انظر أعلاه) ، ووقت تنقيط أسرع ، ومعدل إطار أعلى. عندما يؤدي كود أسوأ موضوعيًا إلى تحسين مؤشرات الأداء ، لا يمكنك الاعتماد على هذه المؤشرات كدليل (توصية).
هذا مجرد مثال واحد على كيف يمكن أن يكون اختبار أداء تطبيقات الأجهزة المحمولة بديهيًا ومعقدًا.
أدناه ، أشارك بعض النصائح التي قمت بجمعها أثناء العمل على تطبيق Flutter's Developer Quest لجوجل I / O.
نصائح عامة
- لا تقيس الأداء في وضع التصحيح (
DEBUG mode
). قياس الأداء فقط في Profile mode
ملف التعريف. - قم بالقياس على جهاز حقيقي ، وليس على iOS Simulator أو Android Emulator. تعد برامج محاكاة البرامجيات رائعة بالنسبة للتطوير ، ولكنها تتميز بخصائص أداء مختلفة عن الخصائص الحقيقية. لن يسمح لك Flutter بالعمل في وضع التنميط على جهاز محاكاة ، لأنه لا معنى له. البيانات التي تجمعها بهذه الطريقة لا تنطبق على الأداء الحقيقي.
- من الناحية المثالية استخدام نفس الجهاز الفعلي. اجعله جهاز اختبار الأداء مخصصًا ولا تستخدمه أبدًا في أي شيء آخر.
- استكشاف أدوات التنميط أداء الرفرفة.
المنظمين وحدة المعالجة المركزية / GPU
كما نوقش أعلاه ، فإن أنظمة التشغيل الحديثة تغير وتيرة كل معالج و GPU تحت تصرفهم وفقا للحمل وبعض الاستدلال الأخرى. (على سبيل المثال ، يؤدي لمس الشاشة عادةً إلى زيادة سرعة هاتف Android.)
على Android ، يمكنك تعطيل عناصر التحكم هذه. نحن نسمي هذه العملية "قفل التحجيم".
- قم بإنشاء برنامج نصي يعطل عناصر التحكم على جهازك لاختبار الأداء. يمكنك استخدام مثال Skia للإلهام. يمكنك أيضًا التحقق من واجهة برمجة تطبيقات Unix CPU .
- قد تحتاج إلى شيء أقل تنوعا وأخف وزنا إذا كنت لا تفعل الكثير من العمل مثل اختبار Skia. تحقق من البرنامج النصي shell في Developer Quest لمعرفة أين تذهب. على سبيل المثال ، يقوم الجزء التالي من البرنامج النصي بتعيين وحدة المعالجة المركزية لوحدة تحكم مساحة المستخدم (وحدة التحكم الوحيدة التي لا تغير تردد المعالج نفسه).
- هدفك هنا ليس محاكاة الأداء الحقيقي (لا يقوم المستخدمون بإيقاف تشغيل المنظمين على أجهزتهم) ، ولكن لديك مؤشرات أداء قابلة للمقارنة بين التشغيلات.
- في النهاية ، تحتاج إلى تجربة البرنامج النصي shell وتكييفه مع الجهاز الذي ستستخدمه. يعمل هذا ، ولكن حتى تقوم بذلك ، ستخدعك بيانات أدائك.

إصدار سابق من Developer Quest ، تم اختباره باستخدام Flutter Driver على سطح المكتب.
سائق الرفرفة
يسمح لك برنامج Flutter Driver باختبار تطبيقك تلقائيًا. اقرأ قسم "ملفات تعريف الأداء" على flutter.dev لمعرفة كيفية استخدامها عند تحديد ملامح تطبيقك.
- لاختبار الأداء ، لا تختبر تطبيقك يدويًا. استخدم دائمًا برنامج Flutter Driver للحصول على بيانات إرشادية حقًا.
- اكتب رمز Flutter Driver الخاص بك حتى يتحقق ما تريد قياسه حقًا. إذا كنت بحاجة إلى الأداء العام للتطبيق ، فحاول المرور عبر جميع أجزاء التطبيق وتفعل ما سيفعله المستخدم.
- إذا كان التطبيق الخاص بك يحتوي على عنصر العشوائية (
Random
، أحداث الشبكة ، وما إلى ذلك) ، ثم إنشاء "وهمية" لمثل هذه الحالات. يجب أن يكون الاختبار التشغيلي أقرب ما يكون إلى الآخر. - إذا أردت ، يمكنك إضافة أحداث مخصصة إلى
startSync()
الزمني باستخدام startSync()
و finishSync()
لفئة الخط الزمني . قد يكون ذلك مفيدًا إذا كنت مهتمًا بأداء وظيفة معينة. ضع startSync()
في بدايته و finishSync()
في نهايته. - احفظ كل من الملخص ( writeSummaryToFile ) ، والأهم من ذلك ، الجدول الزمني الخام ( writeTimelineToFile ).
- اختبار كل إصدار من التطبيق الخاص بك عدة مرات. لمطوري كويست ، قضيت 100 بداية. (عندما تقيس الأشياء التي قد تكون صاخبة ، مثل استخدام مقياس P99 ، فقد تحتاج إلى مزيد من التشغيل.) بالنسبة للأنظمة المستندة إلى POSIX ، هذا يعني ببساطة القيام بشيء مثل التالي: من
for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done

أداة الجدول الزمني لـ Chrome للتحقق من نتائج ملفات التعريف في Flutter.
جدول زمني
الجدول الزمني هو الناتج الخام لنتائج التنميط الخاص بك. يكتب Flutter هذه المعلومات في ملف JSON ، والذي يمكن تنزيله في chrome://tracing
.
- فهم كيفية فتح الجدول الزمني الكامل في Chrome. يمكنك ببساطة فتح
chrome://tracing
في متصفح Chrome ، انقر فوق "تحميل" وحدد ملف JSON. يمكنك قراءة المزيد في هذا الدليل المختصر . (هناك أيضًا أداة جدول زمني للرفرفة موجودة حاليًا في المعاينة الفنية. لم أستخدمها لأن مشروع Developer Quest تم إطلاقه قبل أن تكون أدوات الرفرفة جاهزة.) - استخدم مفاتيح WSAD للتنقل في المخطط الزمني في
chrome://tracing
و 1234 لتغيير أوضاع التشغيل. - عند إعداد اختبار الأداء لأول مرة ، فكر في تشغيل Flutter Driver باستخدام أداة Systrace Android. يمنحك هذا فكرة أفضل عما يجري فعليًا في الجهاز ، بما في ذلك معلومات حول قياس وتيرة المعالج. لا تقيس التطبيق بالكامل باستخدام Systrace ، لأن هذا سيجعل كل شيء أبطأ وأقل قابلية للتنبؤ به.
- كيفية تشغيل Android Systrace مع Flutter Driver؟ أولاً ، قم بتشغيل Android Systrace باستخدام
/path/to/your/android/sdk/platform-tools/systrace/systrace.py --atrace-categories=gfx,input,view,webview,wm,am,sm,audio,video,camera,hal,app,res,dalvik,rs,bionic,power,pm,ss,database,network,adb,pdx,sched,irq,freq,idle,disk,load,workq,memreclaim,regulators,binder_driver,binder_lock
. ثم flutter run test_driver/perf.dart --profile --trace-systrace
التطبيق flutter run test_driver/perf.dart --profile --trace-systrace
. أخيرًا ، قم بتشغيل flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/
Driver flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/
(حيث NNNNN هو المنفذ الذي يمنحك تطبيق الرفرفة أعلاه).
المقاييس
من الأفضل أن ننظر إلى أكبر عدد ممكن من المقاييس ، لكنني قررت أن بعضها أكثر فائدة من غيرها.
يعد وقت البناء ووقت التنقيط (المقاييس التي يتم توفيرها افتراضيًا باستخدام TimelineSummary
) مفيدة فقط لاختبارات الأداء القاسية للغاية ، والتي لا تتضمن الكثير غير إنشاء واجهة مستخدم.
لا تفكر في TimelineSummary.frameCount
كطريقة لحساب الإطارات في الثانية (FPS). أدوات التشكيل الجانبي للرفرفة لا توفر معلومات معدل الإطار الحقيقي. يوفر TimelineSummary
طريقة countFrames()
، لكنه يحسب فقط عدد مجموعات الإطارات المكتملة. سيكون للتطبيق المحسّن بشكل جيد والذي يحد من عمليات إعادة البناء غير الضرورية (التحديثات) عدد أقل من FPS مقارنة بالتطبيق غير المُحسّن الذي يعيد البناء كثيرًا.
أنا شخصياً أحصل على البيانات الأكثر فائدة عن طريق قياس إجمالي وقت المعالج الذي يقضيه في تنفيذ رمز Dart. هذا يحسب الكود الذي يتم تنفيذه في أساليب build
الخاصة بك وخارجها. بافتراض إجراء اختبارات تحديد ملامح على جهاز مقفل ، يمكن اعتبار إجمالي وقت وحدة المعالجة المركزية تقريبًا جيدًا لعدد البطاريات التي يستهلكها التطبيق أكثر / أقل.

أسهل طريقة لمعرفة إجمالي وقت المعالج الذي يقضيه في تنفيذ تعليمات برمجية Dart هي تقدير عدد الأحداث MessageLoop:FlushTasks
الزمني. بالنسبة إلى Developer Quest ، كتبت أداة Dart لاستخراجها.
للعثور على خردة (سلة المهملات) (أي ، الإطارات المسقطة) ، ابحث عن التطرف. على سبيل المثال ، بالنسبة لحالة معينة من Developer Quest والجهاز الذي اختبرناه ، من المفيد إلقاء نظرة على وقت الإنشاء للنسبة المئوية 95. (كان وقت إنشاء النسبة المئوية التسعين مشابهًا للغاية ، حتى لو قارنت الكود بمستويات مختلفة تمامًا من الأداء ، وأرقام المئوية التاسعة والتسعين عادة ما تكون صاخبة. قد يختلف أدائك.)

كما ذكر أعلاه ، اختبار كل إصدار من التطبيق الخاص بك عدة (ربما 100) مرات. ثم استخدم البيانات المتوسطة أو المئوية مع حقول الخطأ. الأفضل من ذلك ، استخدام الرسوم البيانية تمتد.
النتائج
بعد التوليف ، يمكنك بثقة مقارنة الالتزامات وإجراء التجارب. أدناه يمكنك رؤية الإجابة على معضلة مشتركة: "هل هذا التحسين في تكاليف الصيانة يستحق كل هذا العناء؟"

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