केस स्टडी

Grab ने R8 और प्रोफ़ाइल गाइडेड ऑप्टिमाइज़ेशन की मदद से, ANR से जुड़ी गड़बड़ियों को 32% कम किया और ऐप्लिकेशन के खुलने में लगने वाले समय को 35% कम किया

पढ़ने में लगने वाला समय: 5 मिनट
3 लेखक
Ajesh Pai, Nguyen Van Minh, Tracy Agyemang

Grab, दक्षिण-पूर्व एशिया का एक लोकप्रिय सुपरऐप्लिकेशन है. यह एक ही ऐप्लिकेशन के ज़रिए, आठ देशों के लाखों उपयोगकर्ताओं को डिलीवरी, मोबिलिटी, और वित्तीय सेवाएं देता है. Grab की टीम को तीन बड़ी चुनौतियों का सामना करना पड़ा: ऐप्लिकेशन काम नहीं कर रहा है (एएनआर) गड़बड़ी की ज़्यादा दरें, ऐप्लिकेशन का साइज़ बढ़ना, और स्टार्टअप टाइम में साल दर साल बढ़ोतरी होना. ऐसा इसलिए हुआ, क्योंकि Grab का कोड बेस 10 साल पुराना था. इसमें एक करोड़ से ज़्यादा लाइन का कोड और तीसरे पक्ष की सैकड़ों लाइब्रेरी शामिल थीं. इन्हें Bazel और Gradle के हाइब्रिड सेटअप का इस्तेमाल करके बनाया गया था.  Grab ने R8 ऑप्टिमाइज़ेशन को चालू करके, कीप रूल को बेहतर बनाकर, और बेसलाइन प्रोफ़ाइलों और स्टार्टअप प्रोफ़ाइलों को लागू करके, यूज़र-पर्सीव्ड एएनआर रेट को 32% तक कम किया. साथ ही, ऐप्लिकेशन के डाउनलोड साइज़ को करीब 30% तक कम किया और स्टार्टअप टाइम को 35% तक बेहतर बनाया.

ऐप्लिकेशन रिलीज़ करने के बाद, एएनआर वाली गड़बड़ियों में होने वाली बढ़ोतरी को कम करना, ताकि उपयोगकर्ताओं को बेहतर अनुभव मिल सके

अपनी बिल्ड प्रोसेस को ऑप्टिमाइज़ करने से पहले, Grab को कोल्ड स्टार्ट में देरी और ऐप्लिकेशन के काम न करने (एएनआर) की गड़बड़ियों का सामना करना पड़ा. ऐसा नए अपडेट के तुरंत बाद हुआ. इसकी मुख्य वजह, ऐप्लिकेशन शुरू होने के दौरान कई DEX फ़ाइलों को पढ़ने में लगने वाला समय था. 

Google Play की क्लाउड प्रोफ़ाइलें, उपयोगकर्ताओं के पूरे ग्रुप के लिए स्टैंडर्ड फ़्लो को ऑप्टिमाइज़ करती हैं. हालांकि, वे Grab की क्रिटिकल यूज़र जर्नी के लिए ज़रूरी सभी इनिशलाइज़ेशन पाथ को ऑप्टिमाइज़ नहीं करती हैं. जैसे, ऐप्लिकेशन लॉन्च के दौरान डैगर डिपेंडेंसी ग्राफ़ को इनिशलाइज़ करना. शुरुआती डिस्ट्रिब्यूशन में शामिल नहीं किए गए कोड पाथ के लिए, डिवाइसों को जेआईटी कंपाइलेशन और आने वाले दिनों में लोकल बैकग्राउंड ऑप्टिमाइज़ेशन पर निर्भर रहना पड़ता था. कस्टम बेसलाइन प्रोफ़ाइल लागू करने से, यह समस्या हल हो गई. इससे, क्रिटिकल यूज़र जर्नी को सीधे Google Play की क्लाउड प्रोफ़ाइलों में उपलब्ध कराया गया. साथ ही, ऑप्टिमाइज़ेशन कवरेज को बढ़ाया गया, ताकि इन मुख्य पाथ को इंस्टॉलेशन के समय ही मशीन कोड में कंपाइल किया जा सके 

ANDDM_Grab_Inline_Quote_ALT.png

