کاهش زمان بیلد در گردل

چگونه زمان بیلد در Gradle را تا 65 درصد کاهش دهیم؟


Gradle یک بیلد سیستم بسیار قدرتمند است که فرآیند پیچیده ساخت فایل های dx. از سورس کدهای جاوا، ادغام تمامی منابع و ابزارها در یک پکیج اپلیکیشن apk. و امضای اپلیکیشن را مدیریت می کند. اما گردل در مقایسه با سایر سیستم های بیلد موجود، عملکرد چندان خوبی را به نمایش نمی گذارد و کندتر است، از این رو به راهکاری برای بهینه سازی آن نیاز داریم.

اما چرا زمان بیلد پروژه اهمیت دارد؟

از آنجایی که بیلد شدن پروژه زمان زیادی طول می کشد، در طول این مدت زمان می توانید به کارهای دیگری مشغول شوید. اما شرایطی را در نظر بگیرید که روزانه 6 ساعت در حال کار بر روی پروژه ای هستید و گردل بیلد را برای نصب فایل apk دیباگ برای روی گوشی حدود 15 بار اجرا می کنید، بدین ترتیب 35 دقیقه از روز و 3 ساعت از هفته را بیکار نشسته و در حال تماشای اجرای فرآیند بیلد گردل می باشید و هرچه زمان کمتری صرف تماشای عملیات بیلد گردل کنید به نفع شما خواهد بود، چرا که زمان بسیار باارزش است.

در این مقاله روشی برای اعمال تغییرات در فرآیند بیلد شرح داده شده تا از طریق آن زمان بیلد کاهش پیدا کند.

اپلیکیشن Google I/O application به عنوان مثالی برای پیاده سازی این تغییرات مورد استفاده قرار خواهد گرفت. این پروژه شامل بیش از 28 وابستگی و 41538 متد رفرنس می باشد و سورس کد پروژه نیز از طریق GitHub در دسترس می باشد.

کاهش زمان بیلد در گردل

بیلد پروژه بدون اعمال تغییرات

در مرحله اول بدون اعمال هیچ گونه تغییری زمان بیلد و دیباگ اپلیکیشن از پروژه با پیکربندی کنونی را با کمک دستور زیر محاسبه می کنیم.

./gradlew android:assembleDebug --profile

Profile به گردل می گوید تا زمان موردنیاز برای اجرای هر تسک را اندازه گیری کرده و داده ها را در یک فایل اچ تی ام ال به نمایش گذارد. پروژه در projectDir/build/reports/profile directory/ قرار دارد.

کاهش زمان بیلد در گردل

- همانطور که مشاهده می کیند، فرآیند بیلد و دیباگ apk از سورس 2 دقیقه و 43 ثانیه طول کشید.

ممکن است این مدت زمان در سایر سیستم ها کمی فرق داشته باشد، این موضوع به پیکربندی و سخت افزار سیستم شما بستگی دارد. در این مثال از مک بوک پرو 2016 با تاچ بار برای اجرای این تسک ها استفاده شده است.

حال با اعمال تغییراتی قصد داریم این زمان را کاهش دهیم.

چرخه بیلد گردل:

گردل دارای سه فاز مجزا در چرخه حیات بیلد خود می باشد:

1. اینیشیالیزیشن: در این مرحله از چرخه حیات بیلد، گردل با گرفتن پروژه، تصمیم می گیرد که چه چیزهایی را بیلد کند.

2. پیکربندی: در این گام، گردل اسکریپت build.gradle را ارزیابی کرده و تمامی پلاگین ها را پیکربندی و گراف تسک ها را ارزیابی می نماید.

3. اجرا: در این فاز، گردل تمامی تسک ها را که در فاز قبلی ارزیابی شده بوند به اجرا در می آورد تا عملیات را انجام داده و اپلیکیشن را بیلد کند.

همانطور که دیدید تمامی عملیات تنها در فاز اجرا انجام می شوند، به این معنا که دو فاز اول پیش از فرآیند بیلد گردل صورت می پذیرند و برای ما اهمیتی ندارند. اما متاسفانه هر وقت هرگونه عملیاتی با گردل انجام دهید، این دو فاز نیز به اجرا در خواهند آمد.

بنابراین چطور می توان متد زمانی که برای اجرای دو فاز اول صرف است را محاسبه کرد؟ خوشبختانه گردل یک کامند dry-run دارد که به گردل می گوید پروژه را بدون اجرای هیچ تسکی ارزیابی کند و در این روش فاز اجرای تسک انجام نمی شود. این کامند را در ترمینال خود به اجرا درآورید:

