فلدي الذهاب بسرعة: بناء للسرعة في دائرة الرقابة الداخلية. الجزء 1



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

تستند المقالة إلى الحديث الرئيسي الذي ألقاه Luke Parham ، وهو حاليًا مهندس iOS في Apple ومؤلف برامج تعليمية لتطوير iOS على RayWenderlich.com ، في مؤتمر مطوري الهواتف المحمولة الدولي MBLT DEV 2017 .

"يا شباب. دعنا نقول ، إذا أمكنك ذلك ، فيمكنك حلاقة 10 ثوانٍ من وقت التشغيل ، واضربها بخمسة ملايين مستخدم و 50 مليون ثانية كل يوم. أكثر من عام ، هذا هو على الأرجح عشرات من العمر. لذا ، إذا قمت بتسريع عملية التمهيد بعشر ثوانٍ ، فقد أنقذت عشرات الأرواح. هذا حقا يستحق كل هذا العناء ، لا تظن؟ "

ستيف جوبز حول الأداء (وقت تشغيل Apple II).

الأداء في دائرة الرقابة الداخلية أو كيفية النزول الرئيسي


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

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

انخفض الإطارات


القاعدة رقم 1: استخدم CADisplayLink لتتبع الإطارات التي تم إسقاطها


CADisplayLink هو مؤقت خاص يطلق على Vsync. يكون Vsync عندما يعرض التطبيق على الشاشة ، ويحدث كل 16 مللي ثانية. لأغراض الاختبار ، في AppDelegate الخاص بك ، يمكنك إعداد CADisplayLink المضافة إلى حلقة التشغيل الرئيسية وبعد ذلك يكون لديك وظيفة أخرى حيث تقوم ببعض الرياضيات. بعد ذلك ، يمكنك تتبع مدة تشغيل التطبيق وطول المدة التي انقضت منذ آخر مرة تم فيها تشغيل هذه الوظيفة. ومعرفة ما إذا كان يستغرق أكثر من 16 ميلي ثانية.



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

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



لا يحب المستخدمون مثل هذه التجربة خاصةً إذا كان التطبيق يدعم الأجهزة القديمة مثل iPhone 5 ، iPods القديمة ، إلخ.

بروفيل الوقت


من المحتمل أن يكون Time Profiler الأداة الأكثر فائدة لتتبع الأشياء. الأدوات الأخرى مفيدة ، لكن في النهاية ، في Fyusion نستخدم Time Profiler مثل 90٪ من الوقت. المشتبه بهم المعتادون في التطبيق هم شريط التمرير والنص والصور.

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

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

مثال تتبع





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

في كثير من الأحيان ، عندما تبدأ في النظر إلى هذا الأمر ، يبدو الأمر رائعًا للغاية. لديك شعور في بعض الأحيان: "ما هو كل هذا القمامة؟ لا أعرف ماذا يعني هذا "FRunLoopDoSource0".

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

شجرة الدعوة


على سبيل المثال ، لدينا تطبيق بسيط حقًا له الوظيفة الرئيسية ، ثم يستدعي عدة طرق داخل التطبيق الرئيسي. ما يفعله منشئ ملفات التعريف هو أنه يأخذ لقطة من أي شيء تتبع المكدس الخاص بك الآن بشكل افتراضي كل ميلي ثانية. ثم تنتظر مللي ثانية وتلتقط لقطة ، حيث قمت بالاتصال بـ "main" والتي تسمى "foo" والتي تسمى "bar". يوجد تتبع المكدس الأول على لقطة الشاشة. بحيث يتم جمعها. لدينا هذه التهم: 1 ، 1 ، 1.



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



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

علاوة على ذلك ، تم استدعاء طريقة واحدة داخل أخرى تستدعي الطريقة الثالثة. نرى أن "buz" كان يسمى مرتين. لكنها طريقة صغيرة تحدث بين ميلي ثانية واحدة.

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



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



في الواقع ، في Mac ، بشكل عام ، يمكنك النقر بزر الماوس الأيمن على مثلثات الكشف وسيتم فتحها بطريقة سحرية وتظهر لك ما هو أهم شيء في ذلك. سوف يسقط إلى كل ما يقوم به معظم العمل. و 90 ٪ من الوقت سيكون CFRunLoopRun ، ثم الاسترجاعات.



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

