1. शुरू करने से पहले
इस कोडलैब में, ऐप्लिकेशन की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, बेसलाइन प्रोफ़ाइल जनरेट करने का तरीका बताया गया है. साथ ही, यह भी बताया गया है कि बेसलाइन प्रोफ़ाइल इस्तेमाल करने से परफ़ॉर्मेंस में होने वाले फ़ायदों की पुष्टि कैसे की जाती है.
आपको इन चीज़ों की ज़रूरत होगी
- Android Studio Hedgehog (2023.1.1) या इसके बाद का वर्शन
- Android Gradle प्लगिन 8.0 या इसके बाद का वर्शन
- Jetpack Macrobenchmark के बारे में बुनियादी जानकारी
- Android 7 (एपीआई लेवल 24) या इसके बाद के वर्शन वाला Android डिवाइस
आपको क्या करना होगा
- बेसलाइन प्रोफ़ाइल जनरेटर का इस्तेमाल करने के लिए, प्रोजेक्ट सेट अप करें.
- ऐप्लिकेशन के शुरू होने और स्क्रोल करने की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, बेसलाइन प्रोफ़ाइल जनरेट करें.
- Jetpack Macrobenchmark लाइब्रेरी की मदद से, परफ़ॉर्मेंस में हुई बढ़ोतरी की पुष्टि करें.
आपको क्या सीखने को मिलेगा
- बेसलाइन प्रोफ़ाइलें और उनसे ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बनाने का तरीका.
- बेसलाइन प्रोफ़ाइल जनरेट करने का तरीका.
- बेसलाइन प्रोफ़ाइल की परफ़ॉर्मेंस में सुधार.
2. सेट अप करना
शुरू करने के लिए, कमांड लाइन से Github रिपॉज़िटरी को क्लोन करें. इसके लिए, यह कमांड इस्तेमाल करें:
$ git clone https://github.com/android/codelab-android-performance.git
इसके अलावा, दो ज़िप फ़ाइलें डाउनलोड की जा सकती हैं:
Android Studio में प्रोजेक्ट खोलना
- Android Studio में आपका स्वागत है विंडो में,
पहले से मौजूद कोई प्रोजेक्ट खोलें को चुनें. [Download Location]/codelab-android-performance/baseline-profilesफ़ोल्डर चुनें. पक्का करें कि आपनेbaseline-profilesडायरेक्ट्री चुनी हो.- Android Studio में प्रोजेक्ट इंपोर्ट करते समय, पक्का करें कि
appमॉड्यूल को चलाया जा सके. इससे आपको बाद में सैंपल ऐप्लिकेशन बनाने में मदद मिलेगी.
ऐप्लिकेशन का सैंपल
इस कोडलैब में, JetSnack के सैंपल ऐप्लिकेशन का इस्तेमाल किया जाता है. यह वर्चुअल स्नैक ऑर्डर करने वाला ऐप्लिकेशन है, जो Jetpack Compose का इस्तेमाल करता है.
ऐप्लिकेशन की परफ़ॉर्मेंस का आकलन करने के लिए, आपको यूआई के स्ट्रक्चर और ऐप्लिकेशन के व्यवहार को समझना होगा. इससे, आपको बेंचमार्क से यूआई एलिमेंट ऐक्सेस करने में मदद मिलेगी. ऐप्लिकेशन चलाएं और स्नैक्स ऑर्डर करके, बुनियादी स्क्रीन के बारे में जानें. आपको यह जानने की ज़रूरत नहीं है कि ऐप्लिकेशन को कैसे बनाया गया है.

