অগ্রাধিকারের ইনভার্সন এড়িয়ে চলুন

এই নিবন্ধে ব্যাখ্যা করা হয়েছে যে Android-এর অডিও সিস্টেম কীভাবে অগ্রাধিকার ইনভার্সন এড়ানোর চেষ্টা করে এবং আপনিও ব্যবহার করতে পারবেন এমন টেকনিক হাইলাইট করে।

এইসব টেকনিক, হাই-পারফর্ম্যান্স অডিও অ্যাপ, OEM ও SoC প্রদানকারী ডেভেলপারদের জন্য উপযোগী হতে পারে, যারা অডিও HAL প্রয়োগ করছেন। মনে রাখবেন, এই কৌশলগুলি প্রয়োগ করলে গ্লিচ বা অন্যান্য সমস্যা যে হবেই না এমন গ্যারান্টি দেওয়া যায় না, বিশেষ করে যদি অডিও কনটেক্সটের বাইরে ব্যবহার করা হয়। আপনার ফলাফল আলাদা হতে পারে এবং আপনাকে নিজের মূল্যায়ন ও পরীক্ষা করতে হবে।

ব্যাকগ্রাউন্ড

লেটেন্সি কমানোর জন্য Android AudioFlinger অডিও সার্ভার এবং AudioTrack/AudioRecord ক্লায়েন্ট ইমপ্লিমেন্টেশন নতুন করে ডিজাইন করা হচ্ছে। এই কাজ Android 4.1-এ শুরু হয়েছিল এবং 4.2, 4.3, 4.4 ও 5.0 ভার্সনে আরও উন্নতি করা হয়েছে।

এই কম লেটেন্সি পেতে, পুরো সিস্টেম জুড়ে অনেক পরিবর্তন করতে হয়েছে। একটি গুরুত্বপূর্ণ পরিবর্তন হল, আরও বেশি অনুমানযোগ্য শিডিউলিং নীতি সহ সময়-সংবেদনশীল থ্রেডে CPU রিসোর্স অ্যাসাইন করা। নির্ভরযোগ্য শিডিউলিং অডিও বাফার সাইজ এবং গণনা কমানোর অনুমতি দেয়, আন্ডাররান এবং ওভাররান এড়ানো যায়।

অগ্রাধিকারের ইনভার্সন

অগ্রাধিকার ইনভার্সন হল রিয়েল-টাইম সিস্টেমের একটি ক্লাসিক ব্যর্থতা মোড, যেখানে একটি উচ্চ-অগ্রাধিকার টাস্ক একটি সীমাহীন সময়ের জন্য ব্লক করা হয় একটি নিম্ন-অগ্রাধিকার টাস্কের জন্য অপেক্ষা করে একটি রিসোর্স রিলিজ করার জন্য যেমন (শেয়ার করা স্টেট দ্বারা সুরক্ষিত) একটি মিউটেক্স।

অডিও সিস্টেমে, প্রায়োরিটি ইনভার্সন সাধারণত গ্লিচ (ক্লিক, পপ, ড্রপআউট), রিপিট হওয়া অডিও হিসেবে প্রকাশ পায়, যখন সার্কুলার বাফার ব্যবহার করা হয় অথবা কোনও কমান্ডের উত্তর দিতে দেরি হয়।

প্রায়োরিটি ইনভার্সনের জন্য একটি সাধারণ সমাধান হল অডিও বাফারের সাইজ বাড়ানো। তবে, এই পদ্ধতিতে লেটেন্সি বেড়ে যায় এবং সমস্যা সমাধানের পরিবর্তে তা কেবল লুকিয়ে রাখা হয়। নিচে দেখানো priority ইনভার্সন বোঝা ও প্রতিরোধ করা ভালো।