إذا بحثنا في أحد هذه الأمور ، يمكننا أن نرى مثل هذه الأشياء حيث يسهل حقًا النظر إليها ، وتكون مثل: "واو ، لا أعرف ما الذي يفعله هذا". مثل يجعل ، مزود الصور ، IO.



هناك خيار حيث يمكنك إخفاء مكتبات النظام. من المغري حقًا الإخفاء ، ولكن في الواقع ، هذا هو في الواقع أكبر عنق الزجاجة في التطبيق.

هناك أوزان توضح النسبة المئوية للعمل الذي تقوم به هذه الوظيفة أو الطريقة. وإذا انتقلنا إلى المثال ، فلدينا 34٪ ويحدث ذلك بسبب Apple jpeg_decode_image_all. بعد قليل من البحث ، يصبح من الواضح أنه يعني أن فك تشفير JPEG يحدث على الخيط الرئيسي ويسبب غالبية قطرات الإطار.



القاعدة رقم 2


بشكل عام ، من الأفضل فك تشفير ملفات JPEG في الخلفية. تقوم معظم مكتبات الطرف الثالث (AsyncDisplayKit و SDWebImage ، ...) بذلك خارج الصندوق. إذا كنت لا ترغب في استخدام الأطر ، يمكنك القيام بذلك بنفسك. ما تفعله هو تمرير صورة ، في هذه الحالة ، هو امتداد لـ UIImage ، ثم تقوم بإعداد سياق وترسم الصورة يدويًا في سياق إلى CGBitmap.



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

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



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

تحذيرات الذاكرة


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

حدث هذا في تطبيق Fyuse. إذا كنت أقفز إلى مؤشر ترابط في الخلفية ، فك تشفير جميع ملفات JPEG الخاصة بي ، في بعض الحالات على الهواتف القديمة ، فإن النظام سيقتلها على الفور. وذلك لأنه يرسل تحذيرًا من الذاكرة يقول مثل: "مهلا! تخلص من ذاكرتك "لكن قوائم الانتظار في الخلفية لا تستمع. ماذا يحدث إذا كنت تقوم بتخصيص كل هذه الصور ثم تعطل في كل مرة. الالتفاف حول هذا هو تنفيذ الأمر ping لمؤشر الترابط الرئيسي من مؤشر ترابط الخلفية.



بشكل عام ، الموضوع الرئيسي هو قائمة انتظار. الحصول على قائمة الانتظار الأشياء وتحدث في الموضوع الرئيسي. عندما تذهب إلى الخلفية في Objective-C ، يمكنك استخدام performSelectorOnMainThread: withObject: waitUntilDone:. سيؤدي ذلك إلى وضعه في نهاية سطر قوائم الانتظار الرئيسية ، لذا إذا كانت قائمة الانتظار الرئيسية مشغولة بمعالجة تحذيرات الذاكرة ، فستنتقل وظيفة استدعاء هذه إلى نهاية السطر وتنتظر معالجة تحذيرات الذاكرة قبل أن تقوم بكل هذا التخصيص الكبير لل الذاكرة

في سويفت ، الأمر أبسط. يمكنك أن تفعل كتلة فارغة الرئيسية إيفاد متزامن على الرئيسي.

فيما يلي مثال حيث قمنا بتنظيف الأشياء ونقوم بفك تشفير الصور في قوائم الانتظار في الخلفية. والتمرير بصريا هو أجمل كثيرا. لا نزال نواجه انخفاضًا في الإطار ، لكن هذا على جهاز iPod 5g ، لذا فهو أحد أسوأ الأشياء التي يمكنك اختبارها والتي لا تزال تدعم مثل iOS 10 و 11.



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

خلاصة القول ، الأمر ليس بهذه السهولة دائمًا ، ولكن إذا كان لديك أشياء صغيرة تستغرق الكثير من الوقت ، فيمكنك القيام بها في الخلفية.

تأكد من أنها ليست ذات صلة UIKit. كثير من فئات UIKit غير آمنة لمؤشر الترابط ولا يمكنك تخصيص UIView في الخلفية.

استخدم Core Graphics إذا كنت بحاجة إلى القيام بأشياء صورة في الخلفية. لا تخفي مكتبات النظام. ولا تنس تحذيرات الذاكرة.

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

فيديو


شاهد الحديث الكامل هنا:

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


All Articles