इस लेख में बताया गया है कि Android का ऑडियो सिस्टम, प्राथमिकता पलटने की समस्या से कैसे बचता है. साथ ही, इसमें ऐसी तकनीकों के बारे में बताया गया है जिनका इस्तेमाल किया जा सकता है.
ये तकनीकें, ज़्यादा परफ़ॉर्मेंस वाले ऑडियो ऐप्लिकेशन के डेवलपर, ओईएम, और एसओसी उपलब्ध कराने वाली कंपनियों के लिए काम की हो सकती हैं. ये कंपनियां, ऑडियो एचएएल लागू कर रही हैं. कृपया ध्यान दें कि इन तकनीकों को लागू करने से, गड़बड़ियों या अन्य समस्याओं को रोका नहीं जा सकता. खास तौर पर, अगर इनका इस्तेमाल ऑडियो कॉन्टेक्स्ट के बाहर किया जाता है. आपको अलग-अलग नतीजे मिल सकते हैं. इसलिए, आपको खुद ही इसका आकलन और जांच करनी चाहिए.
बैकग्राउंड
Android AudioFlinger ऑडियो सर्वर और AudioTrack/AudioRecord क्लाइंट को फिर से डिज़ाइन किया जा रहा है, ताकि लेटेंसी को कम किया जा सके. इस पर काम Android 4.1 से शुरू हुआ था. इसके बाद, इसे 4.2, 4.3, 4.4, और 5.0 में और बेहतर बनाया गया.
कम समय में वीडियो स्ट्रीम करने के लिए, सिस्टम में कई बदलाव करने पड़े. एक अहम बदलाव यह है कि समय के हिसाब से ज़रूरी थ्रेड को सीपीयू संसाधन असाइन किए जाएं. इसके लिए, शेड्यूल करने की ऐसी नीति का इस्तेमाल किया जाए जिसके बारे में पहले से अनुमान लगाया जा सकता हो. शेड्यूलिंग की सुविधा से, ऑडियो बफ़र के साइज़ और संख्या को कम किया जा सकता है. साथ ही, इससे अंडररन और ओवररन से बचा जा सकता है.
प्रायॉरिटी इनवर्ज़न
प्रायॉरिटी इन्वर्ज़न, रीयल-टाइम सिस्टम की एक क्लासिक समस्या है. इसमें ज़्यादा प्राथमिकता वाले टास्क को अनिश्चित समय के लिए ब्लॉक कर दिया जाता है. ऐसा इसलिए होता है, क्योंकि वह कम प्राथमिकता वाले टास्क के किसी संसाधन को रिलीज़ करने का इंतज़ार कर रहा होता है. जैसे, (शेयर किए गए स्टेट से सुरक्षित) म्यूटेक्स.
ऑडियो सिस्टम में, प्राथमिकता उलटने की समस्या आम तौर पर गड़बड़ी (क्लिक, पॉप, ड्रॉपआउट), सर्कुलर बफ़र का इस्तेमाल करने पर बार-बार ऑडियो या किसी कमांड का जवाब देने में देरी के तौर पर दिखती है.
प्राथमिकता उलटने की समस्या को ठीक करने का एक सामान्य तरीका, ऑडियो बफ़र के साइज़ को बढ़ाना है. हालांकि, इस तरीके से लेटेन्सी बढ़ जाती है. साथ ही, इससे समस्या हल नहीं होती, बल्कि सिर्फ़ छिप जाती है. नीचे दिए गए उदाहरण में, प्राथमिकता पलटने की समस्या को समझने और उससे बचने का तरीका बताया गया है.
Android में ऑडियो लागू करने के दौरान, प्राथमिकता पलटने की समस्या इन जगहों पर सबसे ज़्यादा होती है. इसलिए, आपको इन बातों पर ध्यान देना चाहिए:
- AudioFlinger में सामान्य मिक्सर थ्रेड और फ़ास्ट मिक्सर थ्रेड के बीच
- तेज़ AudioTrack और तेज़ मिक्सर थ्रेड के लिए ऐप्लिकेशन कॉलबैक थ्रेड के बीच (इन दोनों की प्राथमिकताएं ज़्यादा होती हैं, लेकिन इनमें थोड़ा अंतर होता है)
- तेज़ AudioRecord और तेज़ कैप्चर थ्रेड (पिछले वर्शन की तरह) के लिए ऐप्लिकेशन कॉलबैक थ्रेड के बीच
- ऑडियो हार्डवेयर ऐब्स्ट्रैक्शन लेयर (एचएएल) के लागू होने के दौरान, जैसे कि टेलीफ़ोनी या नॉइज़ कैंसलेशन के लिए
- कर्नेल में ऑडियो ड्राइवर के अंदर
- AudioTrack या AudioRecord कॉलबैक थ्रेड और ऐप्लिकेशन की अन्य थ्रेड के बीच (यह हमारे कंट्रोल से बाहर है)
सामान्य समाधान
आम तौर पर, इन समस्याओं को ठीक करने के लिए ये तरीके अपनाए जाते हैं:
- इंटरप्ट बंद करना
- प्रायॉरिटी इनहेरिटेंस म्यूटेक्स
Linux के उपयोगकर्ता स्पेस में इंटरप्ट बंद नहीं किए जा सकते. साथ ही, यह सिमेट्रिक मल्टी-प्रोसेसर (एसएमपी) के लिए काम नहीं करता.
ऑडियो सिस्टम में, प्राथमिकता इनहेरिटेंस वाले futexes (फ़ास्ट यूज़र-स्पेस म्यूटेक्स) का इस्तेमाल नहीं किया जाता. ऐसा इसलिए, क्योंकि ये अपेक्षाकृत हैवीवेट होते हैं. साथ ही, ये भरोसेमंद क्लाइंट पर निर्भर होते हैं.
Android की ओर से इस्तेमाल की जाने वाली तकनीकें
"try lock" और टाइम आउट के साथ लॉक करने की सुविधा वाले एक्सपेरिमेंट शुरू किए गए. ये म्यूटेक्स लॉक ऑपरेशन के नॉन-ब्लॉकिंग और बाउंडेड ब्लॉकिंग वैरिएंट हैं. लॉक और लॉक के साथ टाइम आउट की सुविधा काफ़ी हद तक काम करती है. हालांकि, कुछ मामलों में यह काम नहीं करती. जैसे, अगर क्लाइंट व्यस्त है, तो सर्वर को शेयर की गई स्थिति को ऐक्सेस करने की अनुमति नहीं दी जाती. इसके अलावा, अगर टाइम आउट होने वाले लॉक की लंबी सीरीज़ है, तो कुल टाइम आउट बहुत ज़्यादा हो सकता है.
हम ऐटॉमिक ऑपरेशंस का भी इस्तेमाल करते हैं. जैसे:
- ज़्यादा
- बिटवाइज़ "or"
- बिटवाइज़ "and"
इन सभी से पिछली वैल्यू मिलती है. साथ ही, इनमें ज़रूरी एसएमपी बैरियर शामिल होते हैं. इसका नुकसान यह है कि इसमें कई बार फिर से कोशिश करनी पड़ सकती है. हमने पाया है कि फिर से कोशिश करने से कोई समस्या नहीं होती.
ध्यान दें: एटॉमिक ऑपरेशन और मेमोरी बैरियर के साथ उनके इंटरैक्शन के बारे में, लोगों को अक्सर गलत जानकारी होती है. साथ ही, वे इनका गलत तरीके से इस्तेमाल करते हैं. हमने यहां इन तरीकों को शामिल किया है, ताकि आपको पूरी जानकारी मिल सके. हालांकि, हमारा सुझाव है कि ज़्यादा जानकारी के लिए, Android के लिए एसएमपी प्राइमर लेख भी पढ़ें.
हमारे पास अब भी ऊपर दिए गए ज़्यादातर टूल हैं और हम उनका इस्तेमाल करते हैं. हमने हाल ही में ये तकनीकें जोड़ी हैं:
- डेटा के लिए, नॉन-ब्लॉकिंग सिंगल-रीडर सिंगल-राइटर FIFO कतारों का इस्तेमाल करें.
- ज़्यादा और कम प्राथमिकता वाले मॉड्यूल के बीच, स्थिति को शेयर करने के बजाय कॉपी करने की कोशिश करें.
- जब स्थिति को शेयर करने की ज़रूरत हो, तब स्थिति को ज़्यादा से ज़्यादा साइज़ शब्द तक सीमित करें. इसे एक बस ऑपरेशन में, बिना फिर से कोशिश किए ऐटम के तौर पर ऐक्सेस किया जा सकता है.
- एक से ज़्यादा शब्दों वाली जटिल स्थिति के लिए, स्टेट क्यू का इस्तेमाल करें. स्टेट क्यू, एक नॉन-ब्लॉकिंग सिंगल-रीडर सिंगल-राइटर फ़र्स्ट इन फ़र्स्ट आउट (FIFO) क्यू होता है. इसका इस्तेमाल डेटा के बजाय स्टेट के लिए किया जाता है. हालांकि, राइटर आस-पास के पुश को एक ही पुश में बदल देता है.
- एसएमपी के सही तरीके से काम करने के लिए, मेमोरी बैरियर पर ध्यान दें.
- भरोसा करें, लेकिन पुष्टि करें. प्रोसेस के बीच स्टेट शेयर करते समय, यह न मान लें कि स्टेट सही तरीके से बनी है. उदाहरण के लिए, यह जांच करें कि इंडेक्स तय सीमा में हैं या नहीं. एक ही प्रोसेस में थ्रेड के बीच, पुष्टि करने की ज़रूरत नहीं होती. साथ ही, एक-दूसरे पर भरोसा करने वाली प्रोसेस (जिनका यूआईडी आम तौर पर एक ही होता है) के बीच भी पुष्टि करने की ज़रूरत नहीं होती. यह शेयर किए गए डेटा के लिए भी ज़रूरी नहीं है. जैसे, पीसीएम ऑडियो, जिसमें गड़बड़ी का कोई असर नहीं पड़ता.
नॉन-ब्लॉकिंग एल्गोरिदम
नॉन-ब्लॉकिंग एल्गोरिदम पर हाल ही में कई स्टडी की गई हैं. हालांकि, सिंगल-रीडर सिंगल-राइटर FIFO कतारों को छोड़कर, हमें ये जटिल और गड़बड़ी वाली लगीं.
Android 4.2 से, हमारी नॉन-ब्लॉकिंग, सिंगल-रीडर/राइटर क्लास इन जगहों पर मिल सकती हैं:
- frameworks/av/include/media/nbaio/
- frameworks/av/media/libnbaio/
- frameworks/av/services/audioflinger/StateQueue*
इन्हें खास तौर पर AudioFlinger के लिए डिज़ाइन किया गया था. ये सामान्य मकसद के लिए नहीं हैं. नॉन-ब्लॉकिंग एल्गोरिदम को डीबग करना मुश्किल होता है. इस कोड को मॉडल के तौर पर देखा जा सकता है. हालांकि, ध्यान रखें कि इसमें कुछ गड़बड़ियां हो सकती हैं. साथ ही, यह भी ज़रूरी नहीं है कि ये क्लास अन्य कामों के लिए सही हों.
डेवलपर को OpenSL ES ऐप्लिकेशन के कुछ सैंपल कोड अपडेट करने चाहिए, ताकि वे नॉन-ब्लॉकिंग एल्गोरिदम का इस्तेमाल कर सकें या किसी नॉन-Android ओपन सोर्स लाइब्रेरी का रेफ़रंस दे सकें.
हमने नॉन-ब्लॉकिंग FIFO को लागू करने का एक उदाहरण पब्लिश किया है. इसे खास तौर पर ऐप्लिकेशन कोड के लिए डिज़ाइन किया गया है. प्लैटफ़ॉर्म की सोर्स डायरेक्ट्री frameworks/av/audio_utils
में मौजूद इन फ़ाइलों को देखें:
टूल
हमारी जानकारी के मुताबिक, प्राथमिकता पलटने की समस्या का पता लगाने के लिए कोई भी ऑटोमैटिक टूल उपलब्ध नहीं है. खास तौर पर, समस्या होने से पहले इसका पता लगाने के लिए. रिसर्च के लिए इस्तेमाल किए जाने वाले कुछ स्टैटिक कोड विश्लेषण टूल, पूरे कोडबेस को ऐक्सेस करने पर प्राथमिकता के उलट होने की समस्या का पता लगा सकते हैं. अगर किसी ऐप्लिकेशन में उपयोगकर्ता का कोड शामिल है (जैसा कि यहां ऐप्लिकेशन के लिए है) या बड़ा कोडबेस है (जैसा कि Linux कर्नल और डिवाइस ड्राइवर के लिए है), तो स्टैटिक विश्लेषण करना मुश्किल हो सकता है. सबसे ज़रूरी यह है कि कोड को ध्यान से पढ़ा जाए. साथ ही, पूरे सिस्टम और इंटरैक्शन को अच्छी तरह से समझा जाए. systrace और ps -t -p
जैसे टूल, प्राथमिकता पलटने की समस्या होने के बाद उसे देखने के लिए काम के होते हैं. हालांकि, ये आपको इस बारे में पहले से नहीं बताते.
आखिरी बात
इस पूरी चर्चा के बाद, म्यूटेक्स से न डरें. सामान्य इस्तेमाल के लिए, म्यूटेक्स आपके काम आ सकते हैं. हालांकि, इनका सही तरीके से इस्तेमाल और लागू किया जाना ज़रूरी है. साथ ही, इनका इस्तेमाल ऐसे मामलों में किया जाना चाहिए जिनमें समयसीमा तय नहीं होती. हालांकि, ज़्यादा और कम प्राथमिकता वाले टास्क के बीच और समय के हिसाब से ज़रूरी सिस्टम में, म्यूटेक्स से ज़्यादा समस्याएं हो सकती हैं.