Grab की पैसेंजर ऐप्लिकेशन कोर टीम के लीड सॉफ़्टवेयर इंजीनियर, न्गुयेन वैन मिन्ह ने बताया, "हर हफ़्ते ऐप्लिकेशन रिलीज़ करने पर, हमें लगातार एएनआर रेट में बढ़ोतरी देखने को मिली." 

ANR की गड़बड़ियों को खत्म करने और ऐप्लिकेशन के खुलने में लगने वाले समय को कम करने के लिए, Grab ने R8 ऑप्टिमाइज़ेशन, बेसलाइन प्रोफ़ाइलें, और स्टार्टअप प्रोफ़ाइलें लागू कीं. प्रोफ़ाइल गाइडेड ऑप्टिमाइज़ेशन और R8 ऑप्टिमाइज़र की मदद से, कोल्ड स्टार्ट में तुरंत 12% का सुधार हुआ. साथ ही, बेसलाइन प्रोफ़ाइलों की मदद से 15% का सुधार हुआ. इससे ऐप्लिकेशन के स्टार्टअप समय में 27% की कमी आई और रिलीज़ के बाद एएनआर की संख्या में होने वाली बढ़ोतरी को कम किया जा सका.

Grab ने इस ऐप्लिकेशन ऑप्टिमाइज़ेशन को तीन रणनीतिक चरणों में लागू किया: कंपैटिबिलिटी मोड में R8 ऑप्टिमाइज़ेशन चालू करना, R8 के फ़ुल मोड पर स्विच करना, और फिर कॉन्फ़िगरेशन ऐनलाइज़र की मदद से 'कीप रूल' को बेहतर बनाना और सीआई/सीडी गवर्नेंस जोड़ना.

पहला चरण: R8 ऑप्टिमाइज़ेशन की सुविधा चालू करना  (2025 में लॉन्च किया गया)

इस पहले चरण में, Grab ने लेगसी डिफ़ॉल्ट Proguard फ़ाइल को छोड़कर, proguard-android-optimize.txt को अपनाया. इससे R8 ऑप्टिमाइज़ेशन की सुविधा चालू हो जाती है.  कोड बेस एक दशक से ज़्यादा पुराना था और इसमें एक करोड़ से ज़्यादा लाइन का कोड था. इसलिए, ऑप्टिमाइज़र को चालू करने के लिए, लेगसी कॉन्फ़िगरेशन और रिफ़्लेक्शन के इस्तेमाल को मैनेज करना ज़रूरी था.

इस फ़ेज़ का ज़्यादा से ज़्यादा फ़ायदा पाने के लिए, Grab ने बेसलाइन प्रोफ़ाइलों और स्टार्टअप प्रोफ़ाइलों के साथ, R8 कंपैट मोड चालू करके ऐप्लिकेशन का अपडेट रिलीज़ किया. इन सभी कोशिशों की वजह से, यूज़र-पर्सीव्ड एएनआर रेट में तुरंत 25% की कमी आई. साथ ही, ऐप्लिकेशन डाउनलोड करने के साइज़ में 16% की कमी आई और कोल्ड स्टार्ट के समय में कुल मिलाकर 27% का सुधार हुआ.

दूसरा चरण: R8 फ़ुल मोड और माइग्रेशन (2026 में लॉन्च किया गया)

पहले रोल आउट के नौ महीने बाद लॉन्च किए गए इस चरण में, ऐप्लिकेशन को R8 फ़ुल मोड में शिफ़्ट किया गया. इससे ऐप्लिकेशन को और ऑप्टिमाइज़ करने में मदद मिली. Retrofit, Firebase, और Jetpack Compose जैसी स्टैंडर्ड लाइब्रेरी, पहले से मौजूद नियमों का इस्तेमाल करके R8 के साथ आसानी से काम करती थीं. हालांकि, बाकी के बड़े कोड बेस को माइग्रेट करने के लिए, रिफ़्लेक्शन-हैवी कोड पाथ को ठीक करना पड़ा:

