سفارش فایل ها

فایل سفارش یک تکنیک اخیر بهینه سازی پیوند دهنده است. این فایل های سفارش فایل های متنی حاوی نمادهایی هستند که توابع را نشان می دهند. لینک‌هایی مانند lld از فایل‌های سفارش برای چیدمان توابع به ترتیب خاصی استفاده می‌کنند. این باینری ها یا کتابخانه ها با نمادهای مرتب شده، خطاهای صفحه را کاهش می دهند و زمان راه اندازی برنامه را به دلیل بارگذاری کارآمد نمادها در طول شروع سرد برنامه بهبود می بخشند.

ویژگی های فایل سفارش را می توان با انجام سه مرحله به برنامه شما اضافه کرد:

  1. ایجاد پروفایل ها و فایل نقشه برداری
  2. از پروفایل ها و فایل نقشه برداری یک فایل سفارش ایجاد کنید
  3. از فایل سفارش در طول ساخت Release برای چیدمان نمادها استفاده کنید

ایجاد فایل سفارش

ایجاد یک فایل سفارش به سه مرحله نیاز دارد:

  1. یک نسخه ابزاری از برنامه بسازید که فایل سفارش را می نویسد
  2. برنامه را برای تولید پروفایل ها اجرا کنید
  3. پروفایل ها و فایل نقشه برداری را پس از پردازش انجام دهید

یک سازه ابزاری ایجاد کنید

پروفایل ها با اجرای یک ساخت ابزاری از برنامه تولید می شوند. یک ساخت ابزاری نیازمند افزودن -forder-file-instrumentation به پرچم‌های کامپایلر و پیونددهنده است و -mllvm -orderfile-write-mapping=<filename>-mapping.txt به‌شدت به پرچم‌های کامپایلر اضافه می‌شود. پرچم ابزار دقیق ابزار دقیق فایل سفارش را برای نمایه سازی فعال می کند و کتابخانه خاص مورد نیاز برای پروفایل را بارگیری می کند. از سوی دیگر، پرچم نگاشت فقط فایل نگاشت را خروجی می دهد که هش MD5 را برای هر تابع در باینری یا کتابخانه نشان می دهد.

علاوه بر این، مطمئن شوید که هر پرچم بهینه‌سازی به غیر از -O0 را ارسال کنید زیرا هم پرچم ابزار دقیق و هم پرچم نقشه‌برداری به یکی نیاز دارند. اگر هیچ پرچم بهینه‌سازی ارسال نشود، فایل نگاشت ایجاد نمی‌شود و ساخت ابزاری ممکن است هش‌های اشتباهی را به فایل نمایه ارسال کند.

ndk-build

حتماً با APP_OPTIM=release بسازید تا ndk-build از حالت بهینه‌سازی دیگری غیر از -O0 استفاده کند. هنگام ساخت با AGP، این برای انتشار بیلدها به صورت خودکار است.

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

LOCAL_LDFLAGS += -forder-file-instrumentation

CMake

مطمئن شوید که از یک 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 را هنگام پیوند حذف کنید.

همه این پرچم‌ها برای ساخت Release مورد نیاز نیستند، بنابراین باید توسط یک متغیر ساخت کنترل شود. برای سادگی، می‌توانید همه این موارد را مانند نمونه ما در 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 آنها را در فایل می نویسد. باید مطمئن شوید که تابع 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;
}

Build for Profiles را اجرا کنید

برای تولید نمایه ها، برنامه ابزاردار را روی یک دستگاه فیزیکی یا مجازی اجرا کنید. می توانید فایل های نمایه را با استفاده از 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 Store اجتناب کنید.

فایل نمایه و نقشه برداری را پس از پردازش انجام دهید

هنگامی که پروفایل ها را دریافت می کنید، باید فایل نگاشت را پیدا کنید و هر پروفایل را به فرمت هگزادسیمال تبدیل کنید. به طور معمول، می توانید فایل نگاشت را در پوشه ساخت برنامه پیدا کنید. وقتی هر دو را دارید، می توانید از اسکریپت ما برای گرفتن یک فایل نمایه و از فایل نگاشت صحیح برای تولید یک فایل سفارش استفاده کنید.

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

ویندوز

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-build

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++ شما در برنامه جاوا یا Kotlin واقعی مفیدترین است. Clang نام هر تابع (نماد) را می گیرد و یک هش MD5 از آن ایجاد می کند و این رابطه را به یک فایل نگاشت خروجی می دهد. هش MD5 یک تابع در فایل نمایه (فرمت profraw) زمانی که تابع برای اولین بار اجرا می شود، نوشته می شود. هر گونه اجرای بعدی تابع، هش MD5 آن را در فایل نمایه نمی‌نویسد زیرا می‌خواهد از تکرار جلوگیری کند. در نتیجه، تنها اولین اجرای تابع در ترتیب ثبت می شود. با مرور فایل پروفایل و فایل نقشه برداری، می توانید هر هش MD5 را بردارید و تابع مربوطه را جایگزین آن کنید و یک فایل سفارش بگیرید.

نمونه هایی از هر دو فایل نمایه در قالب هگزادسیمال و فایل نگاشت را می توان به ترتیب به عنوان example.prof و example-mapping.txt یافت.