./gradlew android:assembleDebug --dry-run --profile

در زیر مدت زمانی که توسط این فاز در پروژه Google I/O طول کشیده را مشاهده می کنید.

کاهش زمان بیلد در گردل

در نمودار بالا می بیندید اینیشیالایز و پیکربندی پروژه حدود 7.8 ثانیه زمان برده که نوعی اتلاف وقت تلقی می شود، حال ببینیم چطور می توان این زمان را کاهش داد.

Configure on demand

اپلیکیشن Google I/O دارای دو کاپوننت/ماژول می باشد:

Android: دربرگیرنده سورس کد مرتبط به اپلیکیشن اندروید.

Server: کدهای مرتبط به سرور بک اند.

اگر در حال بیلد یک اپلیکیشن اندروید هستید، احتمالا نمی خواهید کامپوننت سرور را هم پیکربندی کنید، اما گردل یک ثانیه راهم  برای کامپوننت سرور صرف می کند.

به همین منظور نیز گردل فلگی به نام configure-on-demand را در اختیار قرار ادده که با استفاده از آن، گردل تنها پروژه های موردنیاز را بیلد می کند.

./gradlew android:assembleDebug --dry-run --profile --configure-on-demand

کاهش زمان بیلد در گردل

در صورت استفاده از configure-on-demand، گردل پیکردبندی ماژول سرور را رد می کند و زمان بیلد حدود یک ثانیه کاهش پیدا می کند.

زمان کم شده : 1 ثانیه (6 درصد بهینه سازی)

آیا امکان فعال سازی configure-on-demand در اندروید استودیو وجود دارد؟

شما قادر به فعال سازی configure-on-demand برای هر بیلدی هستید و برای این کار باید org.gradle.configurationdeamnd=true را در فایل gradle.properties اندروید استودیو اضافه کرده و به بخش Preferences>Build,Execution,Deployment>Compiler مراجعه کرده و گزینه configure on demand را انتخاب کنید.

کاهش زمان بیلد در گردل

فعال سازی daemon:

گردل دارای قابلیت بسیار خوبی به نام Gradle Deamon می باشد. Daemon نمونه اولیه گردل را نگه داشته و آن را حتی زمانی که بیلد تمام شد، در پس زمینه به اجرا در می آورد. با این کار زمان لازم برای اینیشیالایز کردن گردل کاهش پیدا می کند و در نهایت موجب کاهش چشمگیری در زمان بیلد می شود.

شما قادر به مشاهده تفاوت زمانی در بیلد اولیه خود نیستند، زیرا گردل باید daemon را اینیشیالایز و استارت کند، اما زمان بیلد در بیلدهای بعدی کاهش پیدا خواهد کرد، زیرا daemon دیگر یک بار اینیشیالایز شده است.

./gradlew android:assembleDebug --dry-run --profile --configure-on-demand --daemon

کاهش زمان بیلد در گردل

در این حالت زمان بیلد گردل حدود 4.5 ثانیه کاهش پیدا می کند.

زمان کم شده: 4.5 ثانیه (71 درصد بهینه سازی)

آیا امکان فعال سازی dameon در اندروید استویدو وجود دارد؟

در نسخه 3.0 یا بالاتر daemon گردل به طور پیش فرض فعال می باشد، اما در نسخه های قبلی گردل، باید در هر بیلد این گزینه را با اضافه کردن org.gradle.daemon=true در فایل gradle.properties فعال کنید.

همشیه گردل خود را آپدیت نگه دارید:

سرعت گردل در هر نسخه بهبود می یابد و تغییرات و بهبودهای عملکردی در نسخه های اخیر گردل اعمال می شود و چنانچه از نسخه 2.4 یا بالاتر گردل استفاده می کنید، کاهش چشمگیری در زمان بیلد مشاهده خواهید کرد.

از این رو لازم است همیشه از این بابت که آخرین نسخه گردل را مورد استفاده قرار می دهید، اطمینان حاصل کنید. می توانید با مراجعه به /gradle/wrapper/gradle-wrapper.properties نسخه گردل را با تغییر distributionUrl ارتقا دهید.

فایل gradle-wrapper.properties برای اپلیکیشن Google I/O را مشاهده می کنید.

کاهش زمان بیلد در گردل

./gradlew android:assembleDebug --dry-run --profile --configure-on-demand --daemon

