প্রোফাইল জিপিইউ রেন্ডারিং টুলটি নির্দেশ করে যে, রেন্ডারিং পাইপলাইনের প্রতিটি ধাপ পূর্ববর্তী ফ্রেমটি রেন্ডার করতে আপেক্ষিকভাবে কত সময় নেয়। এই তথ্য আপনাকে পাইপলাইনের প্রতিবন্ধকতাগুলো শনাক্ত করতে সাহায্য করতে পারে, যাতে আপনি আপনার অ্যাপের রেন্ডারিং পারফরম্যান্স উন্নত করার জন্য অপ্টিমাইজ করতে পারেন।
এই পৃষ্ঠাটিতে প্রতিটি পাইপলাইন পর্যায়ে কী ঘটে তা সংক্ষেপে ব্যাখ্যা করা হয়েছে এবং যে সমস্যাগুলো প্রতিবন্ধকতা সৃষ্টি করতে পারে, সেগুলো নিয়ে আলোচনা করা হয়েছে। এই পৃষ্ঠাটি পড়ার আগে, ‘প্রোফাইল জিপিইউ রেন্ডারিং স্পিড’ -এ উপস্থাপিত তথ্যের সাথে আপনার পরিচিত থাকা উচিত। এছাড়াও, সমস্ত পর্যায়গুলো কীভাবে একে অপরের সাথে কাজ করে তা বোঝার জন্য, রেন্ডারিং পাইপলাইন কীভাবে কাজ করে তা পর্যালোচনা করা সহায়ক হতে পারে।
চাক্ষুষ উপস্থাপনা
প্রোফাইল জিপিইউ রেন্ডারিং টুলটি বিভিন্ন পর্যায় এবং তাদের আপেক্ষিক সময়কে একটি গ্রাফের আকারে প্রদর্শন করে: যা একটি রঙ-কোডযুক্ত হিস্টোগ্রাম। চিত্র ১-এ এই ধরনের একটি প্রদর্শনের উদাহরণ দেখানো হয়েছে।

প্রোফাইল জিপিইউ রেন্ডারিং গ্রাফে প্রদর্শিত প্রতিটি উল্লম্ব বারের প্রতিটি অংশ পাইপলাইনের একটি পর্যায়কে প্রতিনিধিত্ব করে এবং বার গ্রাফে একটি নির্দিষ্ট রঙ ব্যবহার করে তা হাইলাইট করা হয়। চিত্র ২-এ প্রদর্শিত প্রতিটি রঙের অর্থের একটি চাবি দেখানো হয়েছে।