R8 के फ़ुल मोड पर माइग्रेट करने के लिए, टीम ने Gson के नए वर्शन से उपभोक्ता के लिए बनाए गए नियमों को अपनाया, ताकि JSON पार्सिंग आसानी से हो सके. उन्होंने Java डाइनैमिक प्रॉक्सी के साथ ऑप्टिमाइज़ेशन से जुड़ी चुनौतियों को भी हल किया. ये प्रॉक्सी, रनटाइम के दौरान इंटरफ़ेस लागू करने के लिए रिफ़्लेक्शन का इस्तेमाल करती हैं. R8, कंपाइलेशन के दौरान इस रनटाइम के इस्तेमाल का पता नहीं लगा सकता. इसलिए, यह ज़रूरी क्लास को हटा देता है या उनका नाम बदल देता है. इससे ऐप्लिकेशन क्रैश हो जाता है. ऐप्लिकेशन का साइज़ बढ़ाने वाले अपवादों को लागू करने के बजाय, टीम ने रिफ़्लेक्शन पर निर्भर खास क्लास को अलग किया. साथ ही, टारगेट किए गए नियमों को लागू किया. इससे ऐप्लिकेशन की परफ़ॉर्मेंस और ऑप्टिमाइज़ेशन की क्षमता, दोनों को बनाए रखा गया

आखिर में, R8 के फ़ुल मोड से कई बड़े और अहम सुधार हुए. इनमें ऐप्लिकेशन के डाउनलोड साइज़ में 14% की और कमी, ऐप्लिकेशन के शुरू होने में लगने वाले समय में 10% का और सुधार, और यूज़र-पर्सीव्ड एएनआर में 10% की और कमी शामिल है. R8 के फ़ुल मोड पर माइग्रेट करने के बाद, Grab के कोड बेस को ये R8 ऑप्टिमाइज़ेशन स्कोर मिले. 

  • ऑप्टिमाइज़ेशन स्कोर: 72%
  • साइज़ कम करने का स्कोर: 73%
  • कोड को अस्पष्ट बनाने का स्कोर: 79.6%

इन स्कोर से, R8 कॉन्फ़िगरेशन के बारे में सुझाव/राय या शिकायत मिलती है. साथ ही, R8 ऑप्टिमाइज़ेशन को बेहतर बनाने के लिए, 'कीप रूल' को बेहतर बनाने की ज़रूरत के बारे में पता चलता है. 

तीसरा चरण: Keep-Rule को बेहतर बनाना 

ऑप्टिमाइज़ेशन के आखिरी चरण में, Grab का फ़ोकस लंबे समय तक कोड बेस को बेहतर बनाए रखने, परफ़ॉर्मेंस की लगातार निगरानी करने, और कंपाइलेशन को बेहतर तरीके से मैनेज करने पर है. नियमों की क्वालिटी को व्यवस्थित तरीके से मेज़र करने और रिलीज़ साइकल के दौरान कॉन्फ़िगरेशन में होने वाली गड़बड़ियों को रोकने के लिए, टीम R8 कॉन्फ़िगरेशन ऐनलाइज़र को अपने इवैलुएशन वर्कफ़्लो में इंटिग्रेट कर रही है. इस टूल से यह जानकारी मिलती है कि Grab के कीप नियम, R8 को ऐप्लिकेशन को ऑप्टिमाइज़ करने, छोटा करने, और कोड को छिपाने की अनुमति कितने असरदार तरीके से देते हैं.

Grab ने R8 के फ़ुल मोड का इस्तेमाल करके और लेगसी कीप रूल को व्यवस्थित तरीके से हटाकर, ऐनालाइज़र की ओर से आकलन किए गए तीनों मुख्य डाइमेंशन में काफ़ी सुधार किए हैं:

  • ऑप्टिमाइज़ेशन स्कोर: 72% से बढ़कर 78.2% हो रहा है
  • रिसॉर्स को हटाने का स्कोर: 73% से बढ़कर 79.1% हो रहा है
  • कोड को अस्पष्ट बनाने का स्कोर: 79.6% से बढ़कर 81.7% हो गया है

इन डाइग्नोस्टिक स्कोर को बेहतर बनाने के अलावा, कीप-रूल को बेहतर बनाने के इस चरण से, ऐप्लिकेशन के डाउनलोड साइज़ में करीब 3.6% की और कमी आ रही है. इससे भी अहम बात यह है कि इन मेट्रिक को ट्रैक करने से, इंजीनियरिंग टीम को ज़रूरी डेटा मिलता है. इससे, मर्ज करने से पहले सीआई गार्डरेल को अपने-आप लागू करने में मदद मिलती है. इससे यह पक्का होता है कि नया कोड, कीप-रूल के सख्त स्टैंडर्ड का पालन करता है. साथ ही, समय के साथ परफ़ॉर्मेंस में होने वाले फ़ायदे सुरक्षित रहते हैं.