کاهش زمان بیلد در گردل

زمان کم شده: 0.7 ثانیه (82 درصد بهینه سازی)

تا این مرحله موفق شدیم 82 درصد از زمان اینیشیالایز و پیکربندی را کم کنیم، در این مرحله می خواهیم زمان لازم برای فاز اجرای تسک ها را هم کاهش دهیم.

افزایش اندازه پشته:

از اندروید 2.2 به بعد گردل از dex جهت کاهش زمان بیلد برای پروژه استفاده می کند.

Dex in process فرآیندی است که امکان اجرای فرآیندهای dex متعدد در یک VM که با گردل اشتراک گذاشته شده است را میسر می گرداند.

به طور کلی در زمان بیلد اپلیکیشن، فرآیندهای dx متعددی در VMهای متفاوت به اجرا در می آیند.

کاهش زمان بیلد در گردل

اما از اندروید استودیو 2.0 به بعد تمامی فرآیندهای dx در یک VM واحد به اجرا درمی آیند و این VM با استفاده از گردل به اشتراک گذاشته می شود.

کاهش زمان بیلد در گردل

این اقدام موجب کاهش چشمگیری در زمان بیلد می شود، اما برای این کار به حافظه بیشتری نیاز است. این بدین معناست که باید اندازه پشته موردنیاز برای daemon گردل را افزایش دهید. به طور پیش فرض اندازه پشته برای daemon حدود 1 گیگابایت می باشد و با اضافه کردن خط زیر به gradle.properties می توانید این مقدار را افزایش دهید.

org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

اندازه پشته موردنیاز در هر سیستمی متفاوت خواهد بود و در این مثال 3 گیگابایت کفایت می کند. افزایش بیشتر اندازه پشته تاثیری بر روی زمان بیلد نخواهد گذاشت.

حال می خوایم بلید را با استفاده از دستور زیر به اجرا در آوریم:

./gradlew android:assembleDebug --profile --configure-on-demand --daemon

کاهش زمان بیلد در گردل

زمان کم شده: 1 دقیقه و 43 ثانیه (63 درصد بهینه سازی)

ماژول بندی و موازی کردن فرآیند بیلد:

لازم است امکان بیلد موازی پروژه را در اختیار گردل قرار دهید، چنانچه ماژول های متعددی در پروژه خود دارید، این گزینه را فعال کنید، گردل می توانید عملیات بیلد را برای ماژول های مستقل به طور موازی به اجرا درآورد و این کار موجب کاهش چشمگیری در زمان بیلد برای پروژه های پیچیده و چند ماژوله می شود.

با افزودن org.gradle.parallel=true در فایل gradle.properties می توانید اجرای موازی را فعال کنید.

از آنجایی که در این پروژه ماژول های متعددی نداریم، بیلد موازی تفاوت چندانی را موجب نمی شود.

زمان کم شده: 1 دقیقه و 45 ثانیه (64.5 درصد بهینه سازی)

کاهش زمان بیلد در گردل

موارد جزئی دیگری که باید به خاطر سپارید:

- از محاسبات سنگین جلوگیری کنید: برای نمونه می توان به افزایش کد نسخه از شمارشگر کامیت های گیت یا دانلود برخی فایل ها از url در زمان بیلد کردن پروژه اشاره کرد. گردل برای انجام این محاسبات و عملیات نتورک زمانی را صرف می کند که در نهایت منجر به افزایش زمان بیلد خواهد شد.

از وابستگی های داینامیک مانند موارد زیر استفاده نکنید.

compile 'com.android.support:appcompat-v7:23.0.+'

چنانچه وابستگی های داینامیک استفاده کنید، گردل به صورت آنلاین به جستجوی نسخه های جدیدتر لایببری های استفاده شده می پردازد، از این رو بهتر است از وابستگی های ثابت استفاده کرده و آنها را هر از چندگاهی به طور دستی آپدیت کنید.

compile 'com.android.support:appcompat-v7:23.0.2'

با افزودن کدهای زیر به فایل gradle.properties می توانید شاهد کاهش 65 درصد در زمان بیلد پروژه خود شوید.

#Enable daemon

org.gradle.daemon=true

# Try and findout the best heap size for your project build.

org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

# Modularise your project and enable parallel build

org.gradle.parallel=true

# Enable configure on demand.

org.gradle.configureondemand=true

 

https://medium.com برگرفته از

اینها را هم بخوانید