ProfilingManager সিস্টেম ট্রিগারের উপর ভিত্তি করে প্রোফাইল ক্যাপচার সমর্থন করে। সিস্টেমটি রেকর্ডিং প্রক্রিয়া পরিচালনা করে এবং ফলাফল প্রোফাইল আপনার অ্যাপে সরবরাহ করে।
ট্রিগারগুলি পারফরম্যান্স-সমালোচনামূলক ইভেন্টগুলির সাথে সম্পর্কিত। সিস্টেম-রেকর্ড করা প্রোফাইলগুলি এই ট্রিগারগুলির সাথে সম্পর্কিত গুরুত্বপূর্ণ ব্যবহারকারীর ভ্রমণের (CUJ) জন্য বিশদ ডিবাগিং তথ্য সরবরাহ করে।
ঐতিহাসিক তথ্য ক্যাপচার করুন
অনেক ট্রিগারের জন্য ঘটনার পূর্ববর্তী ঐতিহাসিক তথ্য বিশ্লেষণ করতে হয়। ট্রিগারটি প্রায়শই মূল কারণের পরিবর্তে কোনও সমস্যার ফলাফল। ট্রিগারটি হওয়ার পরেই যদি আপনি একটি প্রোফাইল শুরু করেন, তাহলে মূল কারণটি ইতিমধ্যেই হারিয়ে যেতে পারে।
উদাহরণস্বরূপ, UI থ্রেডে দীর্ঘ সময় ধরে চলমান একটি অপারেশনের ফলে একটি অ্যাপ্লিকেশন নট রেসপন্ডিং (ANR) ত্রুটি দেখা দেয়। সিস্টেম যখন ANR সনাক্ত করে এবং অ্যাপটিকে সংকেত দেয়, তখন অপারেশনটি শেষ হয়ে যেতে পারে। সেই মুহূর্তে একটি প্রোফাইল শুরু করলে প্রকৃত ব্লকিং কাজটি মিস হয়ে যায়।
কিছু ট্রিগার কখন ঘটবে তা ঠিকভাবে ভবিষ্যদ্বাণী করা অসম্ভব, যার ফলে আগে থেকে ম্যানুয়ালি প্রোফাইল শুরু করা অসম্ভব হয়ে পড়ে।
ট্রিগার-ভিত্তিক ক্যাপচার কেন ব্যবহার করবেন?
প্রোফাইলিং ট্রিগার ব্যবহার করার প্রাথমিক কারণ হল অপ্রত্যাশিত ইভেন্টগুলির ডেটা ক্যাপচার করা যেখানে কোনও অ্যাপের পক্ষে এই ইভেন্টগুলি ঘটার আগে ম্যানুয়ালি রেকর্ডিং শুরু করা অসম্ভব। প্রোফাইলিং ট্রিগারগুলি নিম্নলিখিত ক্ষেত্রে ব্যবহার করা যেতে পারে:
- ডিবাগ কর্মক্ষমতা সমস্যা: ANR, মেমরি লিক এবং অন্যান্য স্থিতিশীলতা সমস্যা নির্ণয় করুন।
- গুরুত্বপূর্ণ ব্যবহারকারীর যাত্রা অপ্টিমাইজ করুন: প্রবাহ বিশ্লেষণ করুন এবং উন্নত করুন, উদাহরণস্বরূপ, অ্যাপ স্টার্টআপ।
- ব্যবহারকারীর আচরণ বুঝুন: ইভেন্টগুলির অন্তর্দৃষ্টি অর্জন করুন, উদাহরণস্বরূপ, ব্যবহারকারী-প্রবর্তিত অ্যাপ প্রস্থান।
একটি ট্রিগার সেট আপ করুন
নিম্নলিখিত কোডটি দেখায় কিভাবে TRIGGER_TYPE_APP_FULLY_DRAWN ট্রিগারের জন্য নিবন্ধন করতে হয় এবং এতে রেট লিমিটিং প্রয়োগ করতে হয়।
কোটলিন
fun recordWithTrigger() { val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) val triggers = ArrayList<ProfilingTrigger>() val triggerBuilder = ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN) .setRateLimitingPeriodHours(1) triggers.add(triggerBuilder.build()) val mainExecutor: Executor = Executors.newSingleThreadExecutor() val resultCallback = Consumer<ProfilingResult> { profilingResult -> if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.resultFilePath ) setupProfileUploadWorker(profilingResult.resultFilePath) } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage ) } } profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback) profilingManager.addProfilingTriggers(triggers)
জাভা
public void recordWithTrigger() { ProfilingManager profilingManager = getApplicationContext().getSystemService( ProfilingManager.class); List<ProfilingTrigger> triggers = new ArrayList<>(); ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder( ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN); triggerBuilder.setRateLimitingPeriodHours(1); triggers.add(triggerBuilder.build()); Executor mainExecutor = Executors.newSingleThreadExecutor(); Consumer<ProfilingResult> resultCallback = new Consumer<ProfilingResult>() { @Override public void accept(ProfilingResult profilingResult) { if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.getResultFilePath()); setupProfileUploadWorker(profilingResult.getResultFilePath()); } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.getErrorCode() + " errormsg=" + profilingResult.getErrorMessage()); } } }; profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback); profilingManager.addProfilingTriggers(triggers);
কোডটি এই পদক্ষেপগুলি সম্পাদন করে:
- ম্যানেজারটি পান :
ProfilingManagerপরিষেবাটি পুনরুদ্ধার করে। - ট্রিগার সংজ্ঞায়িত করুন :
TRIGGER_TYPE_APP_FULLY_DRAWNএর জন্য একটিProfilingTriggerতৈরি করে। এই ইভেন্টটি তখন ঘটে যখন অ্যাপটি রিপোর্ট করে যে এটি স্টার্টআপ শেষ করেছে এবং ইন্টারেক্টিভ। - হারের সীমা নির্ধারণ করুন : এই নির্দিষ্ট ট্রিগারে ১ ঘন্টার হারের সীমা প্রয়োগ করে (
setRateLimitingPeriodHours(1))। এটি অ্যাপটিকে প্রতি ঘন্টায় একাধিক স্টার্টআপ প্রোফাইল রেকর্ড করতে বাধা দেয়। - Register listener : ফলাফল পরিচালনাকারী কলব্যাক নির্ধারণ করতে
registerForAllProfilingResultsকল করে। এই কলব্যাকটিgetResultFilePath()এর মাধ্যমে সংরক্ষিত প্রোফাইলের পথ গ্রহণ করে। - ট্রিগার যোগ করুন :
addProfilingTriggersব্যবহার করেProfilingManagerসাথে ট্রিগার তালিকা নিবন্ধন করে। - ফায়ার ইভেন্ট :
reportFullyDrawn()কল করে, যা সিস্টেমেTRIGGER_TYPE_APP_FULLY_DRAWNইভেন্ট নির্গত করে, যা ধরে নেয় যে সিস্টেমের ব্যাকগ্রাউন্ড ট্রেস চলছে এবং রেট লিমিটার কোটা উপলব্ধ রয়েছে, একটি প্রোফাইল সংগ্রহ ট্রিগার করে। এই ঐচ্ছিক ধাপটি একটি এন্ড-টু-এন্ড ফ্লো প্রদর্শন করে কারণ আপনার অ্যাপটিকে এই ট্রিগারের জন্যreportFullyDrawn()কল করতে হবে।
ট্রেসটি পুনরুদ্ধার করুন
সিস্টেমটি ট্রিগার-ভিত্তিক প্রোফাইলগুলিকে অন্যান্য প্রোফাইলের মতো একই ডিরেক্টরিতে সংরক্ষণ করে। ট্রিগার করা ট্রেসের ফাইলের নাম এই ফর্ম্যাট অনুসরণ করে:
profile_trigger_<profile_type_code>_<datetime>.<profile-type-name>
আপনি ADB ব্যবহার করে ফাইলটি টেনে আনতে পারেন। উদাহরণস্বরূপ, ADB ব্যবহার করে উদাহরণ কোড দিয়ে ক্যাপচার করা সিস্টেম ট্রেসটি টেনে আনতে, এটি দেখতে এরকম হতে পারে:
adb pull /data/user/0/com.example.sampleapp/files/profiling/profile_trigger_1_2025-05-06-14-12-40.perfetto-trace
এই ট্রেসগুলি ভিজ্যুয়ালাইজ করার বিশদ বিবরণের জন্য, প্রোফাইলিং ডেটা পুনরুদ্ধার এবং বিশ্লেষণ দেখুন।
ব্যাকগ্রাউন্ড ট্রেসিং কীভাবে কাজ করে
ট্রিগারের আগে থেকে ডেটা ক্যাপচার করার জন্য, OS পর্যায়ক্রমে একটি ব্যাকগ্রাউন্ড ট্রেস শুরু করে। যদি এই ব্যাকগ্রাউন্ড ট্রেস সক্রিয় থাকাকালীন এবং আপনার অ্যাপটি এর জন্য নিবন্ধিত থাকাকালীন কোনও ট্রিগার ঘটে, তাহলে সিস্টেমটি ট্রেস প্রোফাইলটি আপনার অ্যাপের ডিরেক্টরিতে সংরক্ষণ করে। তারপর উইল প্রোফাইলে ট্রিগারের দিকে পরিচালিত তথ্য অন্তর্ভুক্ত থাকে।
প্রোফাইলটি সংরক্ষণ করা হয়ে গেলে, সিস্টেমটি registerForAllProfilingResults এ প্রদত্ত কলব্যাক ব্যবহার করে আপনার অ্যাপটিকে অবহিত করে। এই কলব্যাকটি ক্যাপচার করা প্রোফাইলের পথটি গোপন করে যা ProfilingResult#getResultFilePath() কল করে অ্যাক্সেস করা যেতে পারে।

