DTO অপ্টিমাইজ করুন

এই পৃষ্ঠায় আপনার ডিভাইস ট্রি ওভারলে (DTO) প্রয়োগে করা অপ্টিমাইজেশন সম্পর্কে আলোচনা করা হয়েছে, রুট নোড ওভারলে করার ক্ষেত্রে বিধিনিষেধ বর্ণনা করা হয়েছে এবং DTBO ছবিতে কীভাবে কম্প্রেস করা ওভারলে কনফিগার করতে হয় সেই বিষয়ে বিস্তারিত বলা হয়েছে। এছাড়াও, এটি স্যাম্পেল প্রয়োগ করার নির্দেশাবলী ও কোড প্রদান করে।

কার্নেল কমান্ড লাইন

ডিভাইস ট্রি (DT)-তে আসল কার্নেল কমান্ড লাইনটি chosen/bootargs নোডে থাকে। বুটলোডারকে অবশ্যই এই লোকেশনকে কার্নেল কমান্ড লাইনের অন্যান্য সোর্সের সাথে কনক্যাটেনেট করতে হবে:

/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};

DTO, মূল DT ও ওভারলে DT থেকে ভ্যালু কনক্যাটেনেট করতে পারে না, তাই আপনাকে মূল DT-এর কার্নেল কমান্ড লাইন chosen/bootargs-এ এবং ওভারলে DT-এর কার্নেল কমান্ড লাইন chosen/bootargs_ext-এ রাখতে হবে। তারপর বুটলোডার এইসব লোকেশন কনক্যাটেনেট করতে এবং ফলাফল কার্নেলে পাস করতে পারে।

main.dts overlay.dts
/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};
/dts-v1/;
/plugin/;

&chosen {
  bootargs_ext = "...";
};

libufdt

লেটেস্ট libfdt DTO-কে সাপোর্ট করলেও, DTO প্রয়োগ করার জন্য libufdt ব্যবহার করার সাজেশন দেওয়া হয় (AOSP সোর্স platform/system/libufdt-এ)। libufdt ফ্ল্যাটেন করা ডিভাইস ট্রি (FDT) থেকে আসল ট্রি স্ট্রাকচার (আন-ফ্ল্যাটেন করা ডিভাইস ট্রি, বা ufdt) তৈরি করে, তাই এটি দুটি .dtb ফাইলের মার্জ করার প্রসেসকে O(N2) থেকে O(N)-এ উন্নত করতে পারে, যেখানে N হল ট্রিতে নোডের সংখ্যা।

পারফর্ম্যান্স টেস্টিং

Google-এর ইন্টার্নাল টেস্টিংয়ে, libufdt ব্যবহার করে ২৪০৫ .dtb এবং ২৮৩ .dtbo DT নোড কম্পাইলেশনের পরে ফাইল সাইজ ৭০,৬১৮ এবং ৮,৫৬৬ বাইট হয়। FreeBSD থেকে পোর্ট করা (১২৪ মিলিসেকেন্ড রানটাইম) DTO ইমপ্লিমেন্টেশনেরসাথে তুলনা করলে, libufdt DTO রানটাইম ১০ মিলিসেকেন্ড।

Pixel ডিভাইসের পারফর্ম্যান্স টেস্টিং libufdt ও libfdt-এর সাথে তুলনা করা হয়েছে। বেস নোডের সংখ্যার প্রভাব একই রকম, তবে এতে নিম্নলিখিত পার্থক্যগুলি অন্তর্ভুক্ত রয়েছে:

  • ৫০০ ওভারলে (যোগ করা বা ওভাররাইড করা) অপারেশনের ক্ষেত্রে ৬x থেকে ৮x সময়ের পার্থক্য থাকে
  • ১০০০ ওভারলে (যোগ করা বা ওভাররাইড করা) অপারেশনে ৮x থেকে ১০x সময়ের পার্থক্য আছে

X-এ সেট করা সংখ্যা যোগ করার উদাহরণ:

ছবি ১. অ্যাপেন্ড করা সংখ্যা হল X.

ওভাররাইডিং গণনা X-এ সেট করা সহ উদাহরণ:

ছবি ২. ওভাররাইডিংয়ের সংখ্যা হল X।

libufdt কিছু libfdt API ও ডেটা স্ট্রাকচার দিয়ে ডেভেলপ করা হয়েছে। libufdt ব্যবহার করার সময়, আপনাকে অবশ্যই libfdt অন্তর্ভুক্ত ও লিঙ্ক করতে হবে (তবে, আপনার কোডে DTB বা DTBO অপারেট করার জন্য আপনি libfdt API ব্যবহার করতে পারবেন)।

libufdt DTO API

libufdt-এ DTO-তে প্রধান API নিচে দেওয়া হল:

struct fdt_header *ufdt_apply_overlay(
        struct fdt_header *main_fdt_header,
        size_t main_fdt_size,
        void *overlay_fdt,
        size_t overlay_size);

main_fdt_header প্যারামিটার হল মূল DT এবং overlay_fdt হল বাফার যাতে .dtbo ফাইলের কন্টেন্ট থাকে। রিটার্ন ভ্যালু হল একটি নতুন বাফার যাতে মার্জ করা DT (বা ভুল হলে null) থাকে। মার্জ করা DT, FDT-তে ফর্ম্যাট করা হয়, যা আপনি কার্নেল শুরু করার সময় কার্নেলে পাস করতে পারবেন।

রিটার্ন ভ্যালু থেকে নতুন বাফার dto_malloc()-এর মাধ্যমে তৈরি করা হয়, যা বুটলোডারে libufdt পোর্ট করার সময় আপনাকে প্রয়োগ করতে হবে। রেফারেন্স প্রয়োগের জন্য, sysdeps/libufdt_sysdeps_*.c দেখুন।

রুট নোড সংক্রান্ত বিধিনিষেধ

আপনি মূল DT-এর রুট নোডে নতুন নোড বা প্রপার্টি ওভারলে করতে পারবেন না কারণ ওভারলে অপারেশন লেবেলের উপর নির্ভর করে। কারণ মূল DT-কে অবশ্যই একটি লেবেল নির্ধারণ করতে হবে এবং ওভারলে DT, লেবেল সহ ওভারলে করার জন্য নোড অ্যাসাইন করে, আপনি রুট নোডের জন্য কোনও লেবেল দিতে পারবেন না (এবং সেইজন্য রুট নোড ওভারলে করতে পারবেন না)।

SoC ভেন্ডরদের অবশ্যই মূল DT-এর ওভারলে করার ক্ষমতা নির্ধারণ করতে হবে; ODM/OEM শুধুমাত্র SoC ভেন্ডরের দ্বারা সংজ্ঞায়িত লেবেল সহ নোড যোগ করতে বা ওভাররাইড করতে পারে। এর বিকল্প হিসেবে, আপনি বেস DT-র রুট নোডের অধীনে odm নোডকে সংজ্ঞায়িত করতে পারেন, যা নতুন নোড যোগ করার জন্য ওভারলে DT-তে সমস্ত ODM নোডকে সক্ষম করে। বিকল্প হিসেবে, আপনি বেস DT-তে SoC-সম্পর্কিত সব নোডকে রুট নোডের অধীনে soc নোডে রাখতে পারেন, যেমন নিচে বর্ণনা করা হয়েছে:

main.dts overlay.dts
/dts-v1/;

/ {
    compatible = "corp,bar";
    ...

    chosen: chosen {
        bootargs = "...";
    };

    /* nodes for all soc nodes */
    soc {
        ...
        soc_device@0: soc_device@0 {
            compatible = "corp,bar";
            ...
        };
        ...
    };

    odm: odm {
        /* reserved for overlay by odm */
    };
};
/dts-v1/;
/plugin/;

/ {
};

&chosen {
    bootargs_ex = "...";
};

&odm {
    odm_device@0 {
        ...
    };
    ...
};

