অর্ডার ফাইল

অর্ডার ফাইল হলো একটি সাম্প্রতিক লিঙ্কার অপটিমাইজেশন কৌশল। এই অর্ডার ফাইলগুলো হলো টেক্সট ফাইল, যেগুলোতে ফাংশনের প্রতিনিধিত্বকারী সিম্বল থাকে। lld-এর মতো লিঙ্কারগুলো ফাংশনগুলোকে একটি নির্দিষ্ট ক্রমে সাজানোর জন্য অর্ডার ফাইল ব্যবহার করে। সাজানো সিম্বলযুক্ত এই বাইনারি বা লাইব্রেরিগুলো পেজ ফল্ট কমায় এবং প্রোগ্রামের কোল্ড-স্টার্টের সময় সিম্বলগুলোর কার্যকর লোডিংয়ের কারণে প্রোগ্রামের লঞ্চ টাইম উন্নত করে।

তিনটি ধাপ অনুসরণ করে আপনার অ্যাপ্লিকেশনে অর্ডার ফাইলের বৈশিষ্ট্যগুলো যোগ করা যেতে পারে:

  1. প্রোফাইল এবং ম্যাপিং ফাইল তৈরি করুন
  2. প্রোফাইল এবং ম্যাপিং ফাইল থেকে একটি অর্ডার ফাইল তৈরি করুন
  3. রিলিজ বিল্ডের সময় সিম্বলগুলো বিন্যস্ত করতে অর্ডার ফাইলটি ব্যবহার করুন।

অর্ডার ফাইল তৈরি করুন

অর্ডার ফাইল তৈরি করতে তিনটি ধাপ প্রয়োজন:

  1. অ্যাপটির এমন একটি ইনস্ট্রুমেন্টেড সংস্করণ তৈরি করুন যা অর্ডার ফাইলটি লিখে রাখে।
  2. প্রোফাইল তৈরি করতে অ্যাপটি চালান।
  3. প্রোফাইল এবং ম্যাপিং ফাইল পোস্ট-প্রসেস করুন

একটি ইন্সট্রুমেন্টেড বিল্ড তৈরি করুন

অ্যাপ্লিকেশনটির একটি ইন্সট্রুমেন্টেড বিল্ড চালানোর মাধ্যমে প্রোফাইলগুলো তৈরি করা হয়। একটি ইন্সট্রুমেন্টেড বিল্ডের জন্য কম্পাইলার এবং লিঙ্কার উভয় ফ্ল্যাগেই -forder-file-instrumentation যোগ করতে হয় এবং কম্পাইলার ফ্ল্যাগে বিশেষভাবে -mllvm -orderfile-write-mapping=<filename>-mapping.txt যোগ করতে হয়। ইন্সট্রুমেন্টেশন ফ্ল্যাগটি প্রোফাইলিংয়ের জন্য অর্ডার ফাইল ইন্সট্রুমেন্টেশন সক্ষম করে এবং প্রোফাইলিংয়ের জন্য প্রয়োজনীয় নির্দিষ্ট লাইব্রেরিটি লোড করে। অন্যদিকে, ম্যাপিং ফ্ল্যাগটি কেবল ম্যাপিং ফাইলটি আউটপুট করে, যা বাইনারি বা লাইব্রেরির প্রতিটি ফাংশনের MD5 হ্যাশ দেখায়।

এছাড়াও, -O0 ছাড়া অন্য যেকোনো অপটিমাইজেশন ফ্ল্যাগ পাস করতে ভুলবেন না, কারণ ইন্সট্রুমেন্টেশন ফ্ল্যাগ এবং ম্যাপিং ফ্ল্যাগ উভয়ের জন্যই এটি প্রয়োজন। যদি কোনো অপটিমাইজেশন ফ্ল্যাগ পাস না করা হয়, তাহলে ম্যাপিং ফাইল তৈরি হয় না এবং ইন্সট্রুমেন্টেড বিল্ডটি প্রোফাইল ফাইলে ভুল হ্যাশ আউটপুট করতে পারে।

এনডিকে-বিল্ড

অবশ্যই APP_OPTIM=release দিয়ে বিল্ড করুন, যাতে ndk-build -O0 ছাড়া অন্য কোনো অপটিমাইজেশন মোড ব্যবহার করে। AGP দিয়ে বিল্ড করার সময় রিলিজ বিল্ডের জন্য এটি স্বয়ংক্রিয়ভাবে হয়ে যায়।

LOCAL_CFLAGS += \
    -forder-file-instrumentation \
    -mllvm -orderfile-write-mapping=mapping.txt \

LOCAL_LDFLAGS += -forder-file-instrumentation

CMake

Debug ছাড়া অন্য একটি CMAKE_BUILD_TYPE ব্যবহার করতে ভুলবেন না, যাতে CMake -O0 ছাড়া অন্য কোনো অপটিমাইজেশন মোড ব্যবহার করে। AGP দিয়ে বিল্ড করার সময় রিলিজ বিল্ডের জন্য এটি স্বয়ংক্রিয়ভাবে হয়ে থাকে।

