استخدم التحسين الموجه للملف الشخصي

يدعم نظام إنشاء Android لنظام التشغيل Android 13 والإصدارات الأقدم استخدام التحسين الموجه للملف الشخصي (PGO) الخاص بـ Clang على وحدات Android الأصلية التي تحتوي على قواعد إنشاء مخطط . توضح هذه الصفحة Clang PGO، وكيفية إنشاء ملفات التعريف المستخدمة لـ PGO وتحديثها باستمرار، وكيفية دمج PGO مع نظام البناء (مع حالة الاستخدام).

ملاحظة: يصف هذا المستند استخدام PGO في نظام Android الأساسي. للتعرف على كيفية استخدام PGO من تطبيق Android، تفضل بزيارة هذه الصفحة .

حول كلانج PGO

يمكن لـ Clang إجراء تحسين موجه للملف الشخصي باستخدام نوعين من الملفات الشخصية:

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

يجب أن يتم إنشاء جميع الملفات الشخصية من عبء عمل تمثيلي يمارس السلوك النموذجي للتطبيق. في حين أن Clang يدعم كلا من المستند إلى AST ( -fprofile-instr-generate ) والمستند إلى LLVM IR ( -fprofile-generate) ، فإن Android يدعم فقط LLVM IR المستند إلى PGO القائم على الأجهزة.

العلامات التالية مطلوبة لإنشاء مجموعة الملفات الشخصية:

  • -fprofile-generate الأجهزة القائمة على الأشعة تحت الحمراء. باستخدام هذا الخيار، تستخدم الواجهة الخلفية أسلوب الشجرة الممتدة الموزونة للحد الأدنى لتقليل عدد نقاط الأجهزة وتحسين موضعها على الحواف منخفضة الوزن (استخدم هذا الخيار لخطوة الارتباط أيضًا). يقوم برنامج تشغيل Clang تلقائيًا بتمرير وقت تشغيل التوصيف ( libclang_rt.profile- arch -android.a ) إلى الرابط. تحتوي هذه المكتبة على إجراءات لكتابة الملفات الشخصية على القرص عند خروج البرنامج.
  • -gline-tables-only لجمع ملفات التعريف المستندة إلى العينات لإنشاء الحد الأدنى من معلومات التصحيح.

يمكن استخدام ملف التعريف لـ PGO باستخدام -fprofile-use= pathname أو -fprofile-sample-use= pathname لملفات التعريف القائمة على الأجهزة والعينات على التوالي.

ملاحظة: عند إجراء تغييرات على التعليمات البرمجية، إذا لم يعد Clang قادرًا على استخدام بيانات الملف الشخصي، فسيتم إنشاء تحذير -Wprofile-instr-out-of-date .

استخدم PGO

يتضمن استخدام PGO الخطوات التالية:

  1. أنشئ المكتبة/الملف القابل للتنفيذ باستخدام الأجهزة عن طريق تمرير -fprofile-generate إلى المترجم والرابط.
  2. جمع ملفات التعريف عن طريق تشغيل عبء عمل تمثيلي على الثنائي المجهز.
  3. قم بالمعالجة اللاحقة لملفات التعريف باستخدام الأداة المساعدة llvm-profdata (لمزيد من التفاصيل، راجع التعامل مع ملفات تعريف LLVM ).
  4. استخدم ملفات التعريف لتطبيق PGO عن طريق تمرير -fprofile-use=<>.profdata إلى المترجم والرابط.

بالنسبة إلى PGO في Android، يجب جمع الملفات الشخصية في وضع عدم الاتصال وإيداعها جنبًا إلى جنب مع الكود لضمان إنشاء نسخ قابلة للتكرار. يمكن استخدام الملفات الشخصية مع تطور التعليمات البرمجية، ولكن يجب إعادة إنشائها بشكل دوري (أو عندما يحذر Clang من أن الملفات الشخصية قديمة).

جمع الملفات الشخصية

