जिटर-संबंधित जंक की पहचान करना

जिटर एक यादृच्छिक सिस्टम व्यवहार है जो प्रत्यक्ष कार्य को चलने से रोकता है। यह पृष्ठ वर्णन करता है कि घबराहट संबंधी जंक समस्याओं को कैसे पहचाना जाए और उनका समाधान कैसे किया जाए।

एप्लिकेशन थ्रेड शेड्यूलर विलंब

शेड्यूलर में देरी घबराहट का सबसे स्पष्ट लक्षण है: एक प्रक्रिया जिसे चलाया जाना चाहिए उसे चलाने योग्य बना दिया जाता है लेकिन कुछ महत्वपूर्ण समय तक नहीं चलता है। विलंब का महत्व संदर्भ के अनुसार भिन्न होता है। उदाहरण के लिए:

  • किसी ऐप में एक यादृच्छिक सहायक थ्रेड संभवतः बिना किसी समस्या के कई मिलीसेकंड तक विलंबित हो सकता है।
  • किसी एप्लिकेशन का यूआई थ्रेड 1-2ms की घबराहट को सहन करने में सक्षम हो सकता है।
  • SCHED_FIFO के रूप में चलने वाले ड्राइवर kthreads यदि चलने से पहले 500us के लिए चलाने योग्य हैं तो समस्याएँ पैदा हो सकती हैं।

थ्रेड के रनिंग सेगमेंट से पहले की नीली पट्टी द्वारा सिस्ट्रेस में रन करने योग्य समय की पहचान की जा सकती है। किसी थ्रेड के लिए sched_wakeup इवेंट और थ्रेड निष्पादन की शुरुआत का संकेत देने वाले sched_switch इवेंट के बीच समय की लंबाई से भी चलने योग्य समय निर्धारित किया जा सकता है।

धागे जो बहुत लंबे चलते हैं

एप्लिकेशन यूआई थ्रेड जो बहुत लंबे समय तक चलने योग्य हैं, समस्याएं पैदा कर सकते हैं। लंबे समय तक चलने योग्य समय वाले निचले स्तर के थ्रेड के आम तौर पर अलग-अलग कारण होते हैं, लेकिन यूआई थ्रेड के चलने योग्य समय को शून्य की ओर धकेलने का प्रयास करने के लिए कुछ समान मुद्दों को ठीक करने की आवश्यकता हो सकती है जो निचले स्तर के थ्रेड को लंबे समय तक चलने योग्य समय का कारण बनते हैं। देरी को कम करने के लिए:

  1. थर्मल थ्रॉटलिंग में वर्णित अनुसार सीपीयूसेट का उपयोग करें।
  2. CONFIG_HZ मान बढ़ाएँ।
    • ऐतिहासिक रूप से, आर्म और आर्म64 प्लेटफॉर्म पर मान 100 निर्धारित किया गया है। हालाँकि, यह इतिहास की एक दुर्घटना है और इंटरैक्टिव उपकरणों के लिए उपयोग करने के लिए यह अच्छा मूल्य नहीं है। CONFIG_HZ=100 का अर्थ है कि एक पल 10ms लंबा है, जिसका अर्थ है कि सीपीयू के बीच लोड संतुलन होने में 20ms (दो पल) लग सकते हैं। यह लोडेड सिस्टम पर जंक में महत्वपूर्ण योगदान दे सकता है।
    • हाल के डिवाइस (Nexus 5X, Nexus 6P, Pixel, और Pixel XL) CONFIG_HZ=300 के साथ शिप किए गए हैं। इसमें बिजली की लागत नगण्य होनी चाहिए जबकि चलने योग्य समय में उल्लेखनीय सुधार होना चाहिए। यदि आपको CONFIG_HZ बदलने के बाद बिजली की खपत या प्रदर्शन समस्याओं में उल्लेखनीय वृद्धि दिखाई देती है, तो संभव है कि आपका कोई ड्राइवर मिलीसेकंड के बजाय कच्चे जिफ़ियों पर आधारित टाइमर का उपयोग कर रहा है और जिफ़ियों में परिवर्तित कर रहा है। यह आम तौर पर एक आसान समाधान है ( पैच देखें जो CONFIG_HZ=300 में कनवर्ट करते समय Nexus 5X और 6P पर kgsl टाइमर समस्याओं को ठीक करता है)।
    • अंत में, हमने नेक्सस/पिक्सेल पर CONFIG_HZ=1000 के साथ प्रयोग किया है और पाया है कि यह आरसीयू ओवरहेड में कमी के कारण ध्यान देने योग्य प्रदर्शन और बिजली में कमी प्रदान करता है।