नतीजे

R8 ऑप्टिमाइज़र के रोल आउट होने के बाद, परफ़ॉर्मेंस में हुए अहम सुधार:

ऑप्टिमाइज़ेशन फ़ेज़ANRsसाइज़कोल्ड स्टार्ट
पहला चरण: R8 ऑप्टिमाइज़र (2025 में लॉन्च किया गया)~25% की कमी16% की कमी~27% सुधार
दूसरा चरण: R8 फ़ुल मोड (2026 में शिप किया गया)10% की कमी14% की कमी10% सुधार
Keep-Rule Optimization-3.6% की कमी-
कुल (कुल)~32.5% की कमी~30.4% की कमी~35% की बढ़ोतरी

तकनीकी चुनौतियां 

Grab के दशक पुराने कोड बेस में R8 ऑप्टिमाइज़र को चालू करने से, बड़े पैमाने पर तकनीकी समस्याएं आईं:

  • टेस्टिंग: पिछले एक दशक में इकट्ठा किए गए डेटा की मदद से, हमने ऑप्टिमाइज़ेशन के दौरान आने वाली समस्याओं को हल किया. लाखों LOC की पूरी तरह से जांच करना नामुमकिन था. इसलिए, टीम ने प्राथमिकता के हिसाब से धीरे-धीरे जांच करने का तरीका अपनाया. खास तौर पर, उस कोड की जांच करने पर ध्यान दिया गया जो कीप रूल के दायरे में आता है. साथ ही, उन नियमों को बार-बार बेहतर बनाया गया, ताकि सिर्फ़ उन क्लास, मेथड या फ़ील्ड को टारगेट किया जा सके जो रिफ़्लेक्शन के लिए ज़रूरी हैं. इससे R8 ऑप्टिमाइज़ेशन को बेहतर बनाने में मदद मिली
  • बिल्ड इंतज़ार का समय और हाइब्रिड आर्किटेक्चर: Grab के हाइब्रिड बिल्ड सिस्टम (डीबग के लिए Bazel, R8 रिलीज़ के लिए तैयार बिल्ड के लिए Gradle) का मतलब है कि R8 में किए गए एक्सपेरिमेंटल बदलावों को रिमोट सीआई में लागू होने में दो घंटे तक का समय लगता था. फ़ीडबैक के गैप को कम करने के लिए, Grab ने अपने रोज़ के QA बिल्ड को प्रोडक्शन R8 के व्यवहार के साथ अलाइन किया. साथ ही, mapping.txt और configuration.txt जैसे मुख्य सीआई बिल्ड आर्टफ़ैक्ट को इकट्ठा करने की प्रोसेस को ऑटोमेट किया, ताकि जांच को आसान बनाया जा सके.
  • डीबग करने में ज़्यादा समय लगना: ऑप्टिमाइज़ की गई सैकड़ों क्लास में असल वजहों का पता लगाने से, छोटी टीम पर काफ़ी बोझ पड़ता था. Grab ने इस समस्या को हल करने के लिए, Gradle के ज़रिए Firebase Crashlytics पर मैपिंग फ़ाइल अपलोड करने की प्रोसेस को ऑटोमेट किया. साथ ही, Play Console के लिए डिकोड करने वाली मैपिंग को बंडल किया. इससे रनटाइम से जुड़ी समस्याओं के लिए, तुरंत और सटीक सिंबल रिज़ॉल्यूशन की सुविधा चालू हो गई

R8 की मदद से, कोड पर लंबे समय तक पड़ने वाला असर

R8 ऑप्टिमाइज़र को चालू करने से, Grab को तुरंत परफ़ॉर्मेंस में सुधार देखने को मिला. साथ ही, इसके बड़े कोड बेस को हमेशा के लिए एक बेहतर स्ट्रक्चर मिला. Grab में, टीम ने R8 के असर का आकलन करने के लिए, ओपन सोर्स टूल app-sizer का इस्तेमाल किया. इससे पता चला कि R8 ने ऐप्लिकेशन के डाउनलोड साइज़ में, कोड की हर लाइन की लागत को हमेशा के लिए कम कर दिया है.