ডিভাইসের কর্মক্ষমতা এবং ব্যাটারি লাইফের উপর প্রভাব কমাতে, সিস্টেমটি ব্যাকগ্রাউন্ড ট্রেসগুলিকে একটানা চালায় না। পরিবর্তে, এটি একটি নমুনা পদ্ধতি ব্যবহার করে। সিস্টেমটি একটি নির্দিষ্ট সময়সীমার মধ্যে (সর্বনিম্ন এবং সর্বোচ্চ সময়কাল সহ) এলোমেলোভাবে একটি ব্যাকগ্রাউন্ড ট্রেস শুরু করে। এলোমেলোভাবে এই ট্রেসগুলিকে ব্যবধান দিলে ট্রিগার কভারেজ উন্নত হয়।
সিস্টেম-ট্রিগার করা প্রোফাইলগুলির একটি সিস্টেম-নির্ধারিত সর্বোচ্চ আকার থাকে, তাই তারা একটি রিং বাফার ব্যবহার করে। বাফারটি পূর্ণ হয়ে গেলে, নতুন ট্রেস ডেটা সবচেয়ে পুরানো ডেটা ওভাররাইট করে। চিত্র 1-এ দেখানো হয়েছে, যদি বাফারটি পূর্ণ হয়ে যায় তবে একটি ক্যাপচার করা ট্রেস ব্যাকগ্রাউন্ড রেকর্ডিংয়ের পুরো সময়কাল কভার নাও করতে পারে; পরিবর্তে, এটি ট্রিগারের দিকে পরিচালিত সাম্প্রতিকতম কার্যকলাপকে প্রতিনিধিত্ব করে।
ট্রিগার-নির্দিষ্ট হার সীমাবদ্ধতা বাস্তবায়ন করুন
উচ্চ-ফ্রিকোয়েন্সি ট্রিগারগুলি আপনার অ্যাপের রেট লিমিটার কোটা দ্রুত গ্রাস করতে পারে। রেট লিমিটারটি আরও ভালভাবে বুঝতে, আমরা আপনাকে রেট লিমিটার কীভাবে কাজ করে তা দেখার জন্য উৎসাহিত করছি। একটি একক ট্রিগার টাইপ যাতে আপনার কোটা শেষ না করে, আপনি ট্রিগার-নির্দিষ্ট রেট লিমিটিং বাস্তবায়ন করতে পারেন।
ProfilingManager অ্যাপ-সংজ্ঞায়িত ট্রিগার-নির্দিষ্ট রেট লিমিটিং সমর্থন করে। এটি আপনাকে বিদ্যমান রেট লিমিটারের পাশাপাশি সময়-ভিত্তিক থ্রটলিংয়ের আরেকটি স্তর যোগ করতে দেয়। একটি ট্রিগারের জন্য একটি নির্দিষ্ট কুলডাউন সময় সেট করতে setRateLimitingPeriodHours API ব্যবহার করুন। কুলডাউনের মেয়াদ শেষ হওয়ার পরে, আপনি এটি আবার ট্রিগার করতে পারেন।
ডিবাগ স্থানীয়ভাবে ট্রিগার করে
যেহেতু ব্যাকগ্রাউন্ড ট্রেসগুলি এলোমেলো সময়ে চলে, তাই স্থানীয়ভাবে ট্রিগারগুলি ডিবাগ করা কঠিন। পরীক্ষার জন্য একটি ব্যাকগ্রাউন্ড ট্রেস জোর করে করতে, নিম্নলিখিত ADB কমান্ডটি ব্যবহার করুন:
adb shell device_config put profiling_testing system_triggered_profiling.testing_package_name <com.example.myapp>
এই কমান্ডটি সিস্টেমকে নির্দিষ্ট প্যাকেজের জন্য একটি অবিচ্ছিন্ন ব্যাকগ্রাউন্ড ট্রেস শুরু করতে বাধ্য করে, যদি রেট লিমিটার অনুমতি দেয় তবে প্রতিটি ট্রিগার একটি প্রোফাইল সংগ্রহ করতে সক্ষম হয়।
আপনি অন্যান্য ডিবাগ বিকল্পগুলিও সক্ষম করতে পারেন, উদাহরণস্বরূপ, স্থানীয়ভাবে ডিবাগ করার সময় রেট লিমিটার অক্ষম করা। আরও তথ্যের জন্য, স্থানীয় প্রোফাইলিংয়ের জন্য ডিবাগ কমান্ডগুলি দেখুন।