target_compile_options(orderfiledemo PRIVATE
    -forder-file-instrumentation
    -mllvm -orderfile-write-mapping=mapping.txt
)
target_link_options(orderfiledemo PRIVATE -forder-file-instrumentation)

অন্যান্য বিল্ড সিস্টেম

আপনার কোডটি -forder-file-instrumentation -O1 -mllvm -orderfile-write-mapping=mapping.txt ব্যবহার করে কম্পাইল করুন।

বিশেষভাবে -O1 ব্যবহার করার প্রয়োজন নেই, কিন্তু -O0 ব্যবহার করবেন না।

লিঙ্ক করার সময় -mllvm -orderfile-write-mapping=mapping.txt বাদ দিন।

রিলিজ বিল্ডের জন্য এই সমস্ত ফ্ল্যাগের প্রয়োজন হয় না, তাই এটি একটি বিল্ড ভেরিয়েবল দ্বারা নিয়ন্ত্রণ করা উচিত। সরলতার জন্য, আপনি আমাদের নমুনার মতো CMakeLists.txt-এ এই সবকিছু সেট আপ করতে পারেন।

একটি অর্ডার ফাইল লাইব্রেরি তৈরি করুন

ফ্ল্যাগগুলো ছাড়াও, প্রোফাইল ফাইলটি সেট আপ করতে হবে এবং ইনস্ট্রুমেন্টেড বাইনারিটিকে তার নির্বাহের সময় সুস্পষ্টভাবে একটি প্রোফাইল রাইট ট্রিগার করতে হবে।

  • প্রোফাইল পাথ সেট করার জন্য __llvm_profile_set_filename(PROFILE_DIR "/<filename>-%m.profraw") কল করুন। যদিও আর্গুমেন্ট হিসেবে <filename>-%m.profraw পাস করা হয়, প্রোফাইল ফাইলটি <filename>-%m.profraw.order হিসেবে সেভ করা হয়। নিশ্চিত করুন যে PROFILE_DIR অ্যাপের জন্য রাইটেবল (writable) এবং ডিরেক্টরিটিতে আপনার অ্যাক্সেস আছে।
    • অনেক শেয়ার্ড লাইব্রেরি প্রোফাইল করা হয় বলে %m বেশ উপযোগী, কারণ এটি লাইব্রেরিটির জন্য একটি অনন্য মডিউল সিগনেচারে রূপান্তরিত হয়, যার ফলে প্রতিটি লাইব্রেরির জন্য একটি পৃথক প্রোফাইল তৈরি হয়। আরও প্যাটার্ন স্পেসিফায়ারের জন্য, আপনি এই লিঙ্কটি দেখতে পারেন।
  • প্রোফাইল ফাইল সেট আপ করতে __llvm_profile_initialize_file() কল করুন।
  • প্রোফাইল ফাইলে স্পষ্টভাবে লেখার জন্য __llvm_orderfile_dump() কল করুন।

প্রোফাইলগুলো মেমরিতে সংগ্রহ করা হয় এবং ডাম্প ফাংশন সেগুলোকে ফাইলে লিখে দেয়। আপনাকে নিশ্চিত করতে হবে যেন স্টার্টআপের শেষে ডাম্প ফাংশনটি কল করা হয়, যাতে আপনার প্রোফাইল ফাইলে স্টার্টআপের শেষ পর্যন্ত সমস্ত সিম্বল থাকে।

extern "C" {
extern int __llvm_profile_set_filename(const char*);
extern int __llvm_profile_initialize_file(void);
extern int __llvm_orderfile_dump(void);
}

#define PROFILE_DIR "<location-writable-from-app>"
void workload() {
  // ...
  // run workload
  // ...

  // set path and write profiles after workload execution
  __llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw");
  __llvm_profile_initialize_file();
  __llvm_orderfile_dump();
  return;
}

প্রোফাইলগুলির জন্য বিল্ডটি চালান

প্রোফাইলগুলো তৈরি করতে ফিজিক্যাল বা ভার্চুয়াল ডিভাইসে ইন্সট্রুমেন্টেড অ্যাপটি চালান। আপনি adb pull ব্যবহার করে প্রোফাইল ফাইলগুলো এক্সট্র্যাক্ট করতে পারেন।

adb shell "run-as <package-name> sh -c 'cat /data/user/0/<package-name>/cache/default-%m.profraw.order' | cat > /data/local/tmp/default-%m.profraw.order"
adb pull /data/local/tmp/default-%m.profraw.order .

পূর্বে যেমন বলা হয়েছে, নিশ্চিত করুন যে লিখিত প্রোফাইল ফাইলটি যে ফোল্ডারে রয়েছে, সেখানে আপনার প্রবেশাধিকার আছে। যদি এটি একটি ভার্চুয়াল ডিভাইস হয়, তবে অনেক ফোল্ডারে প্রবেশাধিকার না থাকার কারণে প্লে স্টোরযুক্ত এমুলেটরগুলো এড়িয়ে চলাই ভালো।

প্রোফাইল এবং ম্যাপিং ফাইল পোস্টপ্রসেস করুন

