Android 6.0 (API লেভেল 23) এবং তার পরবর্তী ভার্সন নেটিভ ট্রেসিং API, trace.h,
সাপোর্ট করে, যাতে সিস্টেম বাফারে ট্রেস ইভেন্ট লেখা যায় এবং আপনি Perfetto বা systrace ব্যবহার করে
সেটি বিশ্লেষণ করতে পারেন। এই API-এর সাধারণ ব্যবহারের মধ্যে রয়েছে কোডের একটি নির্দিষ্ট ব্লক এক্সিকিউট করতে যে সময় লাগে তা পর্যবেক্ষণ করা এবং কোডের একটি ব্লককে অবাঞ্ছিত সিস্টেম আচরণের সাথে যুক্ত করা।
মনে রাখবেন: API লেভেল ২৭ ও তার নিচের ভার্সনে চলা ডিভাইস ও এমুলেটরে, পর্যাপ্ত মেমরি উপলভ্য না থাকলে বা মেমরি খুব বেশি ফ্র্যাগমেন্টেড হলে, আপনি এই মেসেজ পাবেন: Atrace could not allocate enough memory to record a trace।
এটি হলে এবং আপনার ক্যাপচারে ডেটার সম্পূর্ণ সেট না থাকলে, আপনাকে
ব্যাকগ্রাউন্ড প্রসেস বন্ধ করতে হবে অথবা ডিভাইস বা এমুলেটর রিস্টার্ট করতে হবে।
আপনার অ্যাপ বা গেমের মধ্যে নেটিভ কোডে ঘটা কাস্টম ইভেন্ট সংজ্ঞায়িত করতে, নিম্নলিখিত ধাপগুলি সম্পূর্ণ করুন:
ATrace ফাংশনের জন্য ফাংশন পয়েন্টার নির্ধারণ করুন যা আপনি নিজের অ্যাপ বা গেমে কাস্টম ইভেন্ট ক্যাপচার করতে ব্যবহার করেন, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:
#include <android/trace.h> #include <dlfcn.h> void *(*ATrace_beginSection) (const char* sectionName); void *(*ATrace_endSection) (void); typedef void *(*fp_ATrace_beginSection) (const char* sectionName); typedef void *(*fp_ATrace_endSection) (void);
রানটাইমে ATrace সিম্বল লোড করুন, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে। সাধারণত, আপনি অবজেক্ট কনস্ট্রাক্টরে এই প্রসেসটি করেন।
// Retrieve a handle to libandroid. void *lib = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL); // Access the native tracing functions. if (lib != NULL) { // Use dlsym() to prevent crashes on devices running Android 5.1 // (API level 22) or lower. ATrace_beginSection = reinterpret_cast<fp_ATrace_beginSection>( dlsym(lib, "ATrace_beginSection")); ATrace_endSection = reinterpret_cast<fp_ATrace_endSection>( dlsym(lib, "ATrace_endSection")); }
সতর্কতা: নিরাপত্তার কারণে, আপনার অ্যাপ বা গেমের শুধুমাত্র ডিবাগ ভার্সনে
dlopen()-এ কল করার সুবিধা অন্তর্ভুক্ত করুন।মনে রাখবেন: Android 4.3 (API লেভেল ১৮) পর্যন্ত ট্রেসিং সংক্রান্ত সহায়তা প্রদান করতে, আপনি JNI ব্যবহার করে ম্যানেজ করা কোডে পদ্ধতি কল করতে পারেন, যা পূর্ববর্তী স্নিপেটে দেখানো কোডের আশেপাশে থাকে।
আপনার কাস্টম ইভেন্টের শুরুতে
ATrace_beginSection()এবং শেষেATrace_endSection()কল করুন:#include <android/trace.h> char *customEventName = new char[32]; sprintf(customEventName, "User tapped %s button", buttonName); ATrace_beginSection(customEventName); // Your app or game's response to the button being pressed. ATrace_endSection();
মনে রাখবেন: আপনি একাধিকবার
ATrace_beginSection()কল করলে,ATrace_endSection()কল করলে শুধুমাত্র সবচেয়ে সম্প্রতি কল করাATrace_beginSection()পদ্ধতি শেষ হয়। তাই, নেস্টেড কলের জন্য, প্রতিটি কলকেATrace_beginSection()-এর সাথেATrace_endSection()-এর কলের সাথে সঠিকভাবে ম্যাচ করতে ভুলবেন না।এছাড়াও, আপনি একটি থ্রেডে
ATrace_beginSection()-কে কল করে অন্য থ্রেড থেকে সেটি শেষ করতে পারবেন না। আপনাকে একই থ্রেড থেকে দুটি ফাংশনই কল করতে হবে।
সুবিধা সংক্রান্ত পরামর্শ
নিম্নলিখিত পরামর্শগুলি ঐচ্ছিক তবে আপনার নেটিভ কোড বিশ্লেষণ করা সহজ করে তুলতে পারে।
সম্পূর্ণ ফাংশন ট্রেস করো
আপনার কল স্ট্যাক বা ফাংশন টাইমিং ইন্সট্রুমেন্ট করার সময়, আপনি সম্পূর্ণ ফাংশন ট্রেস করার জন্য
এটি উপযোগী বলে মনে করতে পারেন। এই ধরনের ট্রেসিং আরও সহজে সেট-আপ করতে আপনি ATRACE_CALL() ম্যাক্রো ব্যবহার করতে পারেন। এছাড়াও, এই ধরনের ম্যাক্রো আপনাকে
try এবং catch ব্লক তৈরি করা এড়িয়ে যেতে দেয়, যেখানে ট্রেস করা ফাংশন
ব্যতিক্রম দেখাতে পারে বা return আগে কল করতে পারে।
সম্পূর্ণ ফাংশন ট্রেস করার জন্য ম্যাক্রো তৈরি করতে, নিম্নলিখিত ধাপগুলি সম্পূর্ণ করুন:
ম্যাক্রো সংজ্ঞায়িত করুন:
#define ATRACE_NAME(name) ScopedTrace ___tracer(name) // ATRACE_CALL is an ATRACE_NAME that uses the current function name. #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__) class ScopedTrace { public: inline ScopedTrace(const char *name) { ATrace_beginSection(name); } inline ~ScopedTrace() { ATrace_endSection(); } };
আপনি যে ফাংশন ট্রেস করতে চান তার মধ্যে ম্যাক্রো কল করুন:
void myExpensiveFunction() { ATRACE_CALL(); // Code that you want to trace. }
আপনার থ্রেডের নাম দিন
আপনার ইভেন্ট যে থ্রেডে ঘটে, আপনি সেটির নাম দিতে পারেন, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে। এই ধাপটি আপনার গেমের মধ্যে নির্দিষ্ট অ্যাকশনের সাথে সম্পর্কিত থ্রেডগুলি শনাক্ত করা সহজ করে তোলে।
#include <pthread.h> static void *render_scene(void *parm) { // Code for preparing your app or game's visual components. } static void *load_main_menu(void *parm) { // Code that executes your app or game's main logic. } void init_threads() { pthread_t render_thread, main_thread; pthread_create(&render_thread, NULL, render_scene, NULL); pthread_create(&main_thread, NULL, load_main_menu, NULL); pthread_setname_np(render_thread, "MyRenderer"); pthread_setname_np(main_thread, "MyMainMenu"); }
আপনার জন্য সাজেস্ট করা হয়েছে
- মনে রাখবেন: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট দেখানো হয়
- SQLite পারফর্ম্যান্সের জন্য পেশাদার পদ্ধতি
- Macrobenchmark ছাড়াই বেসলাইন প্রোফাইল তৈরি ও পরিমাপ করা