अकेले उन दो परिवर्तनों के साथ, एक डिवाइस को लोड के तहत यूआई थ्रेड चलाने योग्य समय के लिए बहुत बेहतर दिखना चाहिए।

Sys.use_fifo_ui का उपयोग करना

आप sys.use_fifo_ui प्रॉपर्टी को 1 पर सेट करके UI थ्रेड के चलने योग्य समय को शून्य पर लाने का प्रयास कर सकते हैं।

चेतावनी : जब तक आपके पास क्षमता-जागरूक आरटी शेड्यूलर न हो, विषम सीपीयू कॉन्फ़िगरेशन पर इस विकल्प का उपयोग न करें। और, इस समय, कोई भी वर्तमान शिपिंग आरटी शेड्यूलर क्षमता से अवगत नहीं है । हम ईएएस के लिए एक पर काम कर रहे हैं, लेकिन यह अभी तक उपलब्ध नहीं है। डिफ़ॉल्ट आरटी शेड्यूलर पूरी तरह से आरटी प्राथमिकताओं पर आधारित है और क्या सीपीयू में पहले से ही समान या उच्च प्राथमिकता का आरटी थ्रेड है।

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

जब sys.use_fifo_ui सक्षम होता है, तो एक्टिविटी मैनेजर शीर्ष एप्लिकेशन के यूआई थ्रेड और रेंडरथ्रेड (दो सबसे यूआई-महत्वपूर्ण थ्रेड) को ट्रैक करता है और उन थ्रेड्स को SCHED_OTHER के बजाय SCHED_FIFO बनाता है। यह यूआई और रेंडरथ्रेड्स से घबराहट को प्रभावी ढंग से समाप्त करता है; इस विकल्प सक्षम के साथ हमने जो निशान एकत्र किए हैं वे मिलीसेकंड के बजाय माइक्रोसेकंड के क्रम पर चलने योग्य समय दिखाते हैं।

हालाँकि, क्योंकि आरटी लोड बैलेंसर क्षमता-जागरूक नहीं था, एप्लिकेशन स्टार्टअप प्रदर्शन में 30% की कमी आई थी क्योंकि ऐप शुरू करने के लिए जिम्मेदार यूआई थ्रेड को 2.1 गीगाहर्ट्ज गोल्ड क्रियो कोर से 1.5 गीगाहर्ट्ज सिल्वर क्रियो कोर में स्थानांतरित कर दिया गया था। . क्षमता-जागरूक आरटी लोड बैलेंसर के साथ, हम अपने कई यूआई बेंचमार्क में थोक संचालन में समान प्रदर्शन और 95 वें और 99 वें प्रतिशत फ्रेम समय में 10-15% की कमी देखते हैं।

यातायात बाधित करें

क्योंकि एआरएम प्लेटफॉर्म केवल डिफ़ॉल्ट रूप से सीपीयू 0 में इंटरप्ट वितरित करते हैं, हम आईआरक्यू बैलेंसर (क्वालकॉम प्लेटफॉर्म पर irqbalance या msm_irqbalance) के उपयोग की सलाह देते हैं।

