एंड्रॉइड 8.0 एआरटी में सुधार

एंड्रॉइड 8.0 रिलीज़ में एंड्रॉइड रनटाइम (एआरटी) में काफी सुधार किया गया है। नीचे दी गई सूची उन संवर्द्धनों का सारांश प्रस्तुत करती है जिनकी उपकरण निर्माता एआरटी में अपेक्षा कर सकते हैं।

समवर्ती कॉम्पैक्टिंग कचरा संग्रहकर्ता

जैसा कि Google I/O में घोषणा की गई है, ART एंड्रॉइड 8.0 में एक नया समवर्ती कॉम्पैक्टिंग कचरा संग्रहकर्ता (GC) पेश करता है। यह कलेक्टर हर बार जीसी चलने पर और ऐप चलने के दौरान, थ्रेड रूट्स को संसाधित करने के लिए केवल एक छोटे से विराम के साथ ढेर को कॉम्पैक्ट करता है। यहाँ इसके लाभ हैं:

  • जीसी हमेशा ढेर को संकुचित करता है: एंड्रॉइड 7.0 की तुलना में औसतन 32% छोटे ढेर आकार।
  • कॉम्पैक्शन थ्रेड लोकल बम्प पॉइंटर ऑब्जेक्ट आवंटन को सक्षम बनाता है: एंड्रॉइड 7.0 की तुलना में आवंटन 70% तेज है।
  • एंड्रॉइड 7.0 GC की तुलना में H2 बेंचमार्क के लिए 85% कम ठहराव समय प्रदान करता है।
  • ढेर के आकार के साथ रुकने का समय अब ​​मापनीय नहीं रह गया है; ऐप्स को जंक की चिंता किए बिना बड़े ढेरों का उपयोग करने में सक्षम होना चाहिए।
  • जीसी कार्यान्वयन विवरण - बाधाएँ पढ़ें:
    • रीड बैरियर प्रत्येक रीड ऑब्जेक्ट फ़ील्ड के लिए किए गए कार्य की एक छोटी मात्रा है।
    • ये कंपाइलर में अनुकूलित हैं, लेकिन कुछ उपयोग मामलों को धीमा कर सकते हैं।

लूप अनुकूलन

एंड्रॉइड 8.0 रिलीज़ में एआरटी द्वारा विभिन्न प्रकार के लूप अनुकूलन नियोजित किए गए हैं:

  • सीमाएँ उन्मूलन की जाँच करती हैं
    • स्थैतिक: संकलन-समय पर श्रेणियाँ सीमा के भीतर साबित होती हैं
    • गतिशील: रन-टाइम परीक्षण सुनिश्चित करते हैं कि लूप सीमा के भीतर रहें (अन्यथा अलग करें)
  • प्रेरण चर उन्मूलन
    • मृत प्रेरण निकालें
    • इंडक्शन को बदलें जो केवल लूप के बाद बंद-फॉर्म अभिव्यक्तियों द्वारा उपयोग किया जाता है
  • लूप-बॉडी के अंदर डेड कोड का उन्मूलन, पूरे लूप को हटाना जो डेड हो जाते हैं
  • ताकत में कमी
  • लूप ट्रांसफॉर्मेशन: रिवर्सल, इंटरचेंजिंग, स्प्लिटिंग, अनरोलिंग, यूनिमॉड्यूलर, आदि।
  • SIMDization (जिसे वैश्वीकरण भी कहा जाता है)

लूप ऑप्टिमाइज़र एआरटी कंपाइलर में अपने स्वयं के अनुकूलन पास में रहता है। अधिकांश लूप अनुकूलन अन्यत्र अनुकूलन और सरलीकरण के समान हैं। कुछ अनुकूलन के साथ चुनौतियाँ उत्पन्न होती हैं जो सीएफजी को सामान्य से अधिक विस्तृत तरीके से फिर से लिखते हैं, क्योंकि अधिकांश सीएफजी उपयोगिताएँ (नोड्स.एच देखें) सीएफजी के निर्माण पर ध्यान केंद्रित करती हैं, न कि उसे फिर से लिखने पर।

वर्ग पदानुक्रम विश्लेषण

एंड्रॉइड 8.0 में एआरटी क्लास पदानुक्रम विश्लेषण (सीएचए) का उपयोग करता है, एक कंपाइलर ऑप्टिमाइज़ेशन जो क्लास पदानुक्रमों का विश्लेषण करके उत्पन्न जानकारी के आधार पर वर्चुअल कॉल को सीधे कॉल में बदल देता है। वर्चुअल कॉल महंगी होती हैं क्योंकि वे एक व्यवहार्य लुकअप के आसपास कार्यान्वित की जाती हैं, और वे कुछ निर्भर भार लेते हैं। साथ ही वर्चुअल कॉल को इनलाइन नहीं किया जा सकता.

