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

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

هذا صحيح. تحسين وقت الترجمة قد عاد! * بعد الترقية ، ذهب وقت التحويل البرمجي من حوالي 17 ثانية إلى 6.3 ثانية.

* (After Unity 5.2.4 ، تحتوي معظم الإصدارات على خطأ مترجم ينفي إستراتيجية تحسين وقت الترجمة الأكثر فعالية)

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

في الصورة: لا يكفي الفرح.

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

لذلك ، ها هي استراتيجيتي الشخصية في محاربة وقت الترجمة:

1. الحصول على الحقائق

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

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

ولكن عليك أولاً أن تعرف وقتك في الترجمة. وتريد أن تتبع ذلك دائمًا ، لذلك لا تحقق أي شيء يزيده بشكل كبير. تذكر كل الوقت الضائع؟ لحل ذلك ، لقد كتبت ملحق محرر يمكنك تنزيله من Github هنا.

2. تحسين!

قبل أن نحسن ، اسمحوا لي أن أقدم لكم بعض المعلومات الأساسية عن كيفية عمل كل هذا. في اللحظة التي تقوم فيها بإجراء تغيير على الكود ، تعيد الوحدة ترجمة التعليمات البرمجية الخاصة بك إلى .dll (رمز مترجم) يسمى التجميع CSharp.dll (أو التجميع - UnityScript ، وما إلى ذلك إذا لم تكن تكتب في C #).

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

أشياء يجب ملاحظتها:

  • نظرًا للترتيب الذي تم فيه ترجمة هذه dlls ، فلن يكون بإمكان الكود الموجود داخل firstpass.dll الرجوع إلى الكود الموجود خارجها.
  • سيؤدي تغيير التعليمات البرمجية داخل المجلدات الخاصة إلى إعادة ترجمة كل من .dlls وإنكار أي مكاسب تحسين.

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

ومع ذلك ، فقد وجدت مشكلة في سحب وإفلات جميع أصولي الخارجية إلى مجلد الإضافات. تعتمد بعض هذه الأصول على مواردها الموجودة في مسارها الأصلي المستوردة وتتوقف بشكل فظيع عندما لا يكون الأمر كذلك. لتوفير الوقت ، اشتريت Optimizer Mad Compile Time (15 دولارًا) *** ، لأنه يترك الملفات غير الشفرة في مكانها ويأتي أيضًا مع ميزة Revert اللطيفة.

*** أنا لست مرتبطًا بـ Mad Compile Time Optimizer بأي طريقة.

3. انظر إلى المشتبه بهم الآخرين

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

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

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

لتحليل مثيلات InitializeOnLoad ، قمت بتسجيل الوقت المستغرق من بداية إلى نهاية أي مُنشئ ثابت برمز يبحث المشبوه. كانت معظم مثيلات InitializeOnLoad غير ضارة (0.0–0.2s) ، لكنني واجهت فئة واحدة كانت تستغلها لتحميل موارد ذاكرة التخزين المؤقت. لقد غيرت قطعة الكود المخالفة إلى ذاكرة التخزين المؤقت بتكاسل عند الحاجة ثم انتقلت.

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

التصور هو أسهل طريقة لتحديد أولويات الملفات التي تستحق إلقاء نظرة عليها. لقد استخدمت GrandPerspective (Mac) لأنه يمكن تصفية النتائج حسب القواعد المخصصة. انتهى بي الأمر بإنشاء مرشح يطابق الأسماء التي تنتهي بـ .cs وآخر لإزالة الملفات التي تحتوي على مسارات "المكونات الإضافية" أو "الأصول القياسية".

هذا ما تشبه قاعدة بيانات مشروعي في نهاية التحسين. لاحظ أن الكود الشخصي هو الكود الوحيد الذي يتم تجميعه بعد التغيير!

نعم ، هذا هو كل رمز. بعض هذه الفئات TextMeshPro ضخمة.

TL، DR:

  • يتم إصلاح المجلدات الخاصة في الوحدة 5.3.5p7
  • دائما تتبع وقت الترجمة الخاص بك (ترجمة الوقت المقتفي)
  • تحسين عن طريق نقل أصول الطرف الثالث إلى الأصول / الإضافات أو الأصول / الأصول القياسية (أوصي بـ Mad Compile Time Optimizer)
  • لا تسيء الاستخدام [InitializeOnLoad]

هل تهتم بالتحقق من صحة اللعبة تلقائيًا لمنع حدوث أي تصدع؟ أو ربما باستخدام الرسوم المتحركة كآلية محدودة بدلاً من بناء تطبيقك الخاص؟ تحقق من مقالاتي الأخرى!