ANDDM_Grab_Inline_Metric.png

एआई की मदद से डेवलपमेंट के इस दौर में, जहां कोड की संख्या तेज़ी से बढ़ रही है, यह ऑप्टिमाइज़ेशन और भी ज़रूरी हो गया है. R8 के बिना, कोड एक्सपैंशन की वजह से डाउनलोड साइज़ बढ़ जाता है. R8 यह पक्का करता है कि कोड एक्सपैंशन की दर एक जैसी होने पर भी, मेमोरी फ़ुटप्रिंट में काफ़ी कमी आए.

ध्यान दें: तरीका: ऐप्लिकेशन डाउनलोड साइज़ (रिप्रज़ेंटेटिव डिवाइस) में, app-sizer के Kotlin/Java का योगदान. इसे प्रोडक्शन Kotlin LOC (cloc; सिर्फ़ मुख्य सोर्स सेट; टेस्ट, मॉक, और सैंपल मॉड्यूल शामिल नहीं हैं) से भाग दिया जाता है.

Keep में नियम मैनेज करना और सुरक्षा के उपाय

Grab, नियम की क्वालिटी को कम होने से रोकने और समय के साथ R8 ऑप्टिमाइज़ेशन को बनाए रखने के लिए, अपने-आप मर्ज होने से पहले की सुरक्षा सुविधाओं को सीधे अपने सीआई पाइपलाइन में इंटिग्रेट करने की योजना बना रहा है. इस नीति के तहत, डेटा को सेव रखने के नए नियमों पर पाबंदी है. अगर कोई अतिरिक्त नियम लागू करना है, तो उसके लिए साफ़ तौर पर वजह बतानी होगी और उसकी समीक्षा करानी होगी. Grab की टीम, सीआई में R8 ऑप्टिमाइज़ेशन स्कोर को ट्रैक करती है. इसके आधार पर, टीम इन मेट्रिक को लगातार फ़ीडबैक लूप के तौर पर इस्तेमाल करने की योजना बना रही है. इससे, मर्ज करने से पहले ही रिग्रेशन का पता लगाया जा सकता है और हर रिलीज़ साइकल में ऑप्टिमाइज़ेशन के फ़ायदों को सुरक्षित रखा जा सकता है. 

R8-rules-score (1).png

पहली इमेज: सीआई डैशबोर्ड, Grab बिल्ड में समय के साथ R8 के श्रिंकिंग, ऑप्टिमाइज़ेशन, और कोड को छिपाने के स्कोर को ट्रैक करता है. इससे रिलीज़ के दौरान, रिग्रेशन का पता लगाने और उन्हें रोकने में मदद मिलती है.

निष्कर्ष 

Grab की Pax App Core टीम को बड़े और लगातार बढ़ रहे कोड बेस की वजह से, ऐप्लिकेशन के स्टार्टअप में लगने वाले समय और रिलीज़ के बाद परफ़ॉर्मेंस में आने वाली रुकावटों जैसी चुनौतियों का सामना करना पड़ा. इन चुनौतियों से निपटने के लिए, टीम ने बेसलाइन प्रोफ़ाइलें लागू कीं और R8 कॉन्फ़िगरेशन को लगातार बेहतर बनाया. टीम ने यूज़र-पर्सीव्ड एएनआर को करीब 32.5% और ऐप्लिकेशन के डाउनलोड साइज़ को करीब 30.3% कम किया. साथ ही, कोल्ड स्टार्ट में लगने वाले समय को करीब 35% कम किया. इसके अलावा, टीम ने अपने कोड बेस को स्केल करने की क्षमता को भी बेहतर बनाया.

इन ऑप्टिमाइज़ेशन की मदद से, दक्षिण-पूर्व एशिया के लाखों उपयोगकर्ताओं को Grab के सुपरऐप्लिकेशन का तेज़ और ज़्यादा बेहतर अनुभव मिला. साथ ही, Grab के इंजीनियर को ऐसी सुविधाएं तेज़ी से बनाने के लिए टूल मिले जिनसे डाउनलोड साइज़ में तेज़ी से बढ़ोतरी नहीं हुई.

R8 का इस्तेमाल शुरू करने और इसके बारे में ज़्यादा जानने के लिए, - d.android.com/r8 पर जाएं.

लेखक:
पढ़ना जारी रखें