यहां संबंधित संवर्द्धनों का सारांश दिया गया है:

  • गतिशील एकल-कार्यान्वयन विधि स्थिति अद्यतन - क्लास लिंकिंग समय के अंत में, जब वीटेबल पॉप्युलेट हो जाता है, एआरटी सुपर क्लास के वीटेबल के साथ एंट्री-बाय-एंट्री तुलना करता है।
  • कंपाइलर अनुकूलन - कंपाइलर किसी विधि के एकल-कार्यान्वयन जानकारी का लाभ उठाएगा। यदि किसी विधि A.foo में एकल-कार्यान्वयन ध्वज सेट है, तो कंपाइलर वर्चुअल कॉल को डायरेक्ट कॉल में डीवर्चुअलाइज़ कर देगा, और परिणामस्वरूप डायरेक्ट कॉल को इनलाइन करने का प्रयास करेगा।
  • संकलित कोड अमान्यकरण - क्लास लिंकिंग समय के अंत में जब एकल-कार्यान्वयन जानकारी अद्यतन की जाती है, यदि विधि A.foo जिसमें पहले एकल-कार्यान्वयन था लेकिन वह स्थिति अब अमान्य हो गई है, तो सभी संकलित कोड जो विधि ए की धारणा पर निर्भर करते हैं। foo को एकल-कार्यान्वयन के लिए अपने संकलित कोड को अमान्य करने की आवश्यकता है।
  • डीऑप्टिमाइज़ेशन - स्टैक पर मौजूद लाइव संकलित कोड के लिए, शुद्धता की गारंटी के लिए अमान्य संकलित कोड को दुभाषिया मोड में मजबूर करने के लिए डीऑप्टिमाइज़ेशन शुरू किया जाएगा। डीऑप्टिमाइज़ेशन का एक नया तंत्र जो सिंक्रोनस और एसिंक्रोनस डीऑप्टिमाइज़ेशन का एक संकर है, का उपयोग किया जाएगा।

.oat फ़ाइलों में इनलाइन कैश

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

डेक्सलेआउट

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

चूँकि प्रोफ़ाइल जानकारी वर्तमान में केवल ऐप्स चलाने के बाद ही उपलब्ध होती है, निष्क्रिय रखरखाव के दौरान डेक्सलेआउट को dex2oat के ऑन-डिवाइस संकलन में एकीकृत किया जाता है।

डेक्स कैश हटाना

Android 7.0 तक, DexCache ऑब्जेक्ट के पास चार बड़े सरणियाँ होती थीं, जो DexFile में कुछ तत्वों की संख्या के अनुपात में होती थीं, अर्थात्:

  • स्ट्रिंग्स (प्रति DexFile::StringId एक संदर्भ),
  • प्रकार (प्रति DexFile::TypeId एक संदर्भ),
  • विधियाँ (प्रति DexFile::MethodId एक मूल सूचक),
  • फ़ील्ड्स (प्रति DexFile::FieldId एक मूल सूचक)।

इन सरणियों का उपयोग उन वस्तुओं की तेजी से पुनर्प्राप्ति के लिए किया गया था जिन्हें हमने पहले हल किया था। एंड्रॉइड 8.0 में, मेथड्स ऐरे को छोड़कर सभी ऐरे हटा दिए गए हैं।

दुभाषिया प्रदर्शन

एंड्रॉइड 7.0 रिलीज़ में "mterp" की शुरुआत के साथ दुभाषिया के प्रदर्शन में काफी सुधार हुआ - एक दुभाषिया जो असेंबली भाषा में लिखे गए कोर फ़ेच/डिकोड/इंटरप्रेट तंत्र की विशेषता रखता है। Mterp को तेज़ डेल्विक दुभाषिया के बाद तैयार किया गया है, और यह आर्म, आर्म64, x86, x86_64, mips और mips64 का समर्थन करता है। कम्प्यूटेशनल कोड के लिए, आर्ट का mterp मोटे तौर पर डाल्विक के तेज़ दुभाषिया के बराबर है। हालाँकि, कुछ स्थितियों में यह महत्वपूर्ण - और यहाँ तक कि नाटकीय रूप से - धीमा भी हो सकता है:

  1. प्रदर्शन का आह्वान करें.
  2. स्ट्रिंग हेरफेर, और विधियों के अन्य भारी उपयोगकर्ताओं को दल्विक में आंतरिक के रूप में मान्यता दी गई है।
  3. उच्च स्टैक मेमोरी उपयोग।