Android অডিও ইমপ্লিমেন্টেশনে, অগ্রাধিকারের ইনভার্সন এইসব জায়গায় সবচেয়ে বেশি ঘটে থাকে। তাই আপনার এখানে মনোযোগ দেওয়া উচিত:

  • AudioFlinger-এ সাধারণ মিক্সার থ্রেড ও ফাস্ট মিক্সার থ্রেডের মধ্যে
  • ফাস্ট AudioTrack-এর জন্য অ্যাপ্লিকেশন কলব্যাক থ্রেড এবং ফাস্ট মিক্সার থ্রেডের মধ্যে (উভয়েরই অগ্রাধিকার বেশি, তবে অগ্রাধিকারের মধ্যে সামান্য পার্থক্য আছে)
  • দ্রুত AudioRecord-এর জন্য অ্যাপ্লিকেশন কলব্যাক থ্রেড এবং দ্রুত ক্যাপচার থ্রেডের (আগেরটির মতো) মধ্যে
  • অডিও হার্ডওয়্যার অ্যাবস্ট্রাকশন লেয়ার (HAL) ইমপ্লিমেন্টেশনের মধ্যে, যেমন টেলিফোনি বা ইকো বাতিল করার জন্য
  • কার্নেলের অডিও ড্রাইভারের মধ্যে
  • AudioTrack বা AudioRecord কলব্যাক থ্রেড এবং অন্যান্য অ্যাপ থ্রেডের মধ্যে (এটি আমাদের নিয়ন্ত্রণে নেই)

সাধারণ সমাধান

সাধারণত এইসব সমাধান করা হয়:

  • ইন্টারাপ্ট বন্ধ করা হচ্ছে
  • অগ্রাধিকার ইনহেরিটেন্স মিউটেক্স

Linux ইউজার স্পেসে ইন্টারাপ্ট বন্ধ করা সম্ভব নয় এবং সিমেট্রিক মাল্টি-প্রসেসরের (SMP) ক্ষেত্রে কাজ করে না।

অগ্রাধিকার ইনহেরিটেন্স futexes (ফাস্ট ইউজার-স্পেস মিউটেক্স) অডিও সিস্টেমে ব্যবহার করা হয় না কারণ সেগুলি তুলনামূলকভাবে ভারী, এবং সেগুলি বিশ্বস্ত ক্লায়েন্টের উপর নির্ভর করে।

Android-এর ব্যবহার করা টেকনিক

"try lock" দিয়ে শুরু হওয়া পরীক্ষা এবং টাইম-আউট সহ লক করা। এগুলি হল মিউটেক্স লক অপারেশনের নন-ব্লকিং এবং বাউন্ডেড ব্লকিং ভেরিয়েন্ট। টাইম-আউট সহ লক ও আনলক করার চেষ্টা মোটামুটি ভাল কাজ করেছে, কিন্তু কয়েকটি অস্পষ্ট ব্যর্থতা মোডের জন্য সংবেদনশীল ছিল: ক্লায়েন্ট ব্যস্ত থাকলে শেয়ার করা স্টেট অ্যাক্সেস করতে পারবে এমন গ্যারান্টি সার্ভারের কাছে ছিল না এবং যদি সম্পর্কিত নয় এমন লকগুলির একটি দীর্ঘ ক্রম থাকে যেগুলি সব টাইম-আউট হয়ে গেছে, তাহলে ক্রমবর্ধমান টাইম-আউট খুব দীর্ঘ হতে পারে।

এছাড়াও, আমরা অ্যাটমিক অপারেশন ব্যবহার করি, যেমন:

  • ইনক্রিমেন্ট
  • বিটওয়াইজ "or"
  • বিটওয়াইজ "AND"

এইসব ফাংশন আগের ভ্যালু ফিরিয়ে দেয় এবং প্রয়োজনীয় SMP ব্যারিয়ার অন্তর্ভুক্ত করে। এর অসুবিধা হল, এটিতে সীমাহীন রিট্রাইয়ের প্রয়োজন হতে পারে। বাস্তবে, আমরা দেখেছি যে আবার চেষ্টা করা কোনও সমস্যা নয়।