पिक्सेल विकास के दौरान, हमने जंक देखा जिसका सीधा कारण रुकावटों के साथ भारी सीपीयू 0 को माना जा सकता है। उदाहरण के लिए, यदि mdss_fb0 थ्रेड को CPU 0 पर शेड्यूल किया गया था, तो स्कैनआउट से लगभग तुरंत पहले डिस्प्ले द्वारा ट्रिगर होने वाली रुकावट के कारण जंक होने की बहुत अधिक संभावना थी। mdss_fb0 बहुत सख्त समय सीमा के साथ अपने स्वयं के काम के बीच में होगा, और फिर यह MDSS इंटरप्ट हैंडलर के लिए कुछ समय खो देगा। प्रारंभ में, हमने रुकावट के साथ विवाद से बचने के लिए mdss_fb0 थ्रेड की CPU एफ़िनिटी को CPU 1-3 पर सेट करके इसे ठीक करने का प्रयास किया, लेकिन तब हमें एहसास हुआ कि हमने अभी तक msm_irqbalance सक्षम नहीं किया है। Msm_irqbalance सक्षम होने के साथ, अन्य इंटरप्ट से कम विवाद के कारण mdss_fb0 और MDSS इंटरप्ट दोनों एक ही सीपीयू पर होने पर भी जंक में उल्लेखनीय सुधार हुआ था।

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

  • इंटरप्ट हैंडलर को तेज़ बनाएं.
  • रुकावट को पहले स्थान पर होने से रोकें।
  • व्यवधान की आवृत्ति को अन्य नियमित कार्यों के चरण से बाहर होने के लिए बदलें जिनमें यह हस्तक्षेप कर सकता है (यदि यह एक नियमित व्यवधान है)।
  • इंटरप्ट की सीपीयू एफ़िनिटी को सीधे सेट करें और इसे संतुलित होने से रोकें।
  • रुकावट से बचने के लिए उस थ्रेड की सीपीयू एफ़िनिटी सेट करें जिसमें रुकावट हस्तक्षेप कर रही है।
  • कम लोड वाले सीपीयू में इंटरप्ट को स्थानांतरित करने के लिए इंटरप्ट बैलेंसर पर भरोसा करें।

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

लंबे सॉफ्टिरक्स

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


सॉफ़्टिरक्यू किसी ट्रेस के irq अनुभाग के भीतर दिखाई देते हैं, इसलिए उन्हें पहचानना आसान होता है कि क्या ट्रेसिंग के दौरान समस्या को पुन: उत्पन्न किया जा सकता है। चूँकि एक सॉफ़्टिरक उपयोगकर्ता प्रक्रिया के भीतर चल सकता है, एक ख़राब सॉफ़्टिरक बिना किसी स्पष्ट कारण के उपयोगकर्ता प्रक्रिया के अंदर अतिरिक्त रनटाइम के रूप में भी प्रकट हो सकता है। यदि आप ऐसा देखते हैं, तो यह देखने के लिए कि क्या सॉफ़्टिरक्यूज़ दोषी हैं, irq अनुभाग की जाँच करें।

प्रीएम्प्शन या आईआरक्यू को बहुत लंबे समय तक अक्षम छोड़ने वाले ड्राइवर

बहुत लंबे समय (दसियों मिलीसेकंड) के लिए प्रीएम्प्शन या व्यवधान को अक्षम करने से जंक उत्पन्न होता है। आम तौर पर, जंक एक थ्रेड के चलने योग्य होने के रूप में प्रकट होता है लेकिन किसी विशेष सीपीयू पर नहीं चल रहा है, भले ही चलाने योग्य थ्रेड अन्य थ्रेड की तुलना में काफी अधिक प्राथमिकता (या SCHED_FIFO) हो।

कुछ दिशानिर्देश:

  • यदि रन करने योग्य थ्रेड SCHED_FIFO है और रनिंग थ्रेड SCHED_OTHER है, तो रनिंग थ्रेड में प्रीएम्प्शन या इंटरप्ट अक्षम है।
  • यदि रन करने योग्य थ्रेड, रनिंग थ्रेड (120) की तुलना में काफी अधिक प्राथमिकता (100) है, तो रन करने योग्य थ्रेड दो पलों के भीतर नहीं चलने पर संभवतः प्रीएम्प्शन या इंटरप्ट अक्षम हो जाता है।
  • यदि रन करने योग्य थ्रेड और रनिंग थ्रेड की प्राथमिकता समान है, तो रन करने योग्य थ्रेड 20ms के भीतर नहीं चलने पर रनिंग थ्रेड में प्रीएम्प्शन या इंटरप्ट अक्षम होने की संभावना है।