যখন আপনি প্রোফাইলগুলো পাবেন, তখন আপনাকে ম্যাপিং ফাইলটি খুঁজে বের করতে হবে এবং প্রতিটি প্রোফাইলকে হেক্সাডেসিমাল ফরম্যাটে রূপান্তর করতে হবে। সাধারণত, আপনি অ্যাপের বিল্ড ফোল্ডারে ম্যাপিং ফাইলটি খুঁজে পাবেন। যখন আপনার কাছে দুটিই থাকবে, তখন আপনি আমাদের স্ক্রিপ্ট ব্যবহার করে একটি প্রোফাইল ফাইল এবং সঠিক ম্যাপিং ফাইল থেকে একটি অর্ডার ফাইল তৈরি করতে পারবেন।

লিনাক্স/ম্যাক/ক্রোমওএস

hexdump -C default-%m.profraw.order > default-%m.prof
python3 create_orderfile.py --profile-file default-%m.prof --mapping-file <filename>-mapping.txt

উইন্ডোজ

certutil -f -encodeHex default-%m.profraw.order default-%m.prof
python3 create_orderfile.py --profile-file default-%m.prof --mapping-file <filename>-mapping.txt

আপনি যদি স্ক্রিপ্টটি সম্পর্কে আরও পড়তে চান, তাহলে এই README-টি দেখতে পারেন।

অ্যাপ্লিকেশন তৈরি করতে অর্ডার ফাইল ব্যবহার করুন

অর্ডার ফাইল তৈরি করার পরে, আপনার আগের ফ্ল্যাগ এবং অর্ডার ফাইল ফাংশনগুলি সরিয়ে ফেলা উচিত কারণ সেগুলি শুধুমাত্র তৈরির ধাপের জন্য ব্যবহৃত হয়। আপনাকে শুধু কম্পাইল এবং লিঙ্কার ফ্ল্যাগে -Wl,--symbol-ordering-file=<filename>.orderfile পাস করতে হবে। কখনও কখনও, সিম্বল খুঁজে পাওয়া যায় না বা সরানো যায় না এবং সতর্কবার্তা দেয়, তাই আপনি এই সতর্কবার্তাগুলি দমন করতে -Wl,--no-warn-symbol-ordering পাস করতে পারেন।

এনডিকে-বিল্ড

LOCAL_CFLAGS += \
    -Wl,--symbol-ordering-file=<filename>.orderfile \
    -Wl,--no-warn-symbol-ordering \

LOCAL_LDFLAGS += \
    -Wl,--symbol-ordering-file=<filename>.orderfile \
    -Wl,--no-warn-symbol-ordering \

CMake

target_compile_options(orderfiledemo PRIVATE
    -Wl,--symbol-ordering-file=<filename>.orderfile
    -Wl,--no-warn-symbol-ordering
)
target_link_options(orderfiledemo PRIVATE
    -Wl,--symbol-ordering-file=<filename>.orderfile
    -Wl,--no-warn-symbol-ordering
)

অন্যান্য বিল্ড সিস্টেম

আপনার কোড কম্পাইল করুন -Wl,--symbol-ordering-file=<filename>.orderfile -Wl,--no-warn-symbol-ordering ব্যবহার করে।

আরও তথ্যের জন্য অর্ডার ফাইলের উদাহরণটি দেখুন।

অর্ডার ফাইল বাস্তবায়নের বিবরণ

অর্ডার ফাইল তৈরি করার এবং বিল্ড করার জন্য সেগুলো ব্যবহার করার অনেক উপায় আছে। NDK, LLVM-এর পদ্ধতি ব্যবহার করে, তাই এটি আসল জাভা বা কোটলিন অ্যাপের চেয়ে আপনার C বা C++ শেয়ার্ড লাইব্রেরির জন্য বেশি উপযোগী। Clang প্রতিটি ফাংশনের নাম (সিম্বল) নিয়ে সেটির একটি MD5 হ্যাশ তৈরি করে এবং এই সম্পর্কটি একটি ম্যাপিং ফাইলে আউটপুট করে। যখন কোনো ফাংশন প্রথমবার এক্সিকিউট হয়, তখন তার MD5 হ্যাশটি প্রোফাইল ফাইলে (profraw ফরম্যাটে) লেখা হয়। ফাংশনটির পরবর্তী কোনো এক্সিকিউশনে এর MD5 হ্যাশ প্রোফাইল ফাইলে লেখা হয় না, কারণ এটি ডুপ্লিকেট এড়াতে চায়। ফলে, অর্ডারে শুধুমাত্র ফাংশনটির প্রথম এক্সিকিউশনটিই রেকর্ড করা হয়। প্রোফাইল ফাইল এবং ম্যাপিং ফাইলের মধ্য দিয়ে গিয়ে, আপনি প্রতিটি MD5 হ্যাশ নিয়ে সেটিকে সংশ্লিষ্ট ফাংশনের সাথে প্রতিস্থাপন করে একটি অর্ডার ফাইল পেতে পারেন।

হেক্সাডেসিমাল ফরম্যাটে একটি প্রোফাইল ফাইল এবং একটি ম্যাপিং ফাইলের উদাহরণ যথাক্রমে example.prof এবং example-mapping.txt হিসেবে পাওয়া যাবে।