মনে রাখবেন: অ্যাটমিক অপারেশন এবং মেমরি ব্যারিয়ারের সাথে সেগুলির ইন্টার‍্যাকশন খুবই জটিল এবং প্রায়শই ভুলভাবে বোঝা ও ব্যবহার করা হয়। আমরা এখানে এই পদ্ধতিগুলি সম্পূর্ণতার জন্য অন্তর্ভুক্ত করেছি, তবে আরও তথ্যের জন্য Android-এর জন্য SMP প্রাইমার নিবন্ধটিও পড়ার জন্য সাজেস্ট করি।

আমরা এখনও উপরের বেশিরভাগ টুল ব্যবহার করি এবং সম্প্রতি এইসব কৌশল যোগ করেছি:

  • ডেটার জন্য নন-ব্লকিং সিঙ্গেল-রিডার সিঙ্গেল-রাইটার FIFO কিউ ব্যবহার করুন।
  • হাই- এবং লো-প্রয়োরিটি মডিউলের মধ্যে স্টেট শেয়ার করার পরিবর্তে স্টেট কপি করার চেষ্টা করুন।
  • স্টেট শেয়ার করার প্রয়োজন হলে, স্টেটকে সর্বাধিক-সাইজের শব্দে সীমিত রাখুন যা রিট্রাই না করেই এক-বাস অপারেশনে অ্যাটমিক অ্যাক্সেস করা যায়।
  • একাধিক শব্দ নিয়ে গঠিত জটিল স্টেট থাকলে, স্টেট কিউ ব্যবহার করুন। স্টেট কোয়েরি হল মূলত একটি নন-ব্লকিং সিঙ্গেল-রিডার সিঙ্গেল-রাইটার FIFO কোয়েরি যা ডেটার পরিবর্তে স্টেটের জন্য ব্যবহার করা হয়, তবে রাইটার সংলগ্ন পুশগুলিকে একটি পুশে একত্রিত করে।
  • SMP-এর সঠিকতার জন্য মেমরি ব্যারিয়ার -এর দিকে মনোযোগ দিন।
  • বিশ্বাস করুন, তবে যাচাই করে নিন। প্রসেসের মধ্যে স্টেট শেয়ার করার সময়, স্টেটটি যে ভালভাবে ফর্ম করা হয়েছে তা ধরে নেবেন না। যেমন, ইন্ডেক্স বাউন্ডের মধ্যে আছে কিনা তা চেক করুন। একই প্রসেসের থ্রেডগুলির মধ্যে, পারস্পরিক বিশ্বাসযোগ্য প্রসেসের মধ্যে (যেগুলির সাধারণত একই UID থাকে) এই যাচাইকরণের প্রয়োজন হয় না। এছাড়াও, শেয়ার করা ডেটা যেমন PCM অডিওর ক্ষেত্রে এটি অপ্রয়োজনীয়, যেখানে ডেটা নষ্ট হয়ে গেলেও কোনও ক্ষতি হয় না।

নন-ব্লকিং অ্যালগরিদম

নন-ব্লকিং অ্যালগরিদম সাম্প্রতিক অনেক গবেষণার বিষয়। তবে, সিঙ্গেল-রিডার সিঙ্গেল-রাইটার 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 এর মতো টুল, অগ্রাধিকারের ইনভার্সন হওয়ার পরে তা দেখতে কাজে লাগে, কিন্তু আগে থেকে তা বলে না।

শেষ কথা

এত আলোচনার পরে, মিউটেক্স নিয়ে ভয় পাওয়ার কিছু নেই। সাধারণ ব্যবহারের ক্ষেত্রে মিউটেক্স আপনার বন্ধু, যদি সাধারণ নন-টাইম-ক্রিটিকাল ব্যবহারের ক্ষেত্রে এটি সঠিকভাবে ব্যবহার ও প্রয়োগ করা হয়। কিন্তু বেশি ও কম অগ্রাধিকারযুক্ত টাস্কের মধ্যে এবং সময়-সংবেদনশীল সিস্টেমে মিউটেক্সের কারণে সমস্যা হওয়ার সম্ভাবনা বেশি থাকে।