طلب الملفات

ملف الطلب هو أحد الأساليب الحديثة لتحسين الروابط. ملفات الترتيب هذه هي ملفات نصية تحتوي على رموز تمثل الدوال. تستخدم الروابط مثل lld ملفات الترتيب لتخطيط الدوال بترتيب معين. وتعمل هذه البرامج الثنائية أو المكتبات ذات الرموز المرتبة على تقليل أخطاء الصفحة وتحسين وقت تشغيل البرنامج بسبب التحميل الفعّال للرموز أثناء بدء البرنامج على البارد.

يمكن إضافة ميزات ملف الطلب إلى تطبيقك بثلاث خطوات:

  1. إنشاء ملفات شخصية وملف تعيين
  2. إنشاء ملف طلب من الملفات الشخصية وملف التعيين
  3. استخدم ملف الطلب أثناء إصدار الإصدار لتنسيق الرموز

إنشاء ملف الطلب

يتطلب إنشاء ملف طلب ثلاث خطوات:

  1. إنشاء إصدار مبرمج من التطبيق يقوم بكتابة ملف الطلب
  2. تشغيل التطبيق لإنشاء الملفات الشخصية
  3. بعد معالجة الملفات الشخصية وملف التعيين

إنشاء إصدار مزوّد بآلة

يتم إنشاء الملفات الشخصية عن طريق تشغيل إصدار معدّ للتطبيق من التطبيق. يتطلّب الإصدار المتكامل إضافة -forder-file-instrumentation إلى كلّ من علامتَي أداة التجميع والربط مع إضافة -mllvm -orderfile-write-mapping=<filename>-mapping.txt بشكل صارم إلى علامات برنامج التجميع. تتيح علامة قياس حالة التطبيق قياس حالة ملف الطلب من أجل تحديد المواصفات الشخصية وتحميل المكتبة المحددة اللازمة للتحليل. من ناحية أخرى، تُخرج علامة التعيين ملف التعيين الذي يُظهر تجزئة MD5 لكل دالة داخل البرنامج الثنائي أو المكتبة.

بالإضافة إلى ذلك، احرص على تمرير أي علامة تحسين غير علامة -O0 لأنّ كلاً من علامة الأداة وعلامة التعيين يتطلبان علامة واحدة. في حال عدم تمرير أي علامة تحسين، لا يتم إنشاء ملف التعيين وقد ينتج عن الإصدار المستند تجزئات خاطئة إلى ملف الملف الشخصي.

إصدار ndk

احرص على الإنشاء باستخدام APP_OPTIM=release حتى يستخدم إنشاء ndk وضع تحسين بخلاف -O0. عند الإنشاء باستخدام AGP، يتم ذلك تلقائيًا في نُسَخ الإصدار.

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

LOCAL_LDFLAGS += -forder-file-instrumentation

CMaker

تأكَّد من استخدام CMAKE_BUILD_TYPE بخلاف Debug حتى يستخدم 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 قابل للكتابة من خلال التطبيق وأنّ لديك إذن وصول إلى الدليل.
    • بما أنّ العديد من المكتبات المشتركة يتم تحليلها، أصبح %m مفيدًا لأنّه يتم توسيعه ليشمل توقيع وحدة فريد للمكتبة، ما يؤدي إلى إنشاء ملف شخصي منفصل لكل مكتبة. لمزيد من محددات الأنماط، يمكنك الاطلاع على هذا الرابط.
  • الاتصال بـ __llvm_profile_initialize_file() لإعداد ملف الملف الشخصي
  • عليك الاتصال بـ __llvm_orderfile_dump() للكتابة صراحةً إلى ملف الملف الشخصي.

يتم جمع الملفات الشخصية في الذاكرة وتقوم دالة 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 .

كما ذكرنا سابقًا، تأكد من أن المجلد الذي يحتوي على ملف الملف الشخصي المكتوب يمكن الوصول إليه. وإذا كان جهازًا افتراضيًا، قد ترغب في تجنب أدوات المحاكاة من خلال متجر Play بسبب عدم إمكانية الوصول إلى العديد من المجلدات.

المعالجة اللاحقة لملف التعريف وملف التعيين

عندما تحصل على الملفات الشخصية، تحتاج إلى العثور على ملف التعيين وتحويل كل ملف شخصي إلى تنسيق سداسي عشري. يمكنك عادةً العثور على ملف الربط في مجلد الإصدار الخاص بالتطبيق. وعندما يكون لديك كلاهما، يمكنك استخدام النص البرمجي لأخذ ملف ملف شخصي وملف التعيين الصحيح لإنشاء ملف طلب.

Linux/Mac/ChromeOS

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

أجهزة Windows

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 هذه التحذيرات.

إصدار ndk

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 \

CMaker

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++ على تطبيق Java أو لغة Kotlin الفعلي. تأخذ علامة Clang كل اسم دالة (رمز) وتنشئ تجزئة MD5 منها وتخرج هذه العلاقة إلى ملف تعيين. تتم كتابة تجزئة MD5 للدالة في ملف الملف الشخصي (تنسيق الملف الشخصي) عند تنفيذ الدالة لأول مرة. لا تكتب أي عمليات تنفيذ لاحقة للدالة تجزئة MD5 في ملف الملف الشخصي لأنها تريد تجنب التكرارات. نتيجة لذلك، يتم تسجيل أول عملية تنفيذ فقط للدالة بالترتيب. من خلال الاطلاع على ملف الملف الشخصي وملف التعيين، يمكنك أخذ كل تجزئة MD5 واستبدالها بالدالة المقابلة والحصول على ملف طلب.

يمكن العثور على أمثلة لكل من ملف ملف شخصي بتنسيق سداسي عشري وملف تعيين على النحو التالي: example.prof وexample-mapping.txt على التوالي.