একবার আপনি প্রতিটি রঙের তাৎপর্য বুঝে গেলে, আপনার অ্যাপের রেন্ডারিং পারফরম্যান্স উন্নত করার জন্য এর নির্দিষ্ট দিকগুলোকে লক্ষ্য করতে পারবেন।
পর্যায় এবং তাদের অর্থ
এই অংশে প্রতিটি পর্যায়ে কী ঘটে এবং কোন কোন প্রতিবন্ধকতার কারণের দিকে নজর রাখতে হবে, তা ব্যাখ্যা করা হয়েছে।
ইনপুট হ্যান্ডলিং
পাইপলাইনের ইনপুট হ্যান্ডলিং পর্যায়টি পরিমাপ করে যে, অ্যাপটি ইনপুট ইভেন্টগুলো পরিচালনা করতে কতক্ষণ সময় ব্যয় করেছে। এই মেট্রিকটি নির্দেশ করে যে, ইনপুট ইভেন্ট কলব্যাকের ফলে কল করা কোড কার্যকর করতে অ্যাপটি কতক্ষণ সময় নিয়েছে।
যখন এই অংশটি বড়
এই ক্ষেত্রে উচ্চ মান সাধারণত ইনপুট-হ্যান্ডলার ইভেন্ট কলব্যাকের ভিতরে অতিরিক্ত বা খুব জটিল কাজ হওয়ার ফলস্বরূপ হয়ে থাকে। যেহেতু এই কলব্যাকগুলি সর্বদা প্রধান থ্রেডে ঘটে, তাই এই সমস্যার সমাধান সরাসরি কাজটি অপ্টিমাইজ করা বা কাজটি অন্য কোনো থ্রেডে স্থানান্তর করার উপর দৃষ্টি নিবদ্ধ করে।
একটি LazyColumn বা LazyRow মধ্যে স্ক্রোলিংও এই পর্যায়ে দেখা যেতে পারে। একবার ব্যবহারকারীর স্পর্শ স্ক্রোল হিসাবে গণ্য হলে, লেজি লিস্টটি ডায়নামিকভাবে আইটেমগুলি তৈরি ও বিন্যাস করার জন্য টাচ ইভেন্টগুলি গ্রহণ করে। যদি আপনার অ্যাপ স্ক্রোল পজিশন পরিবর্তনের প্রতিক্রিয়া হিসাবে কাস্টম কাজ সম্পাদন করে, তবে ফ্রেম ড্রপ এড়াতে এই অপারেশনটিকে যতটা সম্ভব দ্রুত করা গুরুত্বপূর্ণ। Android Studio-এর CPU Profiler বা Perfetto-এর মতো প্রোফাইলিং টুলগুলি আপনাকে আরও তদন্ত করতে সাহায্য করতে পারে। আরও তথ্যের জন্য সিস্টেম ট্রেসিং-এর ওভারভিউ দেখুন।
অ্যানিমেশন
অ্যানিমেশন পর্যায়টি আপনাকে দেখায় যে সেই ফ্রেমে চলমান সমস্ত অ্যানিমেশন স্টেট মূল্যায়ন করতে কতক্ষণ সময় লেগেছে। Compose-এর কিছু সাধারণ অ্যানিমেশন API হলো animate*AsState , Transition , এবং Animatable । এছাড়াও, স্ন্যাপশট স্টেটের পরিবর্তনগুলি প্রসেস করতে এবং কম্পোজিশন আপডেট করতে এই পর্যায়ে Recomposer চলে। এর মানে হলো, রিকম্পোজিশনের অতিরিক্ত কাজ প্রায়শই সরাসরি অ্যানিমেশন পর্যায়েই প্রকাশ পায়।
Jetpack Compose UI-এর ক্ষেত্রে, সিস্টেম ইভেন্টের পাশাপাশি বিস্তারিত কম্পোজিশন ট্রেস দেখতে Compose Runtime Tracing লাইব্রেরিটি অন্তর্ভুক্ত করুন।
যখন এই অংশটি বড়
এই এলাকার উচ্চ মান সাধারণত অ্যানিমেশন দ্বারা চালিত অবস্থার পরিবর্তনের কারণে সম্পাদিত কাজের ফল। উদাহরণস্বরূপ, একটি ফ্লিং অ্যানিমেশন, যা আপনার LazyColumn বা LazyRow স্ক্রল করে, নতুন তালিকা আইটেমগুলির দ্রুত গঠন, পরিমাপ এবং বরাদ্দের কারণ হয়।
পরিমাপ
স্ক্রিনে আপনার কম্পোজেবলগুলো আঁকতে, অ্যান্ড্রয়েড আপনার UI ট্রি-এর লেআউট নোডগুলোতে তিনটি পর্যায় সম্পাদন করে।
প্রথমে, সিস্টেমটি লেআউট নোডগুলো পরিমাপ করে। প্রতিটি কম্পোজেবলের নির্দিষ্ট সীমাবদ্ধতা এবং মডিফায়ার থাকে, যা স্ক্রিনে থাকা অবজেক্টটির আকারের সীমা নির্ধারণ করে। কিছু কম্পোজেবলের একটি নির্দিষ্ট, স্থির আকার থাকতে পারে; অন্যগুলোর আকার প্যারেন্ট লেআউট কন্টেইনার থেকে আসা সীমাবদ্ধতার সাথে খাপ খাইয়ে নেয়।
দ্বিতীয়ত, সিস্টেমটি লেআউট নোডগুলো স্থাপন করে। পরিমাপ পর্বে Compose যখন চাইল্ড নোডগুলোর আকার গণনা করে ফেলে, তখন এটি স্থাপন পর্বে এগিয়ে যেতে পারে, যেখানে এটি স্ক্রিনে লেআউট নোডগুলোর আকার ও অবস্থান নির্ধারণ করে।
সিস্টেমটি দক্ষতার জন্য সর্বদা এই এক-ধাপের লেআউটটি সম্পাদন করে। যখন একটি কম্পোজেবল লেআউট বাতিল হয়ে যায়, তখন কম্পোজ সেই নির্দিষ্ট নোডটিকে পরিমাপ করে এবং শুধুমাত্র তখনই লেআউটের আপডেটগুলি তার প্যারেন্ট স্তর পর্যন্ত পাঠায়, যদি চাইল্ড নোডটির আকার বা সীমাবদ্ধতা পরিবর্তিত হয়।
যখন এই অংশটি বড়
এই ক্ষেত্রে একটি বড় অংশ নির্দেশ করে যে অ্যাপটি লেআউট পর্যায়ে খুব বেশি সময় ব্যয় করছে, যার মধ্যে লেআউট নোডগুলির অবস্থান নির্ধারণ এবং আকার নির্ণয় করা অন্তর্ভুক্ত। এই অপারেশনগুলির মধ্যে কম্পোজেবলগুলির জন্য পরিমাপ এবং প্লেসমেন্ট মডিফায়ারগুলি কার্যকর করা অন্তর্ভুক্ত, যা লেআউট ট্রি অতিরিক্ত জটিল হলে ফ্রেম প্রস্তুতিতে বিলম্ব ঘটাতে পারে। এই ক্ষেত্রে, পারফরম্যান্সের উন্নতি করতে আপনার কম্পোজ অ্যাপের বেঞ্চমার্কিং করা এবং পারফরম্যান্সের সর্বোত্তম অনুশীলনগুলি অনুসরণ করা প্রয়োজন।
লেআউট পাসগুলো পরীক্ষা করতে এবং প্রতিবন্ধকতা শনাক্ত করতে অ্যান্ড্রয়েড স্টুডিও-এর সিপিইউ প্রোফাইলার অথবা পারফেটটো ব্যবহার করুন। আরও তথ্যের জন্য সিস্টেম ট্রেসিং-এর ওভারভিউ দেখুন।
ড্র
ড্র স্টেজটি ব্যাকগ্রাউন্ড, আকৃতি বা টেক্সট আঁকার মতো রেন্ডারিং অপারেশনগুলোকে নেটিভ ড্রয়িং কমান্ডের একটি অনুক্রমে রূপান্তরিত করে। সিস্টেম এই কমান্ডগুলোকে GPU-তে কার্যকর করার জন্য একটি ডিসপ্লে লিস্টে ধারণ করে।
এই ফ্রেমে স্ক্রিনে আপডেট করার প্রয়োজন এমন সমস্ত লেআউট নোডের জন্য, ডিসপ্লে লিস্টে কমান্ডগুলো ক্যাপচার করতে কত সময় লাগে তা ড্র বার রেকর্ড করে। এই পরিমাপ করা সময়টি ড্র মডিফায়ার বা ক্যানভাস কম্পোজেবলের ভিতরে আপনার থাকা যেকোনো কাস্টম ড্রয়িং লজিকের ক্ষেত্রেও প্রযোজ্য।
যখন এই অংশটি বড়
সহজ ভাষায় বলতে গেলে, এই মেট্রিকটি প্রতিটি ইনভ্যালিডেটেড লেআউট নোডের জন্য সমস্ত ড্রয়িং কমান্ড চালাতে কতক্ষণ সময় লেগেছে তা দেখায়। এই পরিমাপের মধ্যে চাইল্ড নোড এবং ভেক্টর ড্রয়েবলগুলিতে এই কমান্ডগুলি প্রেরণ করতে ব্যয়িত সময়ও অন্তর্ভুক্ত থাকে। এই কারণে, যখন আপনি এই বারটির ঊর্ধ্বগতি দেখতে পান, তার কারণ হতে পারে যে অনেক কম্পোজেবল হঠাৎ করে ইনভ্যালিডেটেড হয়ে গেছে। ইনভ্যালিডেশনের ফলে ড্রয়িং কমান্ডগুলি পুনরায় চালানো এবং লেআউট নোডগুলির ডিসপ্লে লিস্ট পুনরায় তৈরি করা আবশ্যক হয়ে পড়ে। বিকল্পভাবে, দীর্ঘ সময় লাগার কারণ হতে পারে কিছু কাস্টম কম্পোজেবল বা ক্যানভাস, যেগুলির DrawScope ইমপ্লিমেন্টেশনে অত্যন্ত জটিল লজিক রয়েছে।
এছাড়াও, Compose প্রায়শই তার অভ্যন্তরীণ মেজার এবং লেআউট পাসগুলো এমন একটি পর্যায়ে পরিচালনা করে, যাকে প্ল্যাটফর্ম 'ড্র' পর্যায় বলে মনে করে। ফলস্বরূপ, শুধুমাত্র ড্রয়িং কমান্ডের কারণে নয়, বরং ব্যয়বহুল বা অতিরিক্ত অভ্যন্তরীণ মেজার/লেআউট অপারেশনের কারণেও ড্র বার উঁচু হয়ে যেতে পারে। সন্দেহ হলে, এই অতিরিক্ত চাপ ড্রয়িং রুটিন থেকে আসছে নাকি Compose-এর মেজার এবং লেআউট পাস থেকে আসছে, তা দেখার জন্য একটি Perfetto ট্রেস ক্যাপচার করুন।
আপলোড
আপলোড মেট্রিকটি বর্তমান ফ্রেমে সিপিইউ মেমরি থেকে জিপিইউ মেমরিতে বিটম্যাপ অবজেক্ট স্থানান্তর করতে যে সময় লাগে, তা নির্দেশ করে।
সিপিইউ এবং জিপিইউ দুটি ভিন্ন প্রসেসর হওয়ায়, প্রসেসিংয়ের জন্য এদের আলাদা র্যাম এলাকা থাকে। আপনি যখন অ্যান্ড্রয়েডে একটি বিটম্যাপ আঁকেন, তখন জিপিইউ স্ক্রিনে সেটি রেন্ডার করার আগে সিস্টেম বিটম্যাপটিকে জিপিইউ মেমরিতে স্থানান্তর করে। এরপর, জিপিইউ বিটম্যাপটিকে ক্যাশে করে রাখে, যাতে টেক্সচারটি জিপিইউ টেক্সচার ক্যাশে থেকে মুছে না যাওয়া পর্যন্ত সিস্টেমকে আর ডেটা স্থানান্তর করতে না হয়।
দ্রষ্টব্য: ললিপপ ডিভাইসগুলোতে এই পর্যায়টি বেগুনি রঙের।
যখন এই অংশটি বড়
একটি ফ্রেম আঁকার জন্য ব্যবহৃত হওয়ার আগে, এর সমস্ত রিসোর্সকে অবশ্যই জিপিইউ মেমরিতে থাকতে হয়। এর মানে হলো, এই মেট্রিকের একটি উচ্চ মান বিপুল সংখ্যক ছোট রিসোর্স লোড অথবা অল্প সংখ্যক খুব বড় রিসোর্সকে বোঝাতে পারে। একটি সাধারণ উদাহরণ হলো যখন কোনো অ্যাপ স্ক্রিনের আকারের কাছাকাছি একটি একক বিটম্যাপ প্রদর্শন করে। আরেকটি উদাহরণ হলো যখন কোনো অ্যাপ বিপুল সংখ্যক থাম্বনেইল প্রদর্শন করে।
এই বারটি ছোট করতে, আপনি নিম্নলিখিত কৌশলগুলি অবলম্বন করতে পারেন:
- আপনার বিটম্যাপের রেজোলিউশন যেন প্রদর্শনের আকারের চেয়ে খুব বেশি বড় না হয়, তা নিশ্চিত করুন। উদাহরণস্বরূপ, একটি 1024x1024 ইমেজকে 48x48 ইমেজ হিসেবে প্রদর্শন করা থেকে বিরত থাকুন।
- পরবর্তী সিঙ্ক পর্বের আগে অ্যাসিঙ্ক্রোনাসভাবে একটি বিটম্যাপ প্রি-আপলোড করতে Coil- এর মতো আধুনিক লাইব্রেরি ব্যবহার করা।
আদেশ জারি করুন
ইস্যু কমান্ডস সেগমেন্টটি স্ক্রিনে ডিসপ্লে লিস্ট আঁকার জন্য প্রয়োজনীয় সমস্ত কমান্ড জারি করতে যে সময় লাগে তা নির্দেশ করে।
স্ক্রিনে ডিসপ্লে লিস্ট আঁকার জন্য সিস্টেমটি জিপিইউ-তে প্রয়োজনীয় কমান্ড পাঠায়। সাধারণত, এটি OpenGL ES API-এর মাধ্যমে এই কাজটি সম্পাদন করে।
এই প্রক্রিয়াটিতে কিছুটা সময় লাগে, কারণ সিস্টেমটি GPU-তে কমান্ড পাঠানোর আগে প্রতিটি কমান্ডের জন্য চূড়ান্ত রূপান্তর এবং ক্লিপিং সম্পাদন করে। এরপর GPU-এর দিকে অতিরিক্ত ওভারহেড তৈরি হয়, যা চূড়ান্ত কমান্ডগুলো গণনা করে। এই কমান্ডগুলোর মধ্যে চূড়ান্ত রূপান্তর এবং অতিরিক্ত ক্লিপিং অন্তর্ভুক্ত থাকে।
যখন এই অংশটি বড়
এই পর্যায়ে ব্যয়িত সময় একটি নির্দিষ্ট ফ্রেমে সিস্টেম দ্বারা রেন্ডার করা ডিসপ্লে লিস্টগুলোর জটিলতা এবং পরিমাণের একটি সরাসরি পরিমাপ। উদাহরণস্বরূপ, অনেকগুলো ড্র অপারেশন থাকলে, বিশেষ করে যেখানে প্রতিটি ড্র প্রিমিটিভের একটি সামান্য অন্তর্নিহিত খরচ থাকে, সেখানে এই সময় বেড়ে যেতে পারে। উদাহরণস্বরূপ:
for (i in 0 until 1000) { canvas.drawPoint() }
এর চেয়ে ইস্যু করতে অনেক বেশি ব্যয়বহুল:
canvas.drawPoints(thousandPointArray)
কমান্ড জারি করা এবং বাস্তবে ডিসপ্লে লিস্ট আঁকার মধ্যে সবসময় ১:১ সম্পর্ক থাকে না। ইস্যু কমান্ডস বারের বিপরীতে, যা জিপিইউ-তে ড্রয়িং কমান্ড পাঠাতে লাগা সময়কে ধারণ করে, ড্র মেট্রিকটি জারি করা কমান্ডগুলোকে ডিসপ্লে লিস্টে ধারণ করতে লাগা সময়কে উপস্থাপন করে।
এই পার্থক্যটি দেখা দেয় কারণ সিস্টেম যথাসম্ভব ডিসপ্লে লিস্টগুলো ক্যাশ করে রাখে। ফলে, এমন পরিস্থিতি তৈরি হয় যেখানে স্ক্রল, ট্রান্সফর্ম বা অ্যানিমেশনের জন্য সিস্টেমকে একটি ডিসপ্লে লিস্ট পুনরায় পাঠাতে হয়, কিন্তু সেটিকে একেবারে গোড়া থেকে পুনর্নির্মাণ করতে হয় না—অর্থাৎ ড্রয়িং কমান্ডগুলো পুনরায় ক্যাপচার করতে হয় না। এর ফলে, আপনি একটি উঁচু ইস্যু কমান্ড বার দেখতে পেলেও একটি উঁচু ড্র কমান্ড বার দেখতে পান না।
বাফার অদলবদল করুন
অ্যান্ড্রয়েড যখন জিপিইউ-তে তার ডিসপ্লে তালিকা জমা দেওয়া শেষ করে, তখন সিস্টেম গ্রাফিক্স ড্রাইভারকে বর্তমান ফ্রেমের কাজ শেষ হয়েছে জানানোর জন্য একটি চূড়ান্ত কমান্ড জারি করে। এই পর্যায়ে, ড্রাইভারটি অবশেষে স্ক্রিনে আপডেট করা ছবিটি প্রদর্শন করতে পারে।
যখন এই অংশটি বড়
এটা বোঝা গুরুত্বপূর্ণ যে জিপিইউ (GPU) সিপিইউ (CPU)-এর সাথে সমান্তরালে কাজ সম্পাদন করে। অ্যান্ড্রয়েড সিস্টেম জিপিইউ-কে ড্র কমান্ড পাঠায় এবং তারপর পরবর্তী কাজে চলে যায়। জিপিইউ একটি কিউ থেকে সেই ড্র কমান্ডগুলো পড়ে এবং সেগুলোকে প্রসেস করে।
যখন জিপিইউ যত দ্রুত কমান্ড গ্রহণ করে, সিপিইউ তার চেয়ে দ্রুত কমান্ড জারি করে, তখন প্রসেসরগুলোর মধ্যকার কমিউনিকেশন কিউ পূর্ণ হয়ে যেতে পারে। এমনটা ঘটলে, সিপিইউ ব্লক হয়ে যায় এবং পরবর্তী কমান্ড রাখার জন্য কিউতে জায়গা হওয়া পর্যন্ত অপেক্ষা করে। এই পূর্ণ-কিউ অবস্থাটি প্রায়শই সোয়াপ বাফার পর্যায়ে দেখা দেয়, কারণ সেই সময়ে একটি সম্পূর্ণ ফ্রেমের সমপরিমাণ কমান্ড জমা দেওয়া হয়ে যায়।
এই সমস্যাটি প্রশমিত করার মূল উপায় হলো GPU-তে সম্পাদিত কাজের জটিলতা হ্রাস করা, ঠিক যেমনটা আপনি কমান্ড জারির পর্যায়ে করে থাকেন।
বিবিধ
রেন্ডারিং সিস্টেমের কাজ সম্পাদনে যে সময় লাগে, তা ছাড়াও মূল থ্রেডে আরও এক ধরনের কাজ সম্পন্ন হয়, যার সাথে রেন্ডারিংয়ের কোনো সম্পর্ক নেই। এই কাজে ব্যয়িত সময়কে বিবিধ সময় (miscellaneous time) হিসেবে রিপোর্ট করা হয়। বিবিধ সময় সাধারণত রেন্ডারিংয়ের দুটি পরপর ফ্রেমের মধ্যবর্তী সময়ে UI থ্রেডে সংঘটিত হতে পারে এমন কাজকে বোঝায়।
যখন এই অংশটি বড়
এই মান বেশি হলে, সম্ভবত আপনার অ্যাপে এমন কলব্যাক, ইন্টেন্ট বা অন্যান্য কাজ রয়েছে যা অন্য কোনো থ্রেডে হওয়া উচিত। অ্যান্ড্রয়েড স্টুডিও-এর সিপিইউ প্রোফাইলার বা পারফেটোর মতো টুলগুলো মেইন থ্রেডে চলমান টাস্কগুলো সম্পর্কে ধারণা দিতে পারে। এই তথ্য আপনাকে পারফরম্যান্সের উন্নতি সাধনে সাহায্য করতে পারে। আরও তথ্যের জন্য সিস্টেম ট্রেসিং-এর ওভারভিউ দেখুন।