बड़े प्रोजेक्ट या ऐसे प्रोजेक्ट जिनमें कस्टम बिल्ड लॉजिक का ज़्यादा इस्तेमाल किया जाता है उनके लिए, आपको बिल्ड प्रोसेस को ज़्यादा बारीकी से देखना पड़ सकता है, ताकि रुकावटों का पता लगाया जा सके.
इसके लिए, Gradle की प्रोफ़ाइलिंग करके यह पता लगाया जा सकता है कि बिल्ड लाइफ़साइकल के हर फ़ेज़ और हर बिल्ड टास्क को पूरा करने में Gradle को कितना समय लगता है. उदाहरण के लिए, अगर आपकी बिल्ड प्रोफ़ाइल से पता चलता है कि Gradle आपके प्रोजेक्ट को कॉन्फ़िगर करने में बहुत ज़्यादा समय ले रहा है, तो हो सकता है कि आपको कस्टम बिल्ड लॉजिक को कॉन्फ़िगरेशन फ़ेज़ से बाहर ले जाने का सुझाव मिले.
इसके अलावा, अगर mergeDevDebugResources टास्क को पूरा होने में ज़्यादा समय लगता है, तो इसका मतलब है कि आपको अपनी इमेज को WebP में बदलना होगा या पीएनजी क्रंचिंग को बंद करना होगा.
अगर Android Studio 4.0 या इसके बाद के वर्शन का इस्तेमाल किया जा रहा है, तो बिल्ड की परफ़ॉर्मेंस से जुड़ी समस्याओं का पता लगाने का सबसे अच्छा तरीका है, Build Analyzer का इस्तेमाल करना.
इसके अलावा, Android Studio के बाहर अपने बिल्ड की प्रोफ़ाइल बनाने के लिए दो विकल्प हैं:
अलग से मौजूद
gradle-profilerटूल, आपके बिल्ड का गहराई से विश्लेषण करने के लिए एक बेहतरीन टूल है.Gradle
--profileविकल्प, Gradle कमांड लाइन से उपलब्ध एक सुविधाजनक टूल है.
अलग से मौजूद gradle-profiler टूल का इस्तेमाल करना
सबसे तेज़ बिल्ड स्पीड देने वाले प्रोजेक्ट सेटअप का पता लगाने के लिए, Gradle प्रोफ़ाइलर का इस्तेमाल करें. यह Gradle बिल्ड के लिए, प्रोफ़ाइलिंग और मानदंड की जानकारी इकट्ठा करने वाला टूल है. Gradle प्रोफ़ाइलर की मदद से, बिल्ड के लिए अलग-अलग स्थितियां बनाई जा सकती हैं और उन्हें कई बार चलाया जा सकता है. इससे नतीजों में ज़्यादा अंतर नहीं आता और नतीजे फिर से जनरेट किए जा सकते हैं.
बेंचमार्किंग मोड का इस्तेमाल, क्लीन और बढ़ने वाले बिल्ड के बारे में जानकारी इकट्ठा करने के लिए किया जाना चाहिए. वहीं, प्रोफ़ाइलिंग मोड का इस्तेमाल, रन के बारे में ज़्यादा विस्तृत जानकारी इकट्ठा करने के लिए किया जा सकता है. इसमें सीपीयू स्नैपशॉट भी शामिल हैं.
बेंचमार्क के लिए, प्रोजेक्ट सेटअप के कुछ कॉन्फ़िगरेशन में ये शामिल हैं:
- प्लगिन के वर्शन
- Gradle के वर्शन
- जेवीएम सेटिंग (हीप साइज़, पर्मजेन साइज़, गार्बेज कलेक्शन वगैरह)
- Gradle वर्कर की संख्या (
org.gradle.workers.max) - परफ़ॉर्मेंस को और बेहतर बनाने के लिए, हर प्लग इन के लिए विकल्प
शुरू करना
- इन निर्देशों का पालन करके, gradle-profiler इंस्टॉल करें
- दौड़ना:
gradle-profiler --benchmark --project-dir <root-project> :app:assembleDebug
इससे पूरी तरह से अप-टू-डेट बिल्ड को बेंचमार्क किया जाएगा, क्योंकि --benchmark प्रोजेक्ट में बदलाव किए बिना, टास्क को कई बार चलाता है. इसके बाद, यह profile-out/ डायरेक्ट्री में एक एचटीएमएल रिपोर्ट जनरेट करेगा. इसमें आपको बिल्ड में लगने वाला समय दिखेगा.
कुछ अन्य स्थितियां भी हैं जो मानदंड तय करने के लिए ज़्यादा काम की हो सकती हैं:
- किसी क्लास के मेथड बॉडी में कोड में बदलाव करना, जहां आपका ज़्यादातर काम होता है.
- आपके पूरे प्रोजेक्ट में इस्तेमाल किए जाने वाले मॉड्यूल में एपीआई में बदलाव. हालांकि, आपके कोड में होने वाले बदलावों की तुलना में, यह बदलाव कम होता है. इसके बावजूद, इसका असर ज़्यादा होता है और इसे मेज़र करना फ़ायदेमंद होता है.
- यूआई के काम को दोहराने के लिए, लेआउट में बदलाव करना.
- अनुवाद के काम को सिम्युलेट करने के लिए, स्ट्रिंग में बदलाव करना.
- बिल्ड को क्लीन करें, ताकि बिल्ड में हुए बदलावों को सिम्युलेट किया जा सके. उदाहरण के लिए, Android Gradle प्लगिन अपडेट, Gradle अपडेट या
buildSrcमें मौजूद आपके बिल्ड कोड में किए गए बदलाव.
इन इस्तेमाल के उदाहरणों को बेंचमार्क करने के लिए, एक ऐसी स्थिति बनाई जा सकती है जिसका इस्तेमाल gradle-profiler को लागू करने के लिए किया जाएगा. साथ ही, यह आपके सोर्स में सही बदलाव लागू करेगी. यहां दिए गए सेक्शन में, कुछ सामान्य स्थितियों के बारे में बताया गया है.
अलग-अलग मेमोरी/सीपीयू सेटिंग की प्रोफ़ाइलिंग
अलग-अलग मेमोरी और सीपीयू सेटिंग की परफ़ॉर्मेंस की तुलना करने के लिए, कई स्थितियां बनाई जा सकती हैं. इनमें org.gradle.jvmargs के लिए अलग-अलग वैल्यू का इस्तेमाल किया जाता है. उदाहरण के लिए, ऐसे परिदृश्य बनाए जा सकते हैं:
# <root-project>/scenarios.txt
clean_build_2gb_4workers {
tasks = [":app:assembleDebug"]
gradle-args = ["--max-workers=4"]
jvm-args = ["-Xmx2048m"]
cleanup-tasks = ["clean"]
}
clean_build_parallelGC {
tasks = [":app:assembleDebug"]
jvm-args = ["-XX:+UseParallelGC"]
cleanup-tasks = ["clean"]
}
clean_build_G1GC_4gb {
tasks = [":app:assembleDebug"]
jvm-args = ["-Xmx4096m", "-XX:+UseG1GC"]
cleanup-tasks = ["clean"]
}
gradle-profiler --benchmark --project-dir
<root-project> --scenario-file scenarios.txt को चलाने पर, तीन स्थितियां चलेंगी. साथ ही, आपके पास यह तुलना करने का विकल्प होगा कि इनमें से हर सेटअप के लिए, :app:assembleDebug को कितना समय लगता है.
Gradle प्लगिन के अलग-अलग वर्शन की प्रोफ़ाइल बनाना
Gradle प्लग इन के वर्शन को बदलने से, बिल्ड टाइम पर क्या असर पड़ता है, यह जानने के लिए मानदंड तय करने वाला एक सिनेरियो बनाएं. इसके लिए, कुछ तैयारी करनी होगी, ताकि प्लगिन वर्शन को सिनेरियो से इंजेक्ट किया जा सके. अपने रूट build.gradle में बदलाव करें:
# <root-project>/build.gradle
buildscript {
def agpVersion = providers.systemProperty("agpVersion").forUseAtConfigurationTime().orNull ?: '4.1.0'
ext.kotlin = providers.systemProperty('kotlinVersion').forUseAtConfigurationTime().orNull ?: '1.4.0'
dependencies {
classpath "com.android.tools.build:gradle:$agpVersion"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin"
}
}
अब सिनैरियो फ़ाइल से, Android Gradle प्लगिन और Kotlin Gradle प्लगिन के वर्शन तय किए जा सकते हैं. साथ ही, सिनैरियो में सोर्स फ़ाइलों में नया तरीका जोड़ा जा सकता है:
# <root-project>/scenarios.txt
non_abi_change_agp4.1.0_kotlin1.4.10 {
tasks = [":app:assembleDebug"]
apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
System-properties {
"agpVersion" = "4.1.0"
"kotlinVersion" = "1.4.10"
}
non_abi_change_agp4.2.0_kotlin1.4.20 {
tasks = [":app:assembleDebug"]
apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
System-properties {
"agpVersion" = "4.2.0-alpha16"
"kotlinVersion" = "1.4.20"
}
इंक्रीमेंटल बिल्ड की प्रोफ़ाइल बनाना
ज़्यादातर बिल्ड इंक्रीमेंटल होते हैं. इसलिए, यह प्रोफ़ाइल बनाने के लिए सबसे अहम स्थितियों में से एक है. Gradle प्रोफ़ाइलर में, इंक्रीमेंटल बिल्ड की प्रोफ़ाइलिंग के लिए बेहतर सहायता उपलब्ध है. यह किसी सोर्स फ़ाइल में अपने-आप बदलाव लागू कर सकता है. इसके लिए, यह मेथड बॉडी में बदलाव करता है, नई मेथड जोड़ता है या लेआउट या स्ट्रिंग रिसॉर्स में बदलाव करता है. उदाहरण के लिए, इस तरह की इंक्रीमेंटल स्थितियां बनाई जा सकती हैं:
# <root-project>/scenarios.txt
non_abi_change {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
}
abi_change {
tasks = [":app:assembleDebug"]
apply-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
}
layout_change {
tasks = [":app:assembleDebug"]
apply-android-layout-change-to = "app/src/main/res/your_layout_file.xml"
}
string_resource_change {
tasks = [":app:assembleDebug"]
apply-android-resource-value-change-to = "app/src/main/res/values/strings.xml"
}
gradle-profiler --benchmark --project-dir <root-project>
--scenario-file scenarios.txt को चलाने पर, मानदंड के डेटा के साथ एचटीएमएल रिपोर्ट जनरेट होगी.
इंक्रीमेंटल बिल्ड के अलग-अलग मामलों को अन्य सेटिंग के साथ जोड़ा जा सकता है. जैसे, हीप साइज़, वर्कर की संख्या या Gradle वर्शन:
# <root-project>/scenarios.txt
non_abi_change_4g {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
jvm-args = ["-Xmx4096m"]
}
non_abi_change_4g_8workers {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
jvm-args = ["-Xmx4096m"]
gradle-args = ["--max-workers=8"]
}
non_abi_change_3g_gradle67 {
tasks = [":app:assembleDebug"]
apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
"app/src/main/java/com/example/your_app/your_code_file.kt"]
jvm-args = ["-Xmx3072m"]
version = ["6.7"]
}
क्लीन बिल्ड की प्रोफ़ाइल बनाना
क्लीन बिल्ड को बेंचमार्क करने के लिए, एक ऐसी स्थिति बनाई जा सकती है जिसका इस्तेमाल, gradle-profiler को चलाने के लिए किया जाएगा:
# <root-project>/scenarios.txt
clean_build {
tasks = [":app:assembleDebug"]
cleanup-tasks = ["clean"]
}
इस स्थिति को चलाने के लिए, इस निर्देश का इस्तेमाल करें:
gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt
Gradle --profile विकल्प का इस्तेमाल करना
Gradle कमांड लाइन से बिल्ड प्रोफ़ाइल जनरेट करने और उसे देखने के लिए, यह तरीका अपनाएं:
अपने प्रोजेक्ट के रूट पर कमांड-लाइन टर्मिनल खोलें.
यह कमांड डालकर, क्लीन बिल्ड करें. अपने बिल्ड की प्रोफ़ाइल बनाते समय, आपको हर बिल्ड के बीच एक क्लीन बिल्ड बनाना चाहिए. ऐसा इसलिए, क्योंकि जब किसी टास्क के इनपुट (जैसे, सोर्स कोड) में बदलाव नहीं होता है, तो Gradle टास्क को स्किप कर देता है. इसलिए, इनपुट में बदलाव किए बिना दूसरा बिल्ड हमेशा तेज़ी से चलता है, क्योंकि टास्क फिर से नहीं चलाए जाते. इसलिए, अपने बिल्ड के बीच
cleanटास्क को चलाने से यह पक्का होता है कि आपने पूरी बिल्ड प्रोसेस को प्रोफ़ाइल किया है.// On Mac or Linux, run the Gradle wrapper using "./gradlew". gradlew cleanअपने किसी ऐप्लिकेशन टाइप के डीबग के लिए बिल्ड को एक्ज़ीक्यूट करें. जैसे, "dev" टाइप. इसके लिए, इन फ़्लैग का इस्तेमाल करें:
gradlew --profile --offline --rerun-tasks assemble<var>Flavor</var>Debug--profile: प्रोफ़ाइलिंग की सुविधा चालू करता है.--offline: यह Gradle को ऑनलाइन डिपेंडेंसी फ़ेच करने से रोकता है. इससे यह पक्का होता है कि Gradle की ओर से आपकी डिपेंडेंसी को अपडेट करने की कोशिश की वजह से होने वाली कोई भी देरी, आपके प्रोफ़ाइलिंग डेटा में रुकावट न डाले. आपको अपना प्रोजेक्ट पहले ही एक बार बना लेना चाहिए, ताकि यह पक्का किया जा सके कि Gradle ने आपकी डिपेंडेंसी पहले ही डाउनलोड और कैश मेमोरी में सेव कर ली हैं.--rerun-tasks: Gradle को सभी टास्क फिर से चलाने और टास्क ऑप्टिमाइज़ेशन को अनदेखा करने के लिए मजबूर करता है.
बिल्ड पूरा होने के बाद, प्रोजेक्ट विंडो का इस्तेमाल करके,
project-root/build/reports/profile/डायरेक्ट्री पर जाएं. इसे पहली इमेज में दिखाया गया है.
पहली इमेज. प्रोजेक्ट व्यू, जिसमें प्रोफ़ाइल रिपोर्ट की जगह की जानकारी दिख रही है.
profile-timestamp.htmlफ़ाइल पर राइट क्लिक करें और ब्राउज़र में खोलें > डिफ़ॉल्ट को चुनें. रिपोर्ट, दूसरी इमेज में दिखाई गई रिपोर्ट जैसी दिखनी चाहिए. रिपोर्ट में मौजूद हर टैब की जांच करके, अपने बिल्ड के बारे में जानकारी हासिल की जा सकती है. जैसे, टास्क एक्ज़ीक्यूशन टैब से पता चलता है कि Gradle को हर बिल्ड टास्क को पूरा करने में कितना समय लगा.
दूसरी इमेज. ब्राउज़र में रिपोर्ट देखना.
ज़रूरी नहीं: अपने प्रोजेक्ट या बिल्ड कॉन्फ़िगरेशन में कोई भी बदलाव करने से पहले, तीसरे चरण में दिए गए कमांड को दोहराएं. हालांकि,
--rerun-tasksफ़्लैग को छोड़ दें. Gradle, उन टास्क को फिर से लागू नहीं करता जिनके इनपुट में कोई बदलाव नहीं हुआ है. इससे समय की बचत होती है. इन टास्क को रिपोर्ट के टास्क एक्ज़ीक्यूशन टैब में,UP-TO-DATEके तौर पर दिखाया जाता है. जैसा कि इमेज 3 में दिखाया गया है, इससे यह पता लगाया जा सकता है कि कौनसे टास्क ऐसे हैं जो ज़रूरत न होने पर भी काम कर रहे हैं. उदाहरण के लिए, अगर:app:processDevUniversalDebugManifestकोUP-TO-DATEके तौर पर मार्क नहीं किया गया है, तो इससे यह पता चल सकता है कि आपका बिल्ड कॉन्फ़िगरेशन, हर बिल्ड के साथ मेनिफ़ेस्ट को डाइनैमिक तौर पर अपडेट कर रहा है. हालांकि, कुछ टास्क हर बिल्ड के दौरान चलाने ज़रूरी होते हैं. जैसे,:app:checkDevDebugManifest.
तीसरी इमेज. टास्क के नतीजों को देखना.
अब आपके पास बिल्ड प्रोफ़ाइल रिपोर्ट है. इसलिए, रिपोर्ट के हर टैब में मौजूद जानकारी की जांच करके, ऑप्टिमाइज़ेशन के अवसरों को ढूंढा जा सकता है. बिल्ड की कुछ सेटिंग के लिए, एक्सपेरिमेंट करना ज़रूरी होता है. इसकी वजह यह है कि प्रोजेक्ट और वर्कस्टेशन के हिसाब से, फ़ायदे अलग-अलग हो सकते हैं. उदाहरण के लिए, बड़े कोड बेस वाले प्रोजेक्ट में कोड छोटा करने की सुविधा का इस्तेमाल किया जा सकता है. इससे, इस्तेमाल न किए गए कोड को हटाया जा सकता है और ऐप्लिकेशन का साइज़ छोटा किया जा सकता है.
हालांकि, छोटे प्रोजेक्ट के लिए कोड छोटा करने की सुविधा को पूरी तरह से बंद करने से ज़्यादा फ़ायदा मिल सकता है. इसके अलावा, org.gradle.jvmargs का इस्तेमाल करके Gradle हीप का साइज़ बढ़ाने से, कम मेमोरी वाली मशीनों की परफ़ॉर्मेंस पर बुरा असर पड़ सकता है.
अपने बिल्ड कॉन्फ़िगरेशन में बदलाव करने के बाद, पिछले चरणों को दोहराकर और नई बिल्ड प्रोफ़ाइल जनरेट करके, अपने बदलावों के नतीजे देखें. उदाहरण के लिए, इमेज 4 में इस पेज पर बताए गए कुछ बुनियादी ऑप्टिमाइज़ेशन लागू करने के बाद, सैंपल के तौर पर मिले उसी ऐप्लिकेशन की रिपोर्ट दिखाई गई है.
चौथी इमेज. बिल्ड स्पीड को ऑप्टिमाइज़ करने के बाद, नई रिपोर्ट देखना.