يمكن لـ Clang استخدام ملفات التعريف التي تم جمعها عن طريق تشغيل المعايير باستخدام بنية مُجهزة للمكتبة أو عن طريق أخذ عينات من عدادات الأجهزة عند تشغيل المعيار. في الوقت الحالي، لا يدعم Android استخدام مجموعة ملفات التعريف المستندة إلى أخذ العينات، لذلك يجب عليك جمع ملفات التعريف باستخدام تصميم مُجهز:

  1. تحديد المعيار ومجموعة المكتبات التي يمارسها هذا المعيار بشكل جماعي.
  2. أضف خصائص pgo إلى المعيار والمكتبات (التفاصيل أدناه).
  3. قم بإنشاء إصدار Android باستخدام نسخة مُجهزة من هذه المكتبات باستخدام:
    make ANDROID_PGO_INSTRUMENT=benchmark

benchmark هو عنصر نائب يحدد مجموعة المكتبات التي تم تجهيزها أثناء الإنشاء. المدخلات التمثيلية الفعلية (وربما ملف تنفيذي آخر يرتبط بمكتبة يتم قياسها) ليست خاصة بـ PGO وهي خارج نطاق هذه الوثيقة.

  1. قم بفلاش أو مزامنة البنية المُجهزة على الجهاز.
  2. قم بتشغيل المعيار لجمع الملفات الشخصية.
  3. استخدم أداة llvm-profdata (الموضحة أدناه) للمعالجة اللاحقة لملفات التعريف وجعلها جاهزة للتحقق في شجرة المصدر.

استخدام ملفات التعريف أثناء الإنشاء

تحقق من الملفات الشخصية في toolchain/pgo-profiles في شجرة Android. يجب أن يتطابق الاسم مع ما تم تحديده في الخاصية الفرعية profile_file لخاصية pgo الخاصة بالمكتبة. يقوم نظام البناء تلقائيًا بتمرير ملف التعريف إلى Clang عند إنشاء المكتبة. يمكن ضبط متغير البيئة ANDROID_PGO_DISABLE_PROFILE_USE على true لتعطيل PGO مؤقتًا وقياس فائدة أدائه.

لتحديد أدلة ملفات تعريف إضافية خاصة بالمنتج، قم بإلحاقها بمتغير التكوين PGO_ADDITIONAL_PROFILE_DIRECTORIES في BoardConfig.mk . إذا تم تحديد مسارات إضافية، فإن ملفات التعريف الموجودة في هذه المسارات ستتجاوز تلك الموجودة في toolchain/pgo-profiles .

عند إنشاء صورة إصدار باستخدام هدف dist make يكتب نظام الإنشاء أسماء ملفات التعريف المفقودة إلى $DIST_DIR/pgo_profile_file_missing.txt . يمكنك التحقق من هذا الملف لمعرفة ملفات التعريف التي تم إسقاطها عن طريق الخطأ (مما يؤدي إلى تعطيل PGO بصمت).

تمكين PGO في ملفات Android.bp

لتمكين PGO في ملفات Android.bp للوحدات الأصلية، ما عليك سوى تحديد خاصية pgo . تحتوي هذه الخاصية على الخصائص الفرعية التالية:

ملكية وصف
instrumentation اضبط على true لـ PGO باستخدام الأجهزة. الافتراضي false .
sampling اضبط على true لـ PGO باستخدام أخذ العينات. الافتراضي false .
benchmarks قائمة السلاسل. تم إنشاء هذه الوحدة للتوصيف إذا تم تحديد أي معيار في القائمة في خيار البناء ANDROID_PGO_INSTRUMENT .
profile_file ملف التعريف (المتعلق بـ toolchain/pgo-profile ) لاستخدامه مع PGO. يحذر البناء من أن هذا الملف غير موجود عن طريق إضافة هذا الملف إلى $DIST_DIR/pgo_profile_file_missing.txt ما لم يتم تعيين خاصية enable_profile_use على false أو يتم تعيين متغير البناء ANDROID_PGO_NO_PROFILE_USE على true .
enable_profile_use اضبط على false إذا كان لا ينبغي استخدام ملفات التعريف أثناء الإنشاء. يمكن استخدامه أثناء التمهيد لتمكين جمع الملفات الشخصية أو لتعطيل PGO مؤقتًا. الافتراضي true .
cflags قائمة العلامات الإضافية التي سيتم استخدامها أثناء إنشاء الأجهزة.

مثال لوحدة مع PGO:

cc_library {
    name: "libexample",
    srcs: [
        "src1.cpp",
        "src2.cpp",
    ],
    static: [
        "libstatic1",
        "libstatic2",
    ],
    shared: [
        "libshared1",
    ]
    pgo: {
        instrumentation: true,
        benchmarks: [
            "benchmark1",
            "benchmark2",
        ],
        profile_file: "example.profdata",
    }
}

إذا كانت المعايير المعيارية benchmark1 و benchmark2 تمارس سلوكًا تمثيليًا للمكتبات libstatic1 أو libstatic2 أو libshared1 ، فيمكن أن تتضمن خاصية pgo لهذه المكتبات أيضًا المعايير. يمكن أن تتضمن وحدة defaults في Android.bp مواصفات pgo شائعة لمجموعة من المكتبات لتجنب تكرار نفس قواعد البناء لعدة وحدات.

لتحديد ملفات تعريف مختلفة أو تعطيل PGO بشكل انتقائي لبنية ما، حدد خصائص profile_file و enable_profile_use و cflags لكل بنية. مثال (مع هدف البنية بالخط العريض ):

cc_library {
    name: "libexample",
    srcs: [
          "src1.cpp",
          "src2.cpp",
    ],
    static: [
          "libstatic1",
          "libstatic2",
    ],
    shared: [
          "libshared1",
    ],
    pgo: {
         instrumentation: true,
         benchmarks: [
              "benchmark1",
              "benchmark2",
         ],
    }

    target: {
         android_arm: {
              pgo: {
                   profile_file: "example_arm.profdata",
              }
         },
         android_arm64: {
              pgo: {
                   profile_file: "example_arm64.profdata",
              }
         }
    }
}

لحل المراجع إلى مكتبة وقت تشغيل ملفات التعريف أثناء إنشاء ملفات التعريف المستندة إلى الأجهزة، قم بتمرير علامة البناء -fprofile-generate إلى الرابط. المكتبات الثابتة المجهزة بـ PGO، وجميع المكتبات المشتركة، وأي ثنائي يعتمد بشكل مباشر على المكتبة الثابتة، يجب أيضًا أن تكون مُجهزة بـ PGO. ومع ذلك، فإن مثل هذه المكتبات المشتركة أو الملفات التنفيذية لا تحتاج إلى استخدام ملفات تعريف PGO، ويمكن تعيين خاصية enable_profile_use الخاصة بها على false . خارج هذا القيد، يمكنك تطبيق PGO على أي مكتبة ثابتة أو مكتبة مشتركة أو قابلة للتنفيذ.

التعامل مع ملفات تعريف LLVM

يؤدي تنفيذ مكتبة مُجهزة أو ملف قابل للتنفيذ إلى إنتاج ملف تعريف يُسمى default_ unique_id _0.profraw في /data/local/tmp (حيث يكون unique_id عبارة عن تجزئة رقمية فريدة لهذه المكتبة). إذا كان هذا الملف موجودًا بالفعل، فسيقوم وقت تشغيل ملف التعريف بدمج ملف التعريف الجديد مع الملف القديم أثناء كتابة ملفات التعريف. لاحظ أن /data/local/tmp لا يمكن لمطوري التطبيقات الوصول إليه؛ يجب عليهم استخدام مكان ما مثل /storage/emulated/0/Android/data/ packagename /files بدلاً من ذلك. لتغيير موقع ملف التعريف، قم بتعيين متغير البيئة LLVM_PROFILE_FILE في وقت التشغيل.

يتم بعد ذلك استخدام الأداة المساعدة llvm-profdata لتحويل ملف .profraw (وربما دمج ملفات .profraw متعددة) إلى ملف .profdata :

  llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>

يمكن بعد ذلك التحقق من profile.profdata في الشجرة المصدر لاستخدامها أثناء الإنشاء.