3. बेसलाइन प्रोफ़ाइल क्या होती हैं
बेसलाइन प्रोफ़ाइल, कोड को चलाने की स्पीड को पहली बार लॉन्च करने के बाद करीब 30% तक बढ़ा देती है. ऐसा इसलिए होता है, क्योंकि इसमें शामिल कोड पाथ के लिए इंटरप्रेटेशन और जस्ट-इन-टाइम (JIT) कंपाइलेशन के चरणों को छोड़ दिया जाता है. किसी ऐप्लिकेशन या लाइब्रेरी में बेसलाइन प्रोफ़ाइल को शिप करके, Android रनटाइम (एआरटी), शामिल किए गए कोड पाथ को ऑप्टिमाइज़ कर सकता है. इसके लिए, वह ऐप्लिकेशन को पहले से कंपाइल करने की सुविधा (एओटी) का इस्तेमाल करता है. इससे हर नए उपयोगकर्ता के लिए और ऐप्लिकेशन के हर अपडेट पर, परफ़ॉर्मेंस बेहतर होती है. प्रोफ़ाइल-गाइडेड ऑप्टिमाइज़ेशन (पीजीओ) की मदद से, ऐप्लिकेशन को स्टार्टअप के लिए ऑप्टिमाइज़ किया जा सकता है. साथ ही, इंटरैक्शन जंक को कम किया जा सकता है. इसके अलावा, पहली बार लॉन्च करने पर, ऐप्लिकेशन की रनटाइम परफ़ॉर्मेंस को बेहतर बनाया जा सकता है.
बेसलिन प्रोफ़ाइल की मदद से, ऐप्लिकेशन को पहली बार चलाने पर उपयोगकर्ता को बेहतर अनुभव मिलता है. जैसे, ऐप्लिकेशन को तेज़ी से चालू करना, एक स्क्रीन से दूसरी स्क्रीन पर आसानी से जाना या कॉन्टेंट को आसानी से स्क्रोल करना. ऐप्लिकेशन की स्पीड और रिस्पॉन्स टाइम को बेहतर बनाने से, रोज़ के सक्रिय उपयोगकर्ताओं की संख्या बढ़ती है. साथ ही, ऐप्लिकेशन पर बार-बार आने वाले लोगों की औसत संख्या भी बढ़ती है.
बेसलाइन प्रोफ़ाइलें, ऐप्लिकेशन के स्टार्टअप के अलावा अन्य चीज़ों को ऑप्टिमाइज़ करने में मदद करती हैं. इसके लिए, वे सामान्य उपयोगकर्ता इंटरैक्शन उपलब्ध कराती हैं. इससे ऐप्लिकेशन के पहले लॉन्च से ही, ऐप्लिकेशन के रनटाइम को बेहतर बनाया जा सकता है. गाइडेड एओटी कंपाइलेशन, उपयोगकर्ता के डिवाइसों पर निर्भर नहीं करता. इसे मोबाइल डिवाइस के बजाय, डेवलपमेंट मशीन पर हर रिलीज़ के लिए एक बार किया जा सकता है. बेसलाइन प्रोफ़ाइल के साथ रिलीज़ शिप करने से, ऐप्लिकेशन ऑप्टिमाइज़ेशन की सुविधा, सिर्फ़ क्लाउड प्रोफ़ाइल पर भरोसा करने की तुलना में बहुत तेज़ी से उपलब्ध हो जाती है.
बेसलाइन प्रोफ़ाइल का इस्तेमाल न करने पर, ऐप्लिकेशन के सभी कोड को मेमोरी में JIT कंपाइल किया जाता है. ऐसा तब होता है, जब डिवाइस का इस्तेमाल न किया जा रहा हो और कोड को इंटरप्रेट किया जा रहा हो या बैकग्राउंड में odex फ़ाइल में कंपाइल किया जा रहा हो. ऐसा हो सकता है कि नए पाथ ऑप्टिमाइज़ होने से पहले, ऐप्लिकेशन को पहली बार इंस्टॉल या अपडेट करने के बाद चलाने पर, उपयोगकर्ताओं को खराब अनुभव मिले.
4. बेसलाइन प्रोफ़ाइल जनरेटर मॉड्यूल सेट अप करना
इंस्ट्रुमेंटेशन टेस्ट क्लास की मदद से बेसलाइन प्रोफ़ाइलें जनरेट की जा सकती हैं. इसके लिए, आपको अपने प्रोजेक्ट में एक नया Gradle मॉड्यूल जोड़ना होगा. इसे अपने प्रोजेक्ट में जोड़ने का सबसे आसान तरीका, Android Studio के साथ आने वाला Android Studio मॉड्यूल विज़र्ड है. यह Android Studio Hedgehog या इसके बाद के वर्शन के साथ आता है.
प्रोजेक्ट पैनल में अपने प्रोजेक्ट या मॉड्यूल पर राइट क्लिक करके, नया मॉड्यूल विज़र्ड विंडो खोलें. इसके बाद, नया > मॉड्यूल चुनें.

खुली हुई विंडो में, टेंप्लेट पैनल से बेसलाइन प्रोफ़ाइल जनरेटर चुनें.