ध्यान रखें कि इंटरप्ट हैंडलर चलाने से आप अन्य इंटरप्ट को सर्विस करने से बच जाते हैं, जो प्रीएम्प्शन को भी अक्षम कर देता है।


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

कार्य कतारों का गलत उपयोग

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

हालाँकि, इस समस्या के लिए कार्य कतारें लगभग हमेशा गलत उत्तर होती हैं क्योंकि वे हमेशा SCHED_OTHER होती हैं। कई हार्डवेयर व्यवधान प्रदर्शन के महत्वपूर्ण पथ में हैं और उन्हें तुरंत चलाया जाना चाहिए। वर्कक्यू के पास इस बात की कोई गारंटी नहीं है कि उन्हें कब चलाया जाएगा। जब भी हमने प्रदर्शन के महत्वपूर्ण पथ में कोई कार्य कतार देखी है, तो यह छिटपुट जंक का एक स्रोत रहा है, डिवाइस की परवाह किए बिना। फ्लैगशिप प्रोसेसर के साथ पिक्सेल पर, हमने देखा कि यदि डिवाइस शेड्यूलर व्यवहार और सिस्टम पर चल रही अन्य चीजों के आधार पर लोड के तहत था, तो एक एकल वर्कक्यू में 7ms तक की देरी हो सकती है।

वर्कक्यू के बजाय, जिन ड्राइवरों को एक अलग थ्रेड के अंदर रुकावट जैसे काम को संभालने की आवश्यकता होती है, उन्हें अपना स्वयं का SCHED_FIFO kthread बनाना चाहिए। Kthread_work फ़ंक्शंस के साथ ऐसा करने में सहायता के लिए, इस पैच को देखें।

फ़्रेमवर्क लॉक विवाद

फ़्रेमवर्क लॉक विवाद जंक या अन्य प्रदर्शन समस्याओं का स्रोत हो सकता है। यह आमतौर पर ActivityManagerService लॉक के कारण होता है लेकिन इसे अन्य लॉक में भी देखा जा सकता है। उदाहरण के लिए, PowerManagerService लॉक स्क्रीन के प्रदर्शन को प्रभावित कर सकता है। यदि आप इसे अपने डिवाइस पर देख रहे हैं, तो इसका कोई अच्छा समाधान नहीं है क्योंकि इसे केवल ढांचे में वास्तु सुधार के माध्यम से ही सुधारा जा सकता है। हालाँकि, यदि आप system_server के अंदर चलने वाले कोड को संशोधित कर रहे हैं, तो लंबे समय तक लॉक रखने से बचना महत्वपूर्ण है, विशेष रूप से एक्टिविटीमैनेजर सर्विस लॉक।

बाइंडर लॉक विवाद

ऐतिहासिक रूप से, बाइंडर के पास एक ही वैश्विक लॉक होता है। यदि बाइंडर लेनदेन चलाने वाले थ्रेड को लॉक रखते समय प्रीमेप्ट किया गया था, तो कोई भी अन्य थ्रेड तब तक बाइंडर लेनदेन नहीं कर सकता जब तक कि मूल थ्रेड ने लॉक जारी नहीं कर दिया हो। यह तो बुरा हुआ; बाइंडर विवाद सिस्टम में सब कुछ ब्लॉक कर सकता है, जिसमें डिस्प्ले पर यूआई अपडेट भेजना भी शामिल है (यूआई थ्रेड्स बाइंडर के माध्यम से सर्फेसफ्लिंगर के साथ संचार करते हैं)।

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

एक प्रक्रिया के भीतर एफडी विवाद

यह दुर्लभ है. आपका जंक संभवतः इसके कारण नहीं हुआ है।

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

