تحسين وقت البناء - الجزء الأول

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

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

ماذا نقيس؟


أول شيء يجب علينا فعله هو تحديد ما نحاول قياسه وتحسينه. يمكن اعتبار خيارين:

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

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

نحسب وقت التجميع


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

تقرير وقت بناء كودكس


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

صورة

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

defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES



صورة



ملخص وقت بناء المشروع في Xcode


Xcode Build Time Summary - صديقك الأول للحصول على إحصائيات وقت البناء والاختناقات. يمكنك تشغيله من خلال Product-> Perform Action-> Build with Timing Summary . سترى الآن تقسيمًا كبيرًا للوقت الذي يقضيه في المهام المختلفة:

صورة

يجب أن تكون هذه الطريقة نقطة بداية جيدة للعثور على معظم المهام التي تستغرق وقتًا طويلاً في عملية التجميع. الصورة أعلاه يظهر أن CompileStoryboard ، CompileXIB ، CompileSwiftSources، و PhaseScriptExecution مراحل حملوا أكثر من مرة بناء. كان Xcode قادرًا على إكمال جزء من المهام بالتوازي ، لذلك يتم الانتهاء من التجميع بشكل أسرع بكثير من الوقت اللازم لإكمال مهمة كل أمر.

يمكننا الحصول على ملخص وقت البناء لـ Clean build باستخدام xcodebuild مع الخيار - buildWithTimingSummary : الآن دعنا نحصل على مقاييس مماثلة للبناء المتزايد. وتجدر الإشارة إلى أن وقت البناء المتزايد يعتمد بشكل كامل على الملفات التي يتم تعديلها في المشروع. للحصول على نتائج متناسقة ، يمكنك تعديل ملف واحد وتجميع المشروع. على عكس أنظمة Buck أو Bazel ، يستخدم Xcode الطوابع الزمنية لتحديد ما الذي تغير وما الذي يجب إعادة بنائه. يمكننا تحديث الطابع الزمني باستخدام اللمس:

xcodebuild -project 'Kickstarter.xcodeproj' \
-scheme 'Kickstarter-iOS' \
-configuration 'Debug' \
-sdk 'iphonesimulator' \
-showBuildTimingSummary \
clean build | sed -n -e '/Build Timing Summary/,$p'

Build Timing Summary
CompileStoryboard (29 tasks) | 87.128 seconds
CompileSwiftSources (4 tasks) | 54.144 seconds
PhaseScriptExecution (14 tasks) | 18.167 seconds
CompileAssetCatalog (2 tasks) | 6.532 seconds
CompileXIB (21 tasks) | 6.293 seconds
CodeSign (7 tasks) | 3.069 seconds
Ld (4 tasks) | 2.342 seconds
LinkStoryboards (2 tasks) | 0.172 seconds
CompileC (3 tasks) | 0.122 seconds
Ditto (20 tasks) | 0.076 seconds
Touch (4 tasks) | 0.007 seconds
** BUILD SUCCEEDED ** [92.620 sec]



touch KsApi/mutations/CancelBackingMutation.swift && \
xcodebuild -project 'Kickstarter.xcodeproj' \
-scheme 'Kickstarter-iOS' \
-configuration 'Debug' \
-sdk 'iphonesimulator' \
-showBuildTimingSummary \
build | sed -n -e '/Build Timing Summary/,$p'

Build Timing Summary
PhaseScriptExecution (14 tasks) | 18.089 seconds
CodeSign (7 tasks) | 2.990 seconds
CompileSwiftSources (1 task) | 1.245 seconds
Ld (1 task) | 0.361 seconds
** BUILD SUCCEEDED ** [23.927 sec]

اكتب تحذيرات التحقق


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

  • -Xfrontend -warn-long-function-body = 100
  • -Xfrontend -تحذير-تعبير طويل-نوع تدقيق = 100

صورة

الآن أنت تعرف الرمز الذي يواجه فيه مترجم Swift مشاكل والآن يمكنك محاولة تحسينه.

خيارات تشخيص المترجم


يحتوي برنامج التحويل البرمجي Swift على العديد من خيارات التشخيص المضمنة التي يمكنك استخدامها لوضع ملف تعريف التجميع.

  • - تجميع وقت القيادة - مستوى عالٍ من مزامنة المهام التي يقوم بها السائق.
  • -Xfrontend -debug-time-compilation — .
  • -Xfrontend -debug-time-function-bodies – .
  • -Xfrontend -debug-time-expression-type-checking – .

دعنا نستخدم علامة - debug-time-compilation للحصول على معلومات حول أبطأ الملفات عند الترجمة : كما ترى ، استغرق الأمر 25 ثانية لتجميع SettingsNewslettersCellViewModel.swift . من سجل التجمع، يمكنك الحصول على معلومات إضافية حول وقت تجميع ملف: الآن فمن الواضح أن نوع التدقيق و التحليل الدلالي هي معظم العمل تستغرق وقتا طويلا. دعنا نمضي قدمًا وسرد أبطأ الوظائف والتعبيرات في خطوة التحقق من النوع :