কম্প্রেস করা ওভারলে ব্যবহার করা

DT টেবিল হেডারের ভার্সন ১ ব্যবহার করার সময় DTBO ইমেজে কমপ্রেস করা ওভারলে ব্যবহার করার সুবিধা Android 9 যোগ করে। DTBO হেডার v1 ব্যবহার করার সময়, dt_table_entry-এর মধ্যে থাকা ফ্ল্যাগ ফিল্ডের চারটি সবচেয়ে কম গুরুত্বপূর্ণ বিট DT এন্ট্রির কম্প্রেশন ফর্ম্যাট নির্দেশ করে।

struct dt_table_entry_v1 {
  uint32_t dt_size;
  uint32_t dt_offset;  /* offset from head of dt_table_header */
  uint32_t id;         /* optional, must be zero if unused */
  uint32_t rev;        /* optional, must be zero if unused */
  uint32_t flags;      /* For version 1 of dt_table_header, the 4 least significant bits
                        of 'flags' are used to indicate the compression
                        format of the DT entry as per the enum 'dt_compression_info' */
  uint32_t custom[3];  /* optional, must be zero if unused */
};

বর্তমানে, zlib এবং gzip কম্প্রেশন কাজ করে।

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9, VtsFirmwareDtboVerification টেস্টে কম্প্রেস করা ওভারলে পরীক্ষা করার সুবিধা যোগ করে, যা আপনাকে ওভারলে অ্যাপের সঠিকতা যাচাই করতে সাহায্য করে।

DTO প্রয়োগের নমুনা

নিম্নলিখিত নির্দেশাবলী আপনাকে libufdt-এর সাথে DTO-এর স্যাম্পেল ইমপ্লিমেন্টেশন (নিচে স্যাম্পেল কোড দেওয়া আছে) সম্পর্কে জানাবে।

DTO নির্দেশাবলীর নমুনা

  1. লাইব্রেরি অন্তর্ভুক্ত করুন। libufdt ব্যবহার করতে, ডেটা স্ট্রাকচার ও API-এর জন্য libfdt অন্তর্ভুক্ত করুন:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
  2. মূল DT ও ওভারলে DT লোড করুন। স্টোরেজ থেকে মেমরিতে .dtb ও .dtbo লোড করুন (সঠিক ধাপগুলি আপনার ডিজাইনের উপর নির্ভর করে)। এই পর্যায়ে, আপনার কাছে .dtb/.dtbo-এর বাফার ও সাইজ থাকতে হবে:
    main_size = my_load_main_dtb(main_buf, main_buf_size)
    overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
  3. DT ওভারলে করুন:
    1. প্রধান DT-এর জন্য FDT হেডার পেতে ufdt_install_blob() ব্যবহার করুন:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
    2. FDT ফর্ম্যাটে মার্জ করা DT পেতে DTO-তে ufdt_apply_overlay() কল করুন ফর্ম্যাট:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
    3. dtc_totalsize()-এর সাইজ পেতে merged_fdt ব্যবহার করুন:
      merged_fdt_size = dtc_totalsize(merged_fdt);
    4. কার্নেল চালু করতে মার্জ করা DT পাস করুন:
      my_kernel_entry(0, machine_type, merged_fdt);

DTO কোডের নমুনা

#include <libfdt.h>
#include <ufdt_overlay.h>

…

{
  struct fdt_header *main_fdt_header;
  struct fdt_header *merged_fdt;

  /* load main dtb into memory and get the size */
  main_size = my_load_main_dtb(main_buf, main_buf_size);

  /* load overlay dtb into memory and get the size */
  overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);

  /* overlay */
  main_fdt_header = ufdt_install_blob(main_buf, main_size);
  main_fdt_size = main_size;
  merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                  overlay_buf, overlay_size);
  merged_fdt_size = dtc_totalsize(merged_fdt);

  /* pass to kernel */
  my_kernel_entry(0, machine_type, merged_fdt);
}