धीरे-धीरे ऑप्टिमाइज़ेशन को अपनाना

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

ऑप्टिमाइज़ेशन को सीमित करना

R8 कई तरह के ऑप्टिमाइज़ेशन करता है. जैसे, कोड हटाना, कोड को फिर से लिखना, और रिसॉर्स हटाना. यहां ऑप्टिमाइज़ेशन के टाइप के बारे में खास जानकारी दी गई है:

  • कोड छोटा करना (या ट्री शेकिंग): इससे ऐसे कोड हटाए जाते हैं जिनका रेफ़रंस नहीं दिया गया है
  • ऑब्फ़स्केशन (या आइडेंटिफ़ायर को छोटा करना): इससे क्लास और मेथड के नामों को छोटा किया जाता है
  • ऑप्टिमाइज़ेशन: कोड को फिर से लिखता है. उदाहरण के लिए, इनलाइनिंग

गड़बड़ियों की संभावना को कम करने के लिए, इनमें से सिर्फ़ कुछ ऑप्टिमाइज़ेशन चालू करें.

सिर्फ़ ट्री शेकिंग की सुविधा चालू करना

कोड छोटा करने की प्रोसेस को ट्री शेकिंग भी कहा जाता है. इसमें ऐसे कोड को हटा दिया जाता है जिसका कोई रेफ़रंस नहीं होता. हमारा सुझाव है कि आप सिर्फ़ ट्री शेकिंग से शुरुआत करें, क्योंकि यह सबसे आसान तरीका है.

सिर्फ़ ट्री शेकिंग की सुविधा चालू करने के लिए, अपनी proguard-rules.pro फ़ाइल में यह कोड जोड़ें. इससे अन्य तरह के ऑप्टिमाइज़ेशन बंद हो जाएंगे. कोड को अस्पष्ट करने की सुविधा को बंद करना ज़रूरी है, क्योंकि इससे स्टैक ट्रेस को पढ़ना आसान हो जाता है.

-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization

आखिर में, आपको इस कॉन्फ़िगरेशन को शिप नहीं करना चाहिए, क्योंकि इससे R8 की कोड को ऑप्टिमाइज़ करने की क्षमता काफ़ी कम हो जाती है. हालांकि, यह एक बेहतरीन शुरुआती पॉइंट है. ऐसा तब होता है, जब आपको ठीक की जाने वाली समस्याओं वाले बड़े कोड बेस में पहली बार R8 को अपनाना हो.

कंपैट मोड का इस्तेमाल करना

डिफ़ॉल्ट रूप से, R8 फ़ुल मोड में चलता है. फ़ुल मोड से, परफ़ॉर्मेंस में काफ़ी सुधार होता है और साइज़ की बचत होती है. हालांकि, पहली बार काट-छांट की सुविधा चालू करते समय, इसे कुछ समय के लिए बंद किया जा सकता है. इसके बजाय, कंपैट मोड का इस्तेमाल किया जा सकता है.

कंपैट मोड का इस्तेमाल करने के लिए, अपनी gradle.properties फ़ाइल में यह सेटिंग इस्तेमाल करें:

android.enableR8.fullMode = false // Use temporarily to disable full mode

बाकी ऑप्टिमाइज़ेशन चालू करना

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

स्टैक ट्रेस को डिकोड करने के बारे में ज़्यादा जानने के लिए, ओरिजनल स्टैक ट्रेस वापस पाना लेख पढ़ें.

ऑप्टिमाइज़ेशन के दायरे को सीमित करना

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

पूरे पैकेज के लिए, निजी डेटा के रखरखाव के नियमों का इस्तेमाल करना

हमारा सुझाव है कि आप पैकेज-वाइड कीप रूल का इस्तेमाल करें. इससे आपके ऐप्लिकेशन के कुछ हिस्सों में, R8 को कुछ समय के लिए बंद किया जा सकता है. आपको ऑप्टिमाइज़ेशन से जुड़ी इन समस्याओं को ठीक करने के लिए, बाद में वापस आना चाहिए. आम तौर पर, यह समस्या वाले हिस्सों को ठीक करने का एक अस्थायी समाधान है.

उदाहरण के लिए, अगर आपके ऐप्लिकेशन का कोई हिस्सा Gson का ज़्यादा इस्तेमाल करता है और इससे ऑप्टिमाइज़ेशन में समस्याएं आ रही हैं, तो सबसे अच्छा तरीका यह है कि ज़्यादा टारगेट किए गए कीप नियम जोड़ें या कोड जनरेट करने वाले समाधान पर जाएं. हालांकि, ऐप्लिकेशन के बाकी हिस्सों को ऑप्टिमाइज़ करने की सुविधा को अनब्लॉक करने के लिए, अपने Gson टाइप को तय करने वाले कोड को किसी खास सबपैकेज में रखा जा सकता है. साथ ही, अपनी proguard-rules.pro फ़ाइल में इस तरह का नियम जोड़ा जा सकता है:

-keep class com.myapp.json.** { *; }

अगर इस्तेमाल की जा रही किसी लाइब्रेरी में, अंदरूनी कॉम्पोनेंट के लिए रिफ़्लेक्शन है, तो पूरी लाइब्रेरी के लिए, सुरक्षित रखने का नियम जोड़ा जा सकता है. आपको लाइब्रेरी के कोड या JAR/AAR की जांच करनी होगी, ताकि आप सही पैकेज ढूंढ सकें. हम इसे लंबे समय तक इस्तेमाल करने का सुझाव नहीं देते. हालांकि, इससे ऐप्लिकेशन के बाकी हिस्से को ऑप्टिमाइज़ किया जा सकता है:

-keep class com.somelibrary.** { *; }

पूरे पैकेज के लिए लागू होने वाले कीप नियमों को हटाना

जब आपका ऐप्लिकेशन, पैकेज-वाइड कीप नियमों के साथ सही तरीके से काम करने लगे, तो आपको वापस जाकर टारगेट किए गए कीप नियम जोड़ने चाहिए. इसके अलावा, रिफ़्लेक्शन के इस्तेमाल या लाइब्रेरी को हटा देना चाहिए. इसकी वजह से, कीप नियम की ज़रूरत पड़ती है.

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

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