हम इसे किसी अन्य स्थिति में पुन: पेश करने में सक्षम नहीं थे, लेकिन ट्रेसिंग के दौरान प्रदर्शन समस्याओं के संभावित कारण के रूप में इसे इंगित करना उचित है।

अनावश्यक सीपीयू निष्क्रिय संक्रमण

आईपीसी, विशेष रूप से बहु-प्रक्रिया पाइपलाइनों से निपटते समय, निम्नलिखित रनटाइम व्यवहार में भिन्नताएं देखना आम बात है:

  1. थ्रेड ए सीपीयू 1 पर चलता है।
  2. थ्रेड ए, थ्रेड बी को जगाता है।
  3. थ्रेड बी सीपीयू 2 पर चलना शुरू करता है।
  4. थ्रेड ए तुरंत सो जाता है, जब थ्रेड बी अपना वर्तमान कार्य पूरा कर लेता है तो उसे थ्रेड बी द्वारा जगाया जाता है।

ओवरहेड का एक सामान्य स्रोत चरण 2 और 3 के बीच है। यदि सीपीयू 2 निष्क्रिय है, तो थ्रेड बी चलने से पहले इसे सक्रिय स्थिति में वापस लाया जाना चाहिए। एसओसी पर निर्भर करता है और निष्क्रियता कितनी गहरी है, थ्रेड बी के चलने से पहले यह दसियों माइक्रोसेकंड हो सकता है। यदि आईपीसी के प्रत्येक पक्ष का वास्तविक रनटाइम ओवरहेड के काफी करीब है, तो सीपीयू निष्क्रिय संक्रमणों द्वारा उस पाइपलाइन का समग्र प्रदर्शन काफी कम हो सकता है। एंड्रॉइड के लिए इसे प्रभावित करने का सबसे आम स्थान बाइंडर लेनदेन के आसपास है, और बाइंडर का उपयोग करने वाली कई सेवाएँ ऊपर वर्णित स्थिति की तरह दिखती हैं।

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

दूसरा, सुनिश्चित करें कि आपका सीपीयू संक्रमण समय यथार्थवादी है और सीपीयू गवर्नर इन्हें सही ढंग से ध्यान में रख रहा है। यदि आपका एसओसी आपकी सबसे गहरी निष्क्रिय अवस्था में अंदर-बाहर हो रहा है, तो आप सबसे गहरी निष्क्रिय स्थिति में जाकर बिजली नहीं बचा पाएंगे।

लॉगिंग

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

I/O मुद्दे