xcodebuild -project 'Kickstarter.xcodeproj' \
-scheme 'Kickstarter-iOS' \
-configuration 'Debug' \
-sdk 'iphonesimulator' \
clean build \
OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-compilation" |
awk '/CompileSwift normal/,/Swift compilation/{print; getline; print; getline; print}' |
grep -Eo "^CompileSwift.+\.swift|\d+\.\d+ seconds" |
sed -e 'N;s/\(.*\)\n\(.*\)/\2 \1/' |
sed -e "s|CompileSwift normal x86_64 $(pwd)/||" |
sort -rn |
head -3

25.6026 seconds Library/ViewModels/SettingsNewslettersCellViewModel.swift
24.4429 seconds Library/ViewModels/PledgeSummaryViewModel.swift
24.4312 seconds Library/ViewModels/PaymentMethodsViewModel.swift



===-------------------------------------------------------------------------===
Swift compilation
===-------------------------------------------------------------------------===
Total Execution Time: 25.6026 seconds (26.6593 wall clock)

---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
24.4632 ( 98.3%) 0.5406 ( 76.5%) 25.0037 ( 97.7%) 26.0001 ( 97.5%) Type checking and Semantic analysis
0.0981 ( 0.4%) 0.1383 ( 19.6%) 0.2364 ( 0.9%) 0.2872 ( 1.1%) Name binding
0.1788 ( 0.7%) 0.0043 ( 0.6%) 0.1831 ( 0.7%) 0.1839 ( 0.7%) IRGen
0.0508 ( 0.2%) 0.0049 ( 0.7%) 0.0557 ( 0.2%) 0.0641 ( 0.2%) Parsing
0.0599 ( 0.2%) 0.0020 ( 0.3%) 0.0619 ( 0.2%) 0.0620 ( 0.2%) SILGen
0.0285 ( 0.1%) 0.0148 ( 2.1%) 0.0433 ( 0.2%) 0.0435 ( 0.2%) SIL optimization
0.0146 ( 0.1%) 0.0015 ( 0.2%) 0.0161 ( 0.1%) 0.0162 ( 0.1%) Serialization, swiftmodule
0.0016 ( 0.0%) 0.0006 ( 0.1%) 0.0022 ( 0.0%) 0.0022 ( 0.0%) Serialization, swiftdoc
0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0001 ( 0.0%) SIL verification, pre-optimization
0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) AST verification
0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) 0.0000 ( 0.0%) SIL verification, post-optimization
24.8956 (100.0%) 0.7069 (100.0%) 25.6026 (100.0%) 26.6593 (100.0%) Total



xcodebuild -project 'Kickstarter.xcodeproj' \
-scheme 'Kickstarter-iOS' \
-configuration 'Debug' \
-sdk 'iphonesimulator' \
clean build \
OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-expression-type-checking \
-Xfrontend -debug-time-function-bodies" |
grep -o "^\d*.\d*ms\t[^$]*$" |
awk '!visited[$0]++' |
sed -e "s|$(pwd)/||" |
sort -rn |
head -5

16226.04ms Library/Styles/UpdateDraftStyles.swift:31:3
10551.24ms Kickstarter-iOS/Views/RewardCardContainerView.swift:171:16 instance method configureBaseGradientView()
10547.41ms Kickstarter-iOS/Views/RewardCardContainerView.swift:172:7
8639.30ms Kickstarter-iOS/Views/Controllers/AddNewCardViewController.swift:396:67
8233.27ms KsApi/models/templates/ProjectTemplates.swift:94:5

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

وقت البناء المستهدف


من المستحسن قياس وقت تجميع الهدف بشكل منفصل وعرضه على الرسم البياني. يمكنك المساعدة في فهم الأهداف التي يتم جمعها أو يمكن جمعها بالتوازي. للقيام بذلك ، يمكنك استخدام أداة التقديم xcode-build-time-renderering. دعنا نعيّنها على أنها RubyGem: بعد اكتمال التثبيت ، قم بتشغيل الأمر التالي لإدخال سجل الطابع الزمني في مرحلة إنشاء البرنامج النصي لأهدافك: ثم قم بتجميع المشروع والتقرير باستخدام: نتيجة لذلك ، يجب أن تحصل على مخطط جانت لطيف من خلال وقت البناء الذي يعرض الوقت تجميعات جميع أهدافك:

gem install xcode-build-times



xcode-build-times install



xcode-build-times generate



صورة

المقاييس المجمعة


سيكون من الرائع تجميع مختلف المؤشرات المذكورة أعلاه. XCLogParser هي أداة رائعة يمكن أن تساعدك في ذلك. وهو محلل سجل لـ xcactivitylog الذي تم إنشاؤه بواسطة Xcode ، ويعطي الكثير من المعلومات حول وقت البناء لكل وحدة وملف في المشروع ، والتحذيرات ، والأخطاء ونتائج اختبار الوحدة. يمكنك تثبيته عن طريق استنساخ المستودع والبدء من خلال سطر الأوامر: هذا تقرير تم إنشاؤه لمشروع Kickstarter iOS:

git clone https://github.com/spotify/XCLogParser
rake build
xclogparser parse --project Kickstarter --reporter html



صورة

التشغيل الآلي


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

استنتاج


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

في المنشور التالي ، سننظر في الطرق التي يمكن استخدامها لتقليل وقت البناء.

شكرا للقراءة!

All Articles