নেটিভ কোডে কাস্টম ট্রেস ইভেন্ট

অ্যান্ড্রয়েড 6.0 (এপিআই স্তর 23) এবং উচ্চতর একটি নেটিভ ট্রেসিং API, trace.h সমর্থন করে, সিস্টেম বাফারে ট্রেস ইভেন্টগুলি লিখতে যা আপনি পারফেটো বা সিস্ট্রেস ব্যবহার করে বিশ্লেষণ করতে পারেন। এই API-এর সাধারণ ব্যবহারের ক্ষেত্রে কোডের একটি নির্দিষ্ট ব্লক কার্যকর করতে যে সময় লাগে তা পর্যবেক্ষণ করা এবং কোডের একটি ব্লককে অবাঞ্ছিত সিস্টেম আচরণের সাথে যুক্ত করা অন্তর্ভুক্ত।

দ্রষ্টব্য: API স্তর 27 এবং তার নিচের ডিভাইস এবং এমুলেটরগুলিতে, যদি পর্যাপ্ত মেমরি উপলব্ধ না থাকে বা মেমরিটি খুব খণ্ডিত হয় তবে আপনি নিম্নলিখিত বার্তাটি পাবেন: Atrace could not allocate enough memory to record a trace ৷ যদি এটি ঘটে এবং আপনার ক্যাপচারে ডেটার সম্পূর্ণ সেট না থাকে, তাহলে আপনার পটভূমি প্রক্রিয়াগুলি বন্ধ করা উচিত বা ডিভাইস বা এমুলেটর পুনরায় চালু করা উচিত।

আপনার অ্যাপ বা গেমের মধ্যে নেটিভ কোডে ঘটে এমন কাস্টম ইভেন্টগুলি সংজ্ঞায়িত করতে, নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করুন:

  1. 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);
    
  2. রানটাইমে 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() এ কল অন্তর্ভুক্ত করুন।

    দ্রষ্টব্য: অ্যান্ড্রয়েড 4.3 (এপিআই স্তর 18) এ আরও ফিরে ট্রেসিং সমর্থন প্রদান করতে, আপনি পূর্বের স্নিপেটে দেখানো কোডের চারপাশে পরিচালিত কোডের পদ্ধতিগুলি কল করতে JNI ব্যবহার করতে পারেন।

  3. আপনার কাস্টম ইভেন্টের শুরুতে এবং শেষে যথাক্রমে 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 করতে পারে।

একটি সম্পূর্ণ ফাংশন ট্রেস করার জন্য একটি ম্যাক্রো তৈরি করতে, নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করুন:

  1. ম্যাক্রো সংজ্ঞায়িত করুন:

    #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();
        }
    };
    
  2. আপনি যে ফাংশনটি ট্রেস করতে চান তার মধ্যে ম্যাক্রোকে কল করুন:

    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");
}
{% verbatim %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}