I/O ऑपरेशन घबराहट के सामान्य स्रोत हैं। यदि कोई थ्रेड मेमोरी-मैप की गई फ़ाइल तक पहुंचता है और पेज पेज कैश में नहीं है, तो यह ख़राब हो जाता है और पेज को डिस्क से पढ़ता है। यह थ्रेड को ब्लॉक कर देता है (आमतौर पर 10+ एमएस के लिए) और यदि यह यूआई रेंडरिंग के महत्वपूर्ण पथ में होता है, तो इसके परिणामस्वरूप जंक हो सकता है। यहां चर्चा करने के लिए I/O संचालन के बहुत सारे कारण हैं, लेकिन I/O व्यवहार में सुधार करने का प्रयास करते समय निम्नलिखित स्थानों की जांच करें:

  • पिनरसेवा । एंड्रॉइड 7.0 में जोड़ा गया, PinnerService फ्रेमवर्क को पेज कैश में कुछ फ़ाइलों को लॉक करने में सक्षम बनाता है। यह किसी अन्य प्रक्रिया द्वारा उपयोग के लिए मेमोरी को हटा देता है, लेकिन अगर कुछ फ़ाइलें हैं जिन्हें नियमित रूप से उपयोग करने के लिए जाना जाता है, तो उन फ़ाइलों को एमलॉक करना प्रभावी हो सकता है।

    Android 7.0 चलाने वाले Pixel और Nexus 6P डिवाइस पर, हमने चार फ़ाइलें लॉक कीं:
    • /system/framework/arm64/boot-framework.oat
    • /system/framework/oat/arm64/services.odex
    • /system/framework/arm64/boot.oat
    • /system/framework/arm64/boot-core-libart.oat
    ये फ़ाइलें अधिकांश एप्लिकेशन और system_server द्वारा लगातार उपयोग में हैं, इसलिए इन्हें पेज आउट नहीं किया जाना चाहिए। विशेष रूप से, हमने पाया है कि यदि उनमें से कोई भी पेज आउट हो गया है, तो उन्हें वापस पेज में डाल दिया जाएगा और हेवीवेट एप्लिकेशन से स्विच करते समय जंक हो जाएगा।
  • कूटलेखन । I/O समस्याओं का एक अन्य संभावित कारण। हमने पाया कि सीपीयू-आधारित एन्क्रिप्शन या डीएमए के माध्यम से सुलभ हार्डवेयर ब्लॉक का उपयोग करने की तुलना में इनलाइन एन्क्रिप्शन सबसे अच्छा प्रदर्शन प्रदान करता है। सबसे महत्वपूर्ण बात यह है कि इनलाइन एन्क्रिप्शन I/O से जुड़े घबराहट को कम करता है, खासकर जब सीपीयू-आधारित एन्क्रिप्शन की तुलना में। क्योंकि पेज कैश में फ़ेच अक्सर यूआई रेंडरिंग के महत्वपूर्ण पथ में होते हैं, सीपीयू-आधारित एन्क्रिप्शन महत्वपूर्ण पथ में अतिरिक्त सीपीयू लोड पेश करता है, जो केवल I/O फ़ेच की तुलना में अधिक घबराहट जोड़ता है।

    डीएमए-आधारित हार्डवेयर एन्क्रिप्शन इंजन में एक समान समस्या है, क्योंकि कर्नेल को उस कार्य को प्रबंधित करने में चक्र खर्च करना पड़ता है, भले ही अन्य महत्वपूर्ण कार्य चलाने के लिए उपलब्ध हो। हम नए हार्डवेयर बनाने वाले किसी भी SOC विक्रेता को इनलाइन एन्क्रिप्शन के लिए समर्थन शामिल करने की पुरजोर अनुशंसा करते हैं।

आक्रामक छोटे कार्य पैकिंग

कुछ शेड्यूलर अधिक सीपीयू को लंबे समय तक निष्क्रिय रखकर बिजली की खपत को कम करने की कोशिश करने के लिए छोटे कार्यों को एकल सीपीयू कोर पर पैक करने के लिए समर्थन प्रदान करते हैं। हालाँकि यह थ्रूपुट और बिजली की खपत के लिए अच्छा काम करता है, लेकिन यह विलंबता के लिए विनाशकारी हो सकता है। यूआई रेंडरिंग के महत्वपूर्ण पथ में कई छोटे-छोटे थ्रेड हैं जिन्हें छोटा माना जा सकता है; यदि इन थ्रेड्स में देरी हो जाती है क्योंकि वे धीरे-धीरे अन्य सीपीयू में स्थानांतरित हो जाते हैं, तो यह जंक का कारण बनेगा । हम छोटे कार्य पैकिंग को बहुत ही सावधानी से उपयोग करने की सलाह देते हैं।

पेज कैश थ्रैशिंग

पर्याप्त खाली मेमोरी के बिना एक उपकरण लंबे समय तक चलने वाले ऑपरेशन, जैसे कि एक नया एप्लिकेशन खोलने, करते समय अचानक बेहद सुस्त हो सकता है। एप्लिकेशन के ट्रेस से पता चल सकता है कि यह किसी विशेष रन के दौरान I/O में लगातार अवरुद्ध है, तब भी जब यह अक्सर I/O में अवरुद्ध नहीं होता है। यह आमतौर पर पेज कैश थ्रैशिंग का संकेत है, खासकर कम मेमोरी वाले डिवाइस पर।