एंड्रॉइड 8.0 इन समस्याओं का समाधान करता है।

अधिक इनलाइनिंग

एंड्रॉइड 6.0 के बाद से, एआरटी एक ही डीएक्स फाइलों के भीतर किसी भी कॉल को इनलाइन कर सकता है, लेकिन विभिन्न डीएक्स फाइलों से केवल इनलाइन लीफ विधियों को ही इनलाइन कर सकता है। इस सीमा के दो कारण थे:

  1. किसी अन्य डेक्स फ़ाइल से इनलाइनिंग के लिए उसी डेक्स फ़ाइल इनलाइनिंग के विपरीत, उस अन्य डेक्स फ़ाइल के डेक्स कैश का उपयोग करने की आवश्यकता होती है, जो केवल कॉलर के डेक्स कैश का पुन: उपयोग कर सकता है। स्थिर कॉल, स्ट्रिंग लोड या क्लास लोड जैसे कुछ निर्देशों के लिए संकलित कोड में डेक्स कैश की आवश्यकता होती है।
  2. स्टैक मानचित्र केवल वर्तमान डेक्स फ़ाइल के भीतर एक विधि सूचकांक को एन्कोड कर रहे हैं।

इन सीमाओं को संबोधित करने के लिए, Android 8.0:

  1. संकलित कोड से डेक्स कैश एक्सेस को हटाता है ("डेक्स कैश रिमूवल" अनुभाग भी देखें)
  2. स्टैक मैप एन्कोडिंग का विस्तार करता है।

तुल्यकालन सुधार

एआरटी टीम ने मॉनिटरएंटर/मॉनिटरएक्सिट कोड पथों को ट्यून किया, और एआरएमवी8 पर पारंपरिक मेमोरी बाधाओं पर हमारी निर्भरता कम कर दी, जहां संभव हो उन्हें नए (अधिग्रहण/रिलीज) निर्देशों के साथ बदल दिया।

तेज़ देशी तरीके

जावा नेटिव इंटरफ़ेस (जेएनआई) पर तेज़ देशी कॉल @FastNative और @CriticalNative एनोटेशन का उपयोग करके उपलब्ध हैं। ये अंतर्निहित एआरटी रनटाइम अनुकूलन जेएनआई बदलावों को गति देते हैं और अब अप्रचलित !बैंग जेएनआई नोटेशन को प्रतिस्थापित करते हैं। एनोटेशन का गैर-देशी तरीकों पर कोई प्रभाव नहीं पड़ता है और ये केवल bootclasspath पर प्लेटफ़ॉर्म जावा भाषा कोड के लिए उपलब्ध हैं (कोई प्ले स्टोर अपडेट नहीं)।

@FastNative एनोटेशन गैर-स्थैतिक तरीकों का समर्थन करता है। यदि कोई विधि किसी jobject पैरामीटर या रिटर्न वैल्यू के रूप में एक्सेस करती है तो इसका उपयोग करें।

@CriticalNative एनोटेशन निम्नलिखित प्रतिबंधों के साथ, देशी तरीकों को चलाने का और भी तेज़ तरीका प्रदान करता है:

  • विधियाँ स्थिर होनी चाहिए—पैरामीटर, रिटर्न मान या अंतर्निहित this के लिए कोई ऑब्जेक्ट नहीं।
  • केवल आदिम प्रकार को मूल विधि में पारित किया जाता है।
  • मूल विधि अपनी फ़ंक्शन परिभाषा में JNIEnv और jclass पैरामीटर का उपयोग नहीं करती है।
  • डायनामिक जेएनआई लिंकिंग पर निर्भर रहने के बजाय विधि को RegisterNatives के साथ पंजीकृत किया जाना चाहिए।

@FastNative देशी पद्धति के प्रदर्शन को 3x तक और @CriticalNative 5x तक सुधार सकता है। उदाहरण के लिए, Nexus 6P डिवाइस पर मापा गया JNI संक्रमण:

जावा नेटिव इंटरफ़ेस (जेएनआई) मंगलाचरण निष्पादन समय (नैनोसेकंड में)
नियमित जेएनआई 115
!बैंग जेएनआई 60
@FastNative 35
@CriticalNative 25