मॉड्यूल का नाम, पैकेज का नाम, भाषा या बिल्ड कॉन्फ़िगरेशन की भाषा जैसे सामान्य पैरामीटर के अलावा, दो ऐसे इनपुट हैं जो नए मॉड्यूल के लिए सामान्य नहीं हैं: टारगेट ऐप्लिकेशन और Gradle मैनेज किए गए डिवाइस का इस्तेमाल करें.
टारगेट ऐप्लिकेशन, ऐप्लिकेशन का वह मॉड्यूल होता है जिसके लिए बेसलाइन प्रोफ़ाइलें जनरेट की जाती हैं. अगर आपके प्रोजेक्ट में एक से ज़्यादा ऐप्लिकेशन मॉड्यूल हैं, तो वह मॉड्यूल चुनें जिसके लिए आपको जनरेटर चलाने हैं.
Gradle मैनेज किए गए डिवाइस का इस्तेमाल करें चेकबॉक्स, मॉड्यूल को अपने-आप मैनेज होने वाले Android एम्युलेटर पर बेसलाइन प्रोफ़ाइल जनरेटर चलाने के लिए सेट करता है. Gradle मैनेज किए गए डिवाइसों की मदद से अपने टेस्ट को स्केल करें लेख में, Gradle मैनेज किए गए डिवाइसों के बारे में ज़्यादा पढ़ा जा सकता है. इस विकल्प से सही का निशान हटाने पर, जनरेटर किसी भी कनेक्ट किए गए डिवाइस का इस्तेमाल करते हैं.
नए मॉड्यूल के बारे में पूरी जानकारी देने के बाद, मॉड्यूल बनाने की प्रोसेस को आगे बढ़ाने के लिए खत्म करें पर क्लिक करें.
मॉड्यूल विज़र्ड की मदद से किए गए बदलाव
मॉड्यूल विज़र्ड, आपके प्रोजेक्ट में कई बदलाव करता है.
यह baselineprofile नाम का Gradle मॉड्यूल जोड़ता है. इसके अलावा, विज़र्ड में चुना गया नाम भी जोड़ा जा सकता है.
यह मॉड्यूल, com.android.test प्लगिन का इस्तेमाल करता है. यह Gradle को बताता है कि इसे आपके ऐप्लिकेशन में शामिल न करें. इसलिए, इसमें सिर्फ़ टेस्टिंग कोड या बेंचमार्क शामिल हो सकते हैं. यह androidx.baselineprofile प्लगिन भी लागू करता है. इससे बेसलाइन प्रोफ़ाइलें अपने-आप जनरेट होती हैं.
विज़र्ड, आपके चुने गए टारगेट ऐप्लिकेशन मॉड्यूल में भी बदलाव करता है. खास तौर पर, यह androidx.baselineprofile प्लगिन लागू करता है, androidx.profileinstaller डिपेंडेंसी जोड़ता है, और नए बनाए गए मॉड्यूल build.gradle(.kts) में baselineProfile डिपेंडेंसी जोड़ता है:
plugins {
id("androidx.baselineprofile")
}
dependencies {
// ...
implementation("androidx.profileinstaller:profileinstaller:1.3.0")
"baselineProfile"(project(mapOf("path" to ":baselineprofile")))
}
androidx.profileinstaller डिपेंडेंसी जोड़ने पर, ये काम किए जा सकते हैं:
- जनरेट की गई बेसलाइन प्रोफ़ाइल की परफ़ॉर्मेंस में हुए फ़ायदों की पुष्टि स्थानीय तौर पर करें.
- Android 7 (एपीआई लेवल 24) और Android 8 (एपीआई लेवल 26) पर बेसलाइन प्रोफ़ाइलों का इस्तेमाल करें. ये क्लाउड प्रोफ़ाइलों के साथ काम नहीं करते.
- उन डिवाइसों पर बेसलाइन प्रोफ़ाइलों का इस्तेमाल करें जिन पर Google Play services उपलब्ध नहीं है.
baselineProfile(project(":baselineprofile")) डिपेंडेंसी से Gradle को पता चलता है कि उसे जनरेट की गई बेसलाइन प्रोफ़ाइलें किस मॉड्यूल से लेनी हैं.
अब जब आपने प्रोजेक्ट सेट कर लिया है, तो बेसलाइन प्रोफ़ाइल जनरेटर क्लास लिखें.
5. बेसलाइन प्रोफ़ाइल जनरेटर लिखना
आम तौर पर, आपके ऐप्लिकेशन के सामान्य उपयोगकर्ता के लिए बेसलाइन प्रोफ़ाइलें जनरेट की जाती हैं.
मॉड्यूल विज़र्ड, एक बेसिक BaselineProfileGenerator टेस्ट क्लास बनाता है. यह आपके ऐप्लिकेशन के स्टार्टअप के लिए बेसलाइन प्रोफ़ाइल जनरेट कर सकती है. यह इस तरह दिखती है:
@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {
@get:Rule
val rule = BaselineProfileRule()
@Test
fun generate() {
rule.collect("com.example.baselineprofiles_codelab") {
// This block defines the app's critical user journey. This is where you
// optimize for app startup. You can also navigate and scroll
// through your most important UI.
// Start default activity for your app.
pressHome()
startActivityAndWait()
// TODO Write more interactions to optimize advanced journeys of your app.
// For example:
// 1. Wait until the content is asynchronously loaded.
// 2. Scroll the feed content.
// 3. Navigate to detail screen.
// Check UiAutomator documentation for more information about how to interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
}
}
यह क्लास, BaselineProfileRule टेस्ट रूल का इस्तेमाल करती है. इसमें प्रोफ़ाइल जनरेट करने के लिए एक टेस्ट मेथड होता है. प्रोफ़ाइल जनरेट करने के लिए, collect() फ़ंक्शन का इस्तेमाल किया जाता है. इसके लिए सिर्फ़ दो पैरामीटर की ज़रूरत होती है:
packageName: आपके ऐप्लिकेशन का पैकेज.profileBlock: आखिरी लैम्डा पैरामीटर.
profileBlock लैंबडा में, उन इंटरैक्शन के बारे में बताया जाता है जो आपके ऐप्लिकेशन में उपयोगकर्ता की सामान्य गतिविधियों को कवर करते हैं. लाइब्रेरी, profileBlock को कई बार चलाती है. साथ ही, कॉल किए गए क्लास और फ़ंक्शन इकट्ठा करती है. इसके बाद, डिवाइस पर बेसलाइन प्रोफ़ाइल जनरेट करती है. इसमें ऑप्टिमाइज़ किए जाने वाले कोड शामिल होते हैं.
डिफ़ॉल्ट रूप से, बनाई गई जनरेटर क्लास में आपके डिफ़ॉल्ट Activity को शुरू करने के लिए इंटरैक्शन शामिल होते हैं. साथ ही, यह तब तक इंतज़ार करती है, जब तक कि आपके ऐप्लिकेशन का पहला फ़्रेम startActivityAndWait() तरीके का इस्तेमाल करके रेंडर नहीं हो जाता.
कस्टम जर्नी की मदद से जनरेटर को बेहतर बनाना
जनरेट की गई क्लास में कुछ TODO भी शामिल हैं. इनकी मदद से, अपने ऐप्लिकेशन की बेहतर जर्नी को ऑप्टिमाइज़ करने के लिए, ज़्यादा इंटरैक्शन लिखे जा सकते हैं. हमारा सुझाव है कि आप ऐसा करें, ताकि ऐप्लिकेशन के स्टार्टअप के अलावा, परफ़ॉर्मेंस को ऑप्टिमाइज़ किया जा सके.
हमारे सैंपल ऐप्लिकेशन में, इन जर्नी की पहचान इस तरह की जा सकती है:
- ऐप्लिकेशन शुरू करें. यह जनरेट की गई क्लास में पहले से ही कुछ हद तक शामिल है.
- कॉन्टेंट के एसिंक्रोनस तरीके से लोड होने तक इंतज़ार करें.
- स्नैक की सूची को स्क्रोल करें.
- स्नैक की जानकारी वाले पेज पर जाएं.
जनरेटर को बदलकर, यहां दिए गए स्निपेट में बताए गए फ़ंक्शन शामिल करें. ये फ़ंक्शन, सामान्य यात्राओं को कवर करते हैं:
// ...
rule.collect("com.example.baselineprofiles_codelab") {
// This block defines the app's critical user journey. This is where you
// optimize for app startup. You can also navigate and scroll
// through your most important UI.
// Start default activity for your app.
pressHome()
startActivityAndWait()
// TODO Write more interactions to optimize advanced journeys of your app.
// For example:
// 1. Wait until the content is asynchronously loaded.
waitForAsyncContent()
// 2. Scroll the feed content.
scrollSnackListJourney()
// 3. Navigate to detail screen.
goToSnackDetailJourney()
// Check UiAutomator documentation for more information about how to interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
// ...
अब, बताई गई हर यात्रा के लिए इंटरैक्शन लिखें. इसे MacrobenchmarkScope के एक्सटेंशन फ़ंक्शन के तौर पर लिखा जा सकता है, ताकि आपके पास इसके पैरामीटर और फ़ंक्शन का ऐक्सेस हो. इस तरह से लिखने पर, परफ़ॉर्मेंस में हुए फ़ायदों की पुष्टि करने के लिए, मानदंड के साथ हुए इंटरैक्शन का फिर से इस्तेमाल किया जा सकता है.
एसिंक्रोनस कॉन्टेंट के लोड होने का इंतज़ार करना
कई ऐप्लिकेशन में, ऐप्लिकेशन के शुरू होने पर एसिंक्रोनस लोडिंग होती है. इसे पूरी तरह से दिखने की स्थिति भी कहा जाता है. इससे सिस्टम को पता चलता है कि कॉन्टेंट कब लोड और रेंडर हुआ है. साथ ही, उपयोगकर्ता उससे इंटरैक्ट कर सकता है. इन इंटरैक्शन के साथ, जनरेटर (waitForAsyncContent) में स्थिति का इंतज़ार करें:
- फ़ीड में दिखने वाले स्नैक की सूची ढूंढो.
- जब तक सूची में मौजूद कुछ आइटम स्क्रीन पर न दिखें, तब तक इंतज़ार करें.
fun MacrobenchmarkScope.waitForAsyncContent() {
device.wait(Until.hasObject(By.res("snack_list")), 5_000)
val contentList = device.findObject(By.res("snack_list"))
// Wait until a snack collection item within the list is rendered.
contentList.wait(Until.hasObject(By.res("snack_collection")), 5_000)
}
स्क्रोल की जा सकने वाली सूची के साथ यात्रा
स्क्रोल करने वाली स्नैक लिस्ट (scrollSnackListJourney) के लिए, इन इंटरैक्शन का इस्तेमाल किया जा सकता है:
- स्नैक लिस्ट वाला यूज़र इंटरफ़ेस (यूआई) एलिमेंट ढूंढें.
- सिस्टम नेविगेशन को ट्रिगर न करने के लिए, जेस्चर मार्जिन सेट करें.
- सूची को स्क्रोल करें और यूज़र इंटरफ़ेस (यूआई) के लोड होने तक इंतज़ार करें.
fun MacrobenchmarkScope.scrollSnackListJourney() {
val snackList = device.findObject(By.res("snack_list"))
// Set gesture margin to avoid triggering gesture navigation.
snackList.setGestureMargin(device.displayWidth / 5)
snackList.fling(Direction.DOWN)
device.waitForIdle()
}
यात्रा की पूरी जानकारी वाले पेज पर जाएं
लास्ट जर्नी (goToSnackDetailJourney) में इन इंटरैक्शन को लागू किया जाता है:
- स्नैक की सूची और वे सभी स्नैक आइटम ढूंढें जिन पर काम किया जा सकता है.
- सूची से कोई आइटम चुनें.
- आइटम पर क्लिक करें और जानकारी वाली स्क्रीन लोड होने तक इंतज़ार करें. इस बात का फ़ायदा उठाया जा सकता है कि स्नैक लिस्ट अब स्क्रीन पर नहीं दिखेगी.
fun MacrobenchmarkScope.goToSnackDetailJourney() {
val snackList = device.findObject(By.res("snack_list"))
val snacks = snackList.findObjects(By.res("snack_item"))
// Select snack from the list based on running iteration.
val index = (iteration ?: 0) % snacks.size
snacks[index].click()
// Wait until the screen is gone = the detail is shown.
device.wait(Until.gone(By.res("snack_list")), 5_000)
}
बेसलाइन प्रोफ़ाइल जनरेटर को चलाने के लिए ज़रूरी सभी इंटरैक्शन तय करने के बाद, आपको उस डिवाइस के बारे में बताना होगा जिस पर इसे चलाया जाएगा.
6. जनरेटर को चलाने के लिए एक डिवाइस तैयार करें
बेसलाइन प्रोफ़ाइलें जनरेट करने के लिए, हमारा सुझाव है कि आप Gradle मैनेज किए गए डिवाइस जैसे किसी एम्युलेटर का इस्तेमाल करें. इसके अलावा, Android 13 (एपीआई 33) या उसके बाद के वर्शन वाले डिवाइस का इस्तेमाल भी किया जा सकता है.
इस प्रोसेस को दोहराने और बेसलाइन प्रोफ़ाइलें अपने-आप जनरेट करने के लिए, Gradle मैनेज किए गए डिवाइसों का इस्तेमाल किया जा सकता है. Gradle Managed Devices की मदद से, Android एम्युलेटर पर टेस्ट चलाए जा सकते हैं. इसके लिए, आपको एम्युलेटर को मैन्युअल तरीके से लॉन्च और बंद करने की ज़रूरत नहीं होती. Gradle मैनेज किए गए डिवाइसों की मदद से, टेस्ट को स्केल करना लेख में, Gradle मैनेज किए गए डिवाइसों के बारे में ज़्यादा जानें.
Gradle Managed Device को तय करने के लिए, उसकी परिभाषा को :baselineprofile मॉड्यूल की build.gradle.kts फ़ाइल में जोड़ें. ऐसा इस स्निपेट में दिखाए गए तरीके से करें:
android {
// ...
testOptions.managedDevices.devices {
create<ManagedVirtualDevice>("pixel6Api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp"
}
}
}
इस मामले में, हम Android 11 (एपीआई लेवल 31) का इस्तेमाल करते हैं. साथ ही, aosp सिस्टम इमेज में रूट किए गए ऐक्सेस की सुविधा होती है.
इसके बाद, तय किए गए Gradle मैनेज किए गए डिवाइस का इस्तेमाल करने के लिए, बेसलाइन प्रोफ़ाइल Gradle प्लगिन को कॉन्फ़िगर करें. इसके लिए, डिवाइस का नाम managedDevices प्रॉपर्टी में जोड़ें और useConnectedDevices को बंद करें. ऐसा नीचे दिए गए स्निपेट में दिखाया गया है:
android {
// ...
}
baselineProfile {
managedDevices += "pixel6Api31"
useConnectedDevices = false
}
dependencies {
// ...
}
इसके बाद, बेसलाइन प्रोफ़ाइल जनरेट करें.
7. बेसलाइन प्रोफ़ाइल जनरेट करना
डिवाइस तैयार होने के बाद, बेसलाइन प्रोफ़ाइल बनाई जा सकती है. बेसलाइन प्रोफ़ाइल Gradle प्लगिन, Gradle टास्क बनाता है. इससे जनरेटर टेस्ट क्लास को चलाने और जनरेट की गई बेसलाइन प्रोफ़ाइलों को आपके ऐप्लिकेशन में लागू करने की पूरी प्रोसेस अपने-आप पूरी हो जाती है.
नए मॉड्यूल विज़र्ड ने रन कॉन्फ़िगरेशन बनाया है, ताकि Gradle टास्क को सभी ज़रूरी पैरामीटर के साथ तुरंत चलाया जा सके. इसके लिए, टर्मिनल और Android Studio के बीच स्विच करने की ज़रूरत नहीं होती
इसे चलाने के लिए, Generate Baseline Profile रन कॉन्फ़िगरेशन ढूंढें और 'चलाएं' बटन
पर क्लिक करें.

यह टास्क, पहले से तय की गई एम्युलेटर इमेज को शुरू करता है. BaselineProfileGenerator टेस्ट क्लास से इंटरैक्शन को कई बार चलाएं. इसके बाद, एम्युलेटर को बंद करें और Android Studio को आउटपुट दें.
जनरेटर के काम पूरा करने के बाद, Gradle प्लगिन जनरेट किए गए baseline-prof.txt को src/release/generated/baselineProfile/ फ़ोल्डर में मौजूद आपके टारगेट ऐप्लिकेशन (:app मॉड्यूल) में अपने-आप डाल देता है.

(ज़रूरी नहीं) कमांड लाइन से जनरेटर चलाना
इसके अलावा, जनरेटर को कमांड लाइन से भी चलाया जा सकता है. Gradle Managed Device की मदद से बनाए गए टास्क—:app:generateBaselineProfile का इस्तेमाल किया जा सकता है. यह कमांड, baselineProfile(project(:baselineProfile)) डिपेंडेंसी से तय किए गए प्रोजेक्ट में मौजूद सभी टेस्ट चलाती है. मॉड्यूल में परफ़ॉर्मेंस में हुए फ़ायदे की पुष्टि करने के लिए, बेंचमार्क भी शामिल होते हैं. इसलिए, ये टेस्ट फ़ेल हो जाते हैं. साथ ही, इम्यूलेटर पर बेंचमार्क चलाने के ख़िलाफ़ चेतावनी मिलती है.
android .testInstrumentationRunnerArguments .androidx.benchmark.enabledRules=BaselineProfile
इसके लिए, इस इंस्ट्रुमेंटेशन रनर आर्ग्युमेंट का इस्तेमाल करके, सभी बेसलाइन प्रोफ़ाइल जनरेटर को फ़िल्टर किया जा सकता है. साथ ही, सभी बेंचमार्क को स्किप किया जा सकता है:
पूरा निर्देश ऐसा दिखता है:
./gradlew :app:generateBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
बेसलाइन प्रोफ़ाइलों की मदद से अपना ऐप्लिकेशन उपलब्ध कराना
बेसलिन प्रोफ़ाइल जनरेट होने और आपके ऐप्लिकेशन के सोर्स कोड में कॉपी होने के बाद, अपने ऐप्लिकेशन का प्रोडक्शन वर्शन बनाएं. इसे बनाने का तरीका वही होगा जो आम तौर पर इस्तेमाल किया जाता है. बेसलिन प्रोफ़ाइल को अपने उपयोगकर्ताओं के साथ शेयर करने के लिए, आपको कुछ भी अतिरिक्त करने की ज़रूरत नहीं है. इन्हें Android Gradle प्लगिन, बिल्ड के दौरान चुनता है और आपके AAB या APK में शामिल करता है. इसके बाद, Google Play में बिल्ड अपलोड करें.
जब उपयोगकर्ता ऐप्लिकेशन इंस्टॉल करते हैं या पिछले वर्शन से ऐप्लिकेशन को अपडेट करते हैं, तो बेसलाइन प्रोफ़ाइल भी इंस्टॉल हो जाती है. इससे ऐप्लिकेशन के पहले रन से ही बेहतर परफ़ॉर्मेंस मिलती है.
अगले चरण में, यह पुष्टि करने का तरीका बताया गया है कि बेसलाइन प्रोफ़ाइल की मदद से, ऐप्लिकेशन की परफ़ॉर्मेंस कितनी बेहतर हुई है.
8. (ज़रूरी नहीं) बेसलाइन प्रोफ़ाइल जनरेट करने की प्रोसेस को अपनी पसंद के मुताबिक बनाएं
बेसलाइन प्रोफ़ाइल Gradle प्लगिन में, प्रोफ़ाइल जनरेट करने के तरीके को अपनी खास ज़रूरतों के हिसाब से बनाने के विकल्प शामिल होते हैं. बिल्ड स्क्रिप्ट में baselineProfile { } कॉन्फ़िगरेशन ब्लॉक का इस्तेमाल करके, इस व्यवहार को बदला जा सकता है.
:baselineprofile मॉड्यूल में मौजूद कॉन्फ़िगरेशन ब्लॉक से यह तय होता है कि जनरेटर को कैसे चलाया जाए. इसमें managedDevices जोड़ने और यह तय करने का विकल्प होता है कि useConnectedDevices या Gradle मैनेज किए गए डिवाइसों का इस्तेमाल किया जाए या नहीं.
:app टारगेट मॉड्यूल में मौजूद कॉन्फ़िगरेशन ब्लॉक से यह तय होता है कि प्रोफ़ाइलें कहां सेव की जाती हैं या उन्हें कैसे जनरेट किया जाता है. इन पैरामीटर में बदलाव किया जा सकता है:
automaticGenerationDuringBuild: अगर यह सुविधा चालू है, तो प्रोडक्शन रिलीज़ बिल्ड बनाते समय, बेसलाइन प्रोफ़ाइल जनरेट की जा सकती है. यह सुविधा, ऐप्लिकेशन को शिप करने से पहले सीआई पर बनाने के लिए काम की है.saveInSrc: इससे यह तय होता है कि जनरेट की गई बेसलाइन प्रोफ़ाइल,src/फ़ोल्डर में सेव की गई है या नहीं. इसके अलावा,:baselineprofileबिल्ड फ़ोल्डर से भी फ़ाइल को ऐक्सेस किया जा सकता है.baselineProfileOutputDir: इससे यह तय होता है कि जनरेट की गई बेसलाइन प्रोफ़ाइलें कहां सेव की जाएंगी.mergeIntoMain: डिफ़ॉल्ट रूप से, बेसलाइन प्रोफ़ाइलें हर बिल्ड वैरिएंट (प्रॉडक्ट फ़्लेवर और बिल्ड टाइप) के हिसाब से जनरेट की जाती हैं. अगर आपको सभी प्रोफ़ाइलों कोsrc/mainमें मर्ज करना है, तो इस फ़्लैग को चालू करके ऐसा किया जा सकता है.filter: जनरेट की गई बेसलाइन प्रोफ़ाइलों में, किन क्लास या मेथड को शामिल करना है या बाहर रखना है, यह फ़िल्टर किया जा सकता है. यह उन लाइब्रेरी डेवलपर के लिए मददगार हो सकता है जो सिर्फ़ लाइब्रेरी का कोड शामिल करना चाहते हैं.
9. स्टार्टअप की परफ़ॉर्मेंस में हुए सुधारों की पुष्टि करना
बेसलिन प्रोफ़ाइल जनरेट करने और उसे अपने ऐप्लिकेशन में जोड़ने के बाद, पुष्टि करें कि इससे आपके ऐप्लिकेशन की परफ़ॉर्मेंस पर वैसा ही असर पड़ा है जैसा आपको चाहिए.
नया मॉड्यूल विज़र्ड, StartupBenchmarks नाम की एक बेंचमार्क क्लास बनाता है. इसमें ऐप्लिकेशन के शुरू होने में लगने वाले समय को मेज़र करने के लिए एक बेंचमार्क शामिल होता है. साथ ही, इसकी तुलना तब की जाती है, जब ऐप्लिकेशन बेसलाइन प्रोफ़ाइल का इस्तेमाल करता है.
क्लास इस तरह दिखती है:
@RunWith(AndroidJUnit4::class)
@LargeTest
class StartupBenchmarks {
@get:Rule
val rule = MacrobenchmarkRule()
@Test
fun startupCompilationNone() =
benchmark(CompilationMode.None())
@Test
fun startupCompilationBaselineProfiles() =
benchmark(CompilationMode.Partial(BaselineProfileMode.Require))
private fun benchmark(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(StartupTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.COLD,
iterations = 10,
setupBlock = {
pressHome()
},
measureBlock = {
startActivityAndWait()
// TODO Add interactions to wait for when your app is fully drawn.
// The app is fully drawn when Activity.reportFullyDrawn is called.
// For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
// from the AndroidX Activity library.
// Check the UiAutomator documentation for more information on how to
// interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
)
}
}
यह MacrobenchmarkRule का इस्तेमाल करता है. यह आपके ऐप्लिकेशन के लिए बेंचमार्क चला सकता है और परफ़ॉर्मेंस मेट्रिक इकट्ठा कर सकता है. मानदंड लिखने का एंट्री पॉइंट, नियम का measureRepeated फ़ंक्शन है.
इसके लिए कई पैरामीटर ज़रूरी होते हैं:
packageName:कि किस ऐप्लिकेशन को मेज़र करना है.metrics: आपको बेंचमार्क के दौरान किस तरह की जानकारी मेज़र करनी है.iterations: बेंचमार्क कितनी बार दोहराया जाता है.startupMode: आपको अपना ऐप्लिकेशन, बेंचमार्क शुरू होने पर कैसे शुरू करना है.setupBlock: मेज़रमेंट से पहले, आपके ऐप्लिकेशन के साथ कौन-कौनसी कार्रवाइयां होनी चाहिए.measureBlock: आपके ऐप्लिकेशन के साथ होने वाले वे इंटरैक्शन जिन्हें आपको बेंचमार्क के दौरान मेज़र करना है.
टेस्ट क्लास में दो टेस्ट भी शामिल हैं: startupCompilationeNone() और startupCompilationBaselineProfiles(). ये दोनों, अलग-अलग compilationMode के साथ benchmark() फ़ंक्शन को कॉल करते हैं.
CompilationMode
CompilationMode पैरामीटर से पता चलता है कि ऐप्लिकेशन को मशीन कोड में पहले से कैसे कंपाइल किया जाता है. इसमें ये विकल्प होते हैं:
DEFAULT: अगर उपलब्ध हो, तो यह ऐप्लिकेशन को Baseline Profiles का इस्तेमाल करके आंशिक रूप से पहले से कंपाइल करता है. इसका इस्तेमाल तब किया जाता है, जब कोईcompilationModeपैरामीटर लागू न किया गया हो.None(): इससे ऐप्लिकेशन की कंपाइलेशन स्थिति रीसेट हो जाती है और ऐप्लिकेशन पहले से कंपाइल नहीं होता. ऐप्लिकेशन के चलने के दौरान, जस्ट-इन-टाइम कंपाइलेशन (JIT) की सुविधा अब भी चालू रहती है.Partial(): ऐप्लिकेशन को बेसलाइन प्रोफ़ाइल या वार्म अप रन या दोनों के साथ पहले से कंपाइल करता है.Full(): यह पूरे ऐप्लिकेशन कोड को पहले से कंपाइल करता है. Android 6 (एपीआई 23) और इससे पहले के वर्शन पर, सिर्फ़ यही विकल्प उपलब्ध है.
अगर आपको अपने ऐप्लिकेशन की परफ़ॉर्मेंस को ऑप्टिमाइज़ करना है, तो DEFAULT कंपाइलेशन मोड चुनें. ऐसा इसलिए, क्योंकि इस मोड में ऐप्लिकेशन की परफ़ॉर्मेंस, Google Play से इंस्टॉल किए गए ऐप्लिकेशन की परफ़ॉर्मेंस जैसी होती है. अगर आपको बेसलाइन प्रोफ़ाइलों से मिलने वाले परफ़ॉर्मेंस फ़ायदों की तुलना करनी है, तो कंपाइलेशन मोड None और Partial के नतीजों की तुलना करके ऐसा किया जा सकता है.
कॉन्टेंट के लोड होने का इंतज़ार करने के लिए, बेंचमार्क में बदलाव करना
बेंचमार्क, आपके ऐप्लिकेशन के साथ इंटरैक्शन लिखकर, बेसलाइन प्रोफ़ाइल जनरेटर की तरह ही लिखे जाते हैं. डिफ़ॉल्ट रूप से, बनाए गए बेंचमार्क सिर्फ़ पहले फ़्रेम के रेंडर होने का इंतज़ार करते हैं. यह BaselineProfileGenerator की तरह ही होता है. इसलिए, हमारा सुझाव है कि आप इसे बेहतर बनाएं, ताकि यह एसिंक्रोनस कॉन्टेंट के लिए इंतज़ार कर सके.
इसके लिए, जनरेटर के लिए लिखे गए एक्सटेंशन फ़ंक्शन का फिर से इस्तेमाल किया जा सकता है. इस बेंचमार्क में स्टार्टअप के समय को कैप्चर किया जाता है. इसके लिए, StartupTimingMetric() का इस्तेमाल किया जाता है. हमारा सुझाव है कि आप यहां सिर्फ़ एसिंक्रोनस कॉन्टेंट के लोड होने का समय शामिल करें. इसके बाद, जनरेटर में तय की गई अन्य उपयोगकर्ता गतिविधियों के लिए अलग बेंचमार्क लिखें.
// ...
measureBlock = {
startActivityAndWait()
// The app is fully drawn when Activity.reportFullyDrawn is called.
// For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter
// from the AndroidX Activity library.
waitForAsyncContent() // <------- Added to wait for async content.
// Check the UiAutomator documentation for more information on how to
// interact with the app.
// https://d.android.com/training/testing/other-components/ui-automator
}
मानदंडों को लागू करना
इंस्ट्रुमेंट किए गए टेस्ट की तरह ही, बेंचमार्क चलाए जा सकते हैं. आपके पास टेस्ट फ़ंक्शन या पूरी क्लास को चलाने का विकल्प होता है. इसके लिए, आपको उसके बगल में मौजूद गटर आइकॉन पर क्लिक करना होगा.

पक्का करें कि आपने कोई फ़िज़िकल डिवाइस चुना हो, क्योंकि Android एम्युलेटर पर बेंचमार्क चलाने पर, रनटाइम में यह गड़बड़ी होती है. साथ ही, यह चेतावनी मिलती है कि बेंचमार्क से गलत नतीजे मिल सकते हैं. तकनीकी तौर पर, इसे एम्युलेटर पर चलाया जा सकता है. हालांकि, इससे आपकी होस्ट मशीन की परफ़ॉर्मेंस का पता चलता है. अगर इस पर ज़्यादा लोड है, तो आपके बेंचमार्क की परफ़ॉर्मेंस धीमी हो जाती है और उल्टी दिशा में काम करती है.

मानदंड चलाने के बाद, आपके ऐप्लिकेशन को फिर से बनाया जाता है. इसके बाद, यह आपके मानदंड चलाता है. आपने जो iterations तय किया है उसके आधार पर, बेंचमार्क आपके ऐप्लिकेशन को कई बार शुरू, बंद, और फिर से इंस्टॉल करते हैं.
बेंचमार्क पूरे होने के बाद, आपको Android Studio के आउटपुट में समय दिखेगा. यह समय इस स्क्रीनशॉट में दिखाया गया है:

स्क्रीनशॉट में देखा जा सकता है कि हर CompilationMode के लिए, ऐप्लिकेशन के चालू होने का समय अलग-अलग है. मीडियन वैल्यू को यहां दी गई टेबल में दिखाया गया है:
timeToInitialDisplay [ms] | timeToFullDisplay [ms] | |
कोई नहीं | 202.2 | 818.8 |
BaselineProfiles | 193.7 | 637.9 |
सुधार | 4% | 28% |
timeToFullDisplay के लिए कंपाइलेशन मोड के बीच का अंतर 180 मि॰से॰ है. इसका मतलब है कि सिर्फ़ बेसलाइन प्रोफ़ाइल का इस्तेमाल करने से,परफ़ॉर्मेंस में ~28% का सुधार हुआ है. CompilationNone की परफ़ॉर्मेंस खराब है, क्योंकि ऐप्लिकेशन के स्टार्टअप के दौरान डिवाइस को सबसे ज़्यादा JIT कंपाइलिंग करनी पड़ती है. CompilationBaselineProfiles की परफ़ॉर्मेंस बेहतर है, क्योंकि बेसलाइन प्रोफ़ाइल के साथ पार्शियल कंपाइलेशन, उस कोड को AOT कंपाइल करता है जिसे उपयोगकर्ता सबसे ज़्यादा इस्तेमाल करता है. साथ ही, यह गैर-ज़रूरी कोड को पहले से कंपाइल नहीं करता, ताकि उसे तुरंत लोड न करना पड़े.
10. (ज़रूरी नहीं) स्क्रोलिंग की परफ़ॉर्मेंस में हुए सुधार की पुष्टि करना
पिछले चरण की तरह ही, स्क्रोलिंग की परफ़ॉर्मेंस का आकलन और पुष्टि की जा सकती है. सबसे पहले, बेंचमार्क नियम और दो टेस्ट मेथड वाली ScrollBenchmarks टेस्ट क्लास बनाएं. इन टेस्ट मेथड में, अलग-अलग कंपाइलेशन मोड का इस्तेमाल किया जाता है:
@LargeTest
@RunWith(AndroidJUnit4::class)
class ScrollBenchmarks {
@get:Rule
val rule = MacrobenchmarkRule()
@Test
fun scrollCompilationNone() = scroll(CompilationMode.None())
@Test
fun scrollCompilationBaselineProfiles() = scroll(CompilationMode.Partial())
private fun scroll(compilationMode: CompilationMode) {
// TODO implement
}
}
scroll तरीके में, ज़रूरी पैरामीटर के साथ measureRepeated फ़ंक्शन का इस्तेमाल करें. metrics पैरामीटर के लिए, FrameTimingMetric का इस्तेमाल करें. इससे यह मेज़र किया जाता है कि यूज़र इंटरफ़ेस (यूआई) फ़्रेम बनाने में कितना समय लगता है:
private fun scroll(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.WARM,
iterations = 10,
setupBlock = {
// TODO implement
},
measureBlock = {
// TODO implement
}
)
}
इस बार, आपको setupBlock और measureBlock के बीच इंटरैक्शन को ज़्यादा बांटना होगा, ताकि पहले लेआउट के दौरान फ़्रेम की अवधि और कॉन्टेंट को स्क्रोल करने की अवधि को ही मेज़र किया जा सके. इसलिए, डिफ़ॉल्ट स्क्रीन को शुरू करने वाले फ़ंक्शन को setupBlock में रखें. साथ ही, पहले से बनाए गए एक्सटेंशन फ़ंक्शन waitForAsyncContent() और scrollSnackListJourney() को measureBlock में रखें:
private fun scroll(compilationMode: CompilationMode) {
rule.measureRepeated(
packageName = "com.example.baselineprofiles_codelab",
metrics = listOf(FrameTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.WARM,
iterations = 10,
setupBlock = {
pressHome()
startActivityAndWait()
},
measureBlock = {
waitForAsyncContent()
scrollSnackListJourney()
}
)
}
बेंचमार्क तैयार होने के बाद, इसे पहले की तरह चलाया जा सकता है. इसके नतीजे, इस स्क्रीनशॉट में दिखाए गए हैं:

FrameTimingMetric, 50वें, 90वें, 95वें, और 99वें पर्सेंटाइल में फ़्रेम की अवधि को मिलीसेकंड (frameDurationCpuMs) में दिखाता है. Android 12 (एपीआई लेवल 31) और इसके बाद के वर्शन में, यह भी पता चलता है कि आपके फ़्रेम, तय सीमा से कितने ज़्यादा समय तक रेंडर हुए (frameOverrunMs). वैल्यू नेगेटिव हो सकती है. इसका मतलब है कि फ़्रेम को रेंडर करने के लिए, तय समय से ज़्यादा समय मिला.
नतीजों से पता चलता है कि CompilationBaselineProfiles की फ़्रेम अवधि औसतन 2 मि॰से॰ कम है. हालांकि, यह उपयोगकर्ताओं को शायद ही दिखे. हालांकि, अन्य पर्सेंटाइल के लिए नतीजे ज़्यादा साफ़ तौर पर दिखते हैं. P99 के लिए, यह अंतर 43.5 मि॰से॰ है. यह 90 FPS पर काम करने वाले डिवाइस पर, स्किप किए गए तीन से ज़्यादा फ़्रेम के बराबर है. उदाहरण के लिए, Pixel 6 के लिए यह 1000 मि॰से॰ / 90 एफ़पीएस = ~11 मि॰से॰ है. इसका मतलब है कि एक फ़्रेम को रेंडर करने में ज़्यादा से ज़्यादा 11 मि॰से॰ लगेंगे.
11. बधाई हो
बधाई हो, आपने इस कोडलैब को पूरा कर लिया है. साथ ही, बेसलाइन प्रोफ़ाइल की मदद से अपने ऐप्लिकेशन की परफ़ॉर्मेंस को बेहतर बना लिया है!
अन्य संसाधन
यहां दिए गए अन्य संसाधन देखें:
- मैक्रोबेंचमार्क की मदद से ऐप्लिकेशन की परफ़ॉर्मेंस की जांच करना: यह कोडलैब, बेंचमार्किंग के बारे में ज़्यादा जानकारी देता है.
- परफ़ॉर्मेंस के सैंपल: यह एक ऐसी रिपॉज़िटरी होती है जिसमें मैक्रोबेंचमार्क और परफ़ॉर्मेंस के अन्य सैंपल शामिल होते हैं.
- Now In Android सैंपल ऐप्लिकेशन: यह एक ऐसा ऐप्लिकेशन है जो परफ़ॉर्मेंस को बेहतर बनाने के लिए, बेंचमार्किंग और बेसलाइन प्रोफ़ाइलों का इस्तेमाल करता है.