इसे पहचानने का एक तरीका पेजकैश टैग का उपयोग करके एक सिस्ट्रेस लेना है और उस ट्रेस को system/extras/pagecache/pagecache.py पर स्क्रिप्ट में फ़ीड करना है। pagecache.py फ़ाइलों को पेज कैश में मैप करने के व्यक्तिगत अनुरोधों को कुल प्रति-फ़ाइल आँकड़ों में अनुवादित करता है। यदि आप पाते हैं कि किसी फ़ाइल के डिस्क पर उस फ़ाइल के कुल आकार से अधिक बाइट्स पढ़े गए हैं, तो आप निश्चित रूप से पेज कैश थ्रैशिंग का शिकार हो रहे हैं।

इसका मतलब यह है कि आपके कार्यभार के लिए आवश्यक कार्य सेट (आमतौर पर एक एप्लिकेशन प्लस सिस्टम_सर्वर) आपके डिवाइस पर पेज कैश के लिए उपलब्ध मेमोरी की मात्रा से अधिक है। परिणामस्वरूप, जैसे ही वर्कलोड के एक हिस्से को पेज कैश में आवश्यक डेटा मिलता है, निकट भविष्य में उपयोग किया जाने वाला दूसरा हिस्सा बेदखल कर दिया जाएगा और उसे फिर से लाना होगा, जिससे लोड होने तक समस्या फिर से होगी पूरा हो गया। जब किसी डिवाइस पर पर्याप्त मेमोरी उपलब्ध नहीं होती है तो यह प्रदर्शन समस्याओं का मूल कारण है।

पेज कैश थ्रैशिंग को ठीक करने का कोई अचूक तरीका नहीं है, लेकिन किसी दिए गए डिवाइस पर इसे सुधारने का प्रयास करने के कुछ तरीके हैं।

  • लगातार प्रक्रियाओं में कम मेमोरी का उपयोग करें। लगातार प्रक्रियाओं द्वारा जितनी कम मेमोरी का उपयोग किया जाता है, अनुप्रयोगों और पेज कैश के लिए उतनी ही अधिक मेमोरी उपलब्ध होती है।
  • यह सुनिश्चित करने के लिए कि आप अनावश्यक रूप से ओएस से मेमोरी नहीं हटा रहे हैं, अपने डिवाइस के लिए मौजूद कार्वआउट का ऑडिट करें। हमने ऐसी स्थितियाँ देखी हैं जहाँ डिबगिंग के लिए उपयोग किए गए कार्वआउट गलती से शिपिंग कर्नेल कॉन्फ़िगरेशन में छोड़ दिए गए थे, जिससे दसियों मेगाबाइट मेमोरी की खपत हुई थी। यह पेज कैश थ्रैशिंग को हिट करने और न करने के बीच अंतर पैदा कर सकता है, खासकर कम मेमोरी वाले डिवाइस पर।
  • यदि आप महत्वपूर्ण फ़ाइलों पर system_server में पेज कैश थ्रैशिंग देख रहे हैं, तो उन फ़ाइलों को पिन करने पर विचार करें। इससे अन्यत्र स्मृति दबाव बढ़ जाएगा, लेकिन यह थ्रैशिंग से बचने के लिए व्यवहार को पर्याप्त रूप से संशोधित कर सकता है।
  • अधिक मेमोरी मुक्त रखने का प्रयास करने के लिए लोमेमोरीकिलर को पुनः ट्यून करें। lowmemorykiller की सीमाएँ पूर्ण मुक्त मेमोरी और पृष्ठ कैश दोनों पर आधारित हैं, इसलिए किसी दिए गए oom_adj स्तर पर प्रक्रियाओं को समाप्त करने की सीमा बढ़ाने से पृष्ठभूमि ऐप की मृत्यु में वृद्धि की कीमत पर बेहतर व्यवहार हो सकता है।
  • ZRAM का उपयोग करने का प्रयास करें. हम Pixel पर ZRAM का उपयोग करते हैं, भले ही Pixel में 4GB है, क्योंकि यह शायद ही कभी उपयोग किए जाने वाले गंदे पृष्ठों में मदद कर सकता है।