إذا تم تحميل العديد من المكتبات/الثنائيات المجهزة بالأدوات أثناء اختبار الأداء، فستقوم كل مكتبة بإنشاء ملف .profraw منفصل بمعرف فريد منفصل. عادةً، يمكن دمج كل هذه الملفات في ملف .profdata واحد واستخدامه لبناء PGO. في الحالات التي يتم فيها استخدام المكتبة بواسطة معيار قياس آخر، يجب تحسين تلك المكتبة باستخدام ملفات التعريف من كلا المعيارين. في هذه الحالة، يكون خيار show لـ llvm-profdata مفيدًا:

  llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw
llvm-profdata show -all-functions default_unique_id.profdata

لتعيين Unique_id للمكتبات الفردية، ابحث في إخراج show لكل Unique_id عن اسم وظيفة فريد للمكتبة.

دراسة الحالة: PGO للفن

تقدم دراسة الحالة العلاج المضاد للفيروسات القهقرية كمثال وثيق الصلة؛ ومع ذلك، فهو ليس وصفًا دقيقًا للمجموعة الفعلية من المكتبات المحددة لـ ART أو الاعتماد المتبادل بينها.

يعتمد المترجم المسبق dex2oat في ART على libart-compiler.so ، والذي يعتمد بدوره على libart.so . يتم تنفيذ وقت تشغيل ART بشكل أساسي في libart.so . ستكون معايير المترجم ووقت التشغيل مختلفة:

المعيار المكتبات الشخصية
dex2oat dex2oat (قابل للتنفيذ)، libart-compiler.so ، libart.so
art_runtime libart.so
  1. أضف خاصية pgo التالية إلى dex2oat libart-compiler.so :
        pgo: {
            instrumentation: true,
            benchmarks: ["dex2oat",],
            profile_file: "dex2oat.profdata",
        }
  2. أضف خاصية pgo التالية إلى libart.so :
        pgo: {
            instrumentation: true,
            benchmarks: ["art_runtime", "dex2oat",],
            profile_file: "libart.profdata",
        }
  3. قم بإنشاء تصميمات مُجهزة لمعايير dex2oat و art_runtime باستخدام:
        make ANDROID_PGO_INSTRUMENT=dex2oat
        make ANDROID_PGO_INSTRUMENT=art_runtime
  4. بدلاً من ذلك، قم بإنشاء بنية مُجهزة واحدة باستخدام جميع المكتبات المُجهزة باستخدام:

        make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime
        (or)
        make ANDROID_PGO_INSTRUMENT=ALL

    يقوم الأمر الثاني ببناء جميع الوحدات النمطية التي تدعم PGO للتوصيف.

  5. قم بتشغيل المعايير التي تمارس dex2oat و art_runtime للحصول على:
    • تم تحديد ثلاثة ملفات .profraw من dex2oat ( dex2oat_exe.profdata dex2oat_libart-compiler.profdata و dexeoat_libart.profdata ) باستخدام الطريقة الموضحة في معالجة ملفات تعريف LLVM .
    • art_runtime_libart.profdata واحد.
  6. قم بإنشاء ملف profdata شائع لـ dex2oat القابل للتنفيذ و libart-compiler.so باستخدام:
    llvm-profdata merge -output=dex2oat.profdata \
        dex2oat_exe.profdata dex2oat_libart-compiler.profdata
  7. احصل على الملف التعريفي لـ libart.so من خلال دمج الملفات الشخصية من المعيارين:
    llvm-profdata merge -output=libart.profdata \
        dex2oat_libart.profdata art_runtime_libart.profdata

    قد تكون الأعداد الأولية لـ libart.so من الملفين الشخصيين مختلفة لأن المعايير تختلف في عدد حالات الاختبار ومدة تشغيلها. في هذه الحالة، يمكنك استخدام الدمج الموزون:

    llvm-profdata merge -output=libart.profdata \
        -weighted-input=2,dex2oat_libart.profdata \
        -weighted-input=1,art_runtime_libart.profdata

    يقوم الأمر أعلاه بتعيين ضعف الوزن لملف التعريف من dex2oat . يجب تحديد الوزن الفعلي بناءً على معرفة المجال أو التجربة.

  8. تحقق من ملفات التعريف dex2oat.profdata و libart.profdata في toolchain/pgo-profiles لاستخدامها أثناء الإنشاء.