ใช้การเพิ่มประสิทธิภาพโดยอิงตามโปรไฟล์

ระบบการสร้างของ Android สำหรับ Android 13 และต่ำกว่ารองรับการใช้การเพิ่มประสิทธิภาพโดยอิงตามโปรไฟล์ (PGO) ของ Clang ในโมดูล Android เนทีฟที่มีกฎการสร้าง blueprint หน้านี้อธิบาย Clang PGO, วิธีสร้างและอัปเดตโปรไฟล์ที่ใช้สำหรับ PGO อย่างต่อเนื่อง และวิธีผสานรวม PGO กับระบบการบิลด์ (พร้อมกรณีการใช้งาน)

หมายเหตุ: เอกสารนี้อธิบายการใช้ PGO ในแพลตฟอร์ม Android ดูข้อมูลเกี่ยวกับการใช้ PGO จากแอป Android ได้ที่ หน้านี้

เกี่ยวกับ Clang PGO

Clang สามารถทำการเพิ่มประสิทธิภาพโดยอิงตามโปรไฟล์ได้โดยใช้โปรไฟล์ 2 ประเภทดังนี้

  • โปรไฟล์ที่อิงตามเครื่องมือวัดสร้างขึ้นจากโปรแกรมเป้าหมายที่มีเครื่องมือวัด โปรไฟล์เหล่านี้มีรายละเอียดสูงและทำให้เกิดค่าใช้จ่ายเพิ่มเติมในรันไทม์
  • โปรไฟล์ที่อิงตามการสุ่มตัวอย่างมักสร้างขึ้นโดยเคาน์เตอร์ฮาร์ดแวร์การสุ่มตัวอย่าง ข้อมูลเหล่านี้มีค่าใช้จ่ายรันไทม์ต่ำและรวบรวมได้โดยไม่ต้องมีเครื่องมือวัดผลหรือการแก้ไขไบนารี โปรไฟล์เหล่านี้มีรายละเอียดน้อยกว่าโปรไฟล์ที่อิงตามเครื่องมือวัด

โปรไฟล์ทั้งหมดควรสร้างขึ้นจากภาระงานที่แสดงถึงลักษณะการทำงานทั่วไปของแอป แม้ว่า Clang จะรองรับทั้งแบบที่อิงตาม AST (-fprofile-instr-generate) และแบบที่อิงตาม LLVM IR (-fprofile-generate) แต่ Android รองรับเฉพาะแบบที่อิงตาม LLVM IR สำหรับ PGO ที่อิงตามเครื่องมือวัด

คุณต้องสร้าง Flag ต่อไปนี้สําหรับการเก็บรวบรวมโปรไฟล์

  • -fprofile-generate สำหรับเครื่องมือวัดที่ใช้ IR เมื่อใช้ตัวเลือกนี้ แบ็กเอนด์จะใช้แนวทางต้นไม้สายเชื่อมขั้นต่ำที่มีน้ำหนักเพื่อลดจํานวนจุดเครื่องมือวัดและเพิ่มประสิทธิภาพตําแหน่งจุดเครื่องมือวัดไปยังขอบที่มีน้ำหนักเบา (ใช้ตัวเลือกนี้สําหรับขั้นตอนลิงก์ด้วย) โปรแกรมขับ 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 make variable in a 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 build
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 รายการ Flag เพิ่มเติมที่จะใช้ในระหว่างการสร้างที่มีการวัดผล

ตัวอย่างโมดูลที่มี 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",
              }
         }
    }
}

หากต้องการแก้ไขการอ้างอิงถึงไลบรารีรันไทม์ของเครื่องมือวิเคราะห์ระหว่างการโปรไฟล์ตามเครื่องมือวัด ให้ส่ง Flag การสร้าง -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 ในกรณีที่มีการใช้ไลบรารีในเบนช์มาร์กอื่น ไลบรารีนั้นจะต้องได้รับการเพิ่มประสิทธิภาพโดยใช้โปรไฟล์จากทั้ง 2 เบนช์มาร์ก ในกรณีนี้ ตัวเลือก 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

กรณีศึกษานี้แสดง ART เป็นตัวอย่างที่เข้าใจง่าย แต่ไม่ใช่คำอธิบายที่ถูกต้องของชุดไลบรารีจริงที่จัดทำโปรไฟล์สำหรับ ART หรือความสัมพันธ์ระหว่างไลบรารีเหล่านั้น

dex2oatคอมไพเลอร์ล่วงหน้าใน ART ขึ้นอยู่กับ libart-compiler.so ซึ่งขึ้นอยู่กับ libart.so รันไทม์ ART ใช้งานได้ใน libart.so เป็นหลัก การเปรียบเทียบประสิทธิภาพสำหรับคอมไพเลอร์และรันไทม์จะแตกต่างกันดังนี้

Benchmark ไลบรารีที่โปรไฟล์
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

    คำสั่งที่ 2 จะสร้างโมดูลที่เปิดใช้ PGO ทั้งหมดสําหรับการสร้างโปรไฟล์

  5. เรียกใช้การเปรียบเทียบการออกกำลังกาย dex2oat และ art_runtime เพื่อรับสิ่งต่อไปนี้
    • ไฟล์ .profraw 3 ไฟล์จาก 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 โดยการผสานโปรไฟล์จากข้อมูลเปรียบเทียบ 2 รายการต่อไปนี้
    llvm-profdata merge -output=libart.profdata \
        dex2oat_libart.profdata art_runtime_libart.profdata

    จํานวนดิบของ libart.so จาก 2 โปรไฟล์อาจแตกต่างกันเนื่องจากเบนช์มาร์กมีจํานวนกรณีทดสอบและระยะเวลาที่ทํางานแตกต่างกัน ในกรณีนี้ คุณสามารถใช้การผสานแบบถ่วงน้ำหนักได้

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

    คําสั่งข้างต้นกําหนดน้ำหนักให้กับโปรไฟล์จาก dex2oat เป็น 2 เท่า น้ำหนักจริงควรกำหนดตามความรู้หรือการทดลองในโดเมน

  8. ตรวจสอบไฟล์โปรไฟล์ dex2oat.profdata และ libart.profdata ไปยัง toolchain/pgo-profiles เพื่อใช้ในระหว่างการสร้าง