Cara kerja Pengoptimalan yang Dipandu Profil (PGO)

Pengoptimalan yang dipandu profil (juga dikenal sebagai PGO, atau "pogo") adalah cara untuk lebih mengoptimalkan build game yang dioptimalkan menggunakan informasi tentang cara game Anda berperilaku saat dimainkan di dunia nyata. Dengan cara ini, kode yang jarang dijalankan seperti error atau kasus ekstrem akan dikurangi dari jalur eksekusi penting kode Anda, sehingga akan mempercepatnya.

Diagram yang menunjukkan ringkasan visual tentang cara kerja
PGO

Gambar 1. Ringkasan cara kerja PGO.

Untuk menggunakan PGO, pertama-tama Anda harus melengkapi build untuk menghasilkan data profil yang dapat digunakan compiler. Kemudian, Anda menjalankan kode dengan menjalankan build tersebut dan membuat satu atau beberapa file data profil. Terakhir, salin kembali file tersebut dari perangkat dan gunakan dengan compiler untuk mengoptimalkan file yang dapat dieksekusi menggunakan informasi profil yang Anda ambil.

Cara kerja build yang dioptimalkan tanpa PGO

Build yang dioptimalkan tanpa menggunakan data profil menggunakan sejumlah heuristik saat memutuskan cara membuat kode yang dioptimalkan.

Beberapa di antaranya ditandai secara eksplisit oleh developer - misalnya, di C++ 20 atau yang lebih baru, dengan menggunakan petunjuk arah cabang seperti [[likely]] dan [[unlikely]]. Contoh lainnya adalah dengan menggunakan kata kunci inline, atau bahkan __forceinline (meskipun secara umum, akan lebih baik dan lebih fleksibel untuk tetap menggunakan yang pertama). Secara default, beberapa compiler menganggap segmen pertama cabang (yaitu pernyataan if, bukan bagian else) adalah yang paling mungkin. Pengoptimal juga dapat membuat asumsi dari analisis statis kode tentang bagaimana kode akan dieksekusi - tetapi biasanya cakupannya terbatas.

Heuristik ini memiliki masalah karena tidak dapat membantu compiler dengan benar dalam semua situasi - dengan markup manual yang lengkap sekalipun - sehingga meskipun kode yang dibuat biasanya dioptimalkan dengan baik, kode tersebut tidak sebaik jika compiler memiliki lebih banyak informasi tentang perilakunya saat runtime.

Membuat profil

Jika file yang dapat dieksekusi di-build dengan PGO yang diaktifkan dalam mode instrumentasi, file yang dapat dieksekusi akan ditambahkan dengan kode di awal setiap blok kode, – misalnya di awal fungsi, atau awal setiap segmen cabang. Kode ini digunakan untuk melacak jumlah setiap kali blok dimasukkan dengan menjalankan kode, yang nantinya dapat digunakan compiler untuk membuat kode yang dioptimalkan.

Beberapa pelacakan lainnya juga dilakukan – misalnya ukuran operasi penyalinan yang umum dalam satu blok, sehingga versi operasi yang cepat dan inline dapat dibuat nanti.

Setelah semacam pekerjaan representatif dilakukan oleh game, file yang dapat dieksekusi harus memanggil fungsi – __llvm_profile_write_file() – untuk menulis data profil ke lokasi yang dapat disesuaikan di perangkat. Fungsi ini akan ditautkan ke game secara otomatis saat konfigurasi build Anda telah mengaktifkan instrumentasi PGO.

File data profil tertulis tersebut kemudian harus disalin kembali ke komputer host, dan sebaiknya disimpan di lokasi bersama dengan profil lain dari build yang sama sehingga dapat digunakan bersama.

Misalnya, Anda dapat mengubah kode game untuk memanggil __llvm_profile_write_file() saat scene game saat ini berakhir. Kemudian, untuk membuat profil, build game dengan instrumentasi yang diaktifkan, lalu deploy ke perangkat Android Anda. Saat sedang berjalan, data profil akan otomatis direkam – engineer UM (Uji Mutu) Anda akan menjalankan game, menjalankan berbagai skenario (atau menjalankan pengujian yang biasa).

Setelah selesai menjalankan berbagai bagian game, Anda dapat kembali ke menu utama, yang akan mengakhiri scene game saat ini dan menulis data profil.

Skrip kemudian dapat digunakan untuk menyalin data profil dari perangkat pengujian dan menguploadnya ke repositori pusat, sehingga dapat diambil untuk digunakan nanti.

Menggabungkan data profil

Setelah profil diperoleh dari perangkat, profil tersebut harus dikonversi dari file data profil yang dihasilkan oleh build berinstrumen, menjadi bentuk yang dapat digunakan oleh compiler. AGDE melakukan hal ini secara otomatis, untuk file data profil apa pun yang Anda tambahkan ke project.

PGO dirancang untuk menggabungkan hasil dari beberapa profil berinstrumen yang dijalankan secara bersamaan – AGDE juga melakukannya secara otomatis jika Anda memiliki beberapa file dalam satu project.

Sebagai contoh bagaimana menggabungkan set data profil bisa berguna, anggaplah Anda memiliki lab yang penuh dengan engineer UM (Uji Mutu) yang semuanya memainkan berbagai level di game Anda. Setiap playthrough-nya dicatat, lalu digunakan untuk menghasilkan data profil dari build berinstrumen PGO dari game Anda. Penggabungan profil memungkinkan Anda menggabungkan hasil dari semua pengujian yang berbeda - yang dapat menjalankan bagian yang sangat berbeda dari kode Anda - untuk memberikan hasil yang lebih baik.

Lebih baik lagi, saat melakukan pengujian longitudinal, tempat Anda menyimpan salinan data profil dari rilis internal ke rilis internal, mem-build ulang tidak harus membatalkan validasi data profil lama. Untuk sebagian besar, kode relatif stabil dari rilis ke rilis, sehingga data profil dari build lama masih berguna dan tidak langsung usang.

Membuat build yang Dioptimalkan dan Dipandu Profil

Setelah menambahkan data profil ke project, Anda dapat menggunakannya untuk mem-build file yang dapat dieksekusi dengan mengaktifkan PGO dalam mode Pengoptimalan di konfigurasi build.

Hal ini mengarahkan pengoptimal compiler untuk menggunakan data profil yang Anda ambil sebelumnya saat membuat keputusan pengoptimalan.

Kapan harus menggunakan Pengoptimalan yang Dipandu Profil

PGO tidak dimaksudkan untuk menjadi sesuatu yang Anda aktifkan pada awal pengembangan, atau selama iterasi sehari-hari pada kode. Selama pengembangan, Anda harus berfokus pada pengoptimalan berbasis algoritma dan tata letak data karena keduanya akan memberikan manfaat yang jauh lebih besar.

PGO akan muncul nanti dalam proses pengembangan, saat Anda sedang memperbaiki aplikasi untuk dirilis. Anggap Pengoptimalan yang Dipandu Profil sebagai pelengkap yang memungkinkan Anda menyelipkan bagian terakhir performa dari kode setelah Anda menghabiskan beberapa waktu untuk mengoptimalkan kode sendiri.

Peningkatan performa yang diharapkan dengan PGO

Hal ini bergantung pada sejumlah besar faktor, termasuk seberapa komprehensif dan usang profil Anda, dan seberapa optimal kode Anda dengan build tradisional yang dioptimalkan.

Secara umum, perkiraan yang sangat konservatif adalah biaya CPU akan berkurang hingga ~5% di thread utama. Anda mungkin melihat hasil yang berbeda.

Overhead instrumentasi

Instrumentasi PGO bersifat komprehensif, dan meskipun dibuat secara otomatis, tetapi tidak gratis. Overhead instrumentasi PGO dapat bervariasi, bergantung pada codebase Anda.

Biaya performa Instrumentasi yang Dipandu Profil

Anda mungkin melihat penurunan kecepatan frame dengan build berinstrumen. Dalam beberapa kasus, tergantung pada berapa persen penggunaan CPU Anda selama operasi normal, penurunan ini mungkin begitu besar sehingga membuat gameplay normal menjadi sulit.

Sebaiknya sebagian besar developer mem-build mode replay semi-deterministik untuk game mereka. Fungsi semacam ini memberikan kemampuan bagi tim UM (Uji Mutu) Anda untuk memulai game di lokasi awal yang dapat diulang dan diketahui dalam game Anda (seperti game tersimpan atau level pengujian tertentu), lalu merekam input mereka. Input yang direkam dari build pengujian ini dapat dimasukkan ke dalam build Berinstrumen PGO, diputar kembali, dan menghasilkan data profil dunia nyata, terlepas dari waktu yang diperlukan untuk memproses masing-masing frame – meskipun game berjalan sangat lambat sehingga tidak bisa dimainkan.

Fungsi semacam ini juga memiliki manfaat utama lainnya, seperti menggandakan upaya penguji: satu penguji dapat merekam input mereka di perangkat, lalu dapat diputar kembali di berbagai jenis perangkat untuk tujuan pengujian asap.

Sistem replay seperti ini dapat memiliki manfaat besar di Android karena ada banyak varian perangkat dalam ekosistem – dan manfaatnya tidak berhenti di situ: Sistem juga dapat membentuk bagian inti dari sistem build continuous integration Anda, sehingga Anda dapat melakukan regresi performa semalam dan uji asap seperti biasa.

Rekaman harus mencatat input pengguna pada titik yang paling sesuai dalam mekanisme input game Anda (mungkin bukan peristiwa layar sentuh langsung, tetapi merekam konsekuensi sebagai perintah). Input ini juga harus menampilkan jumlah frame yang berdetik secara monoton selama gameplay, sehingga selama pemutaran, mekanisme replay dapat menunggu frame yang sesuai untuk memicu peristiwa.

Dalam mode pemutaran, game Anda harus menghindari login online, tidak boleh menampilkan iklan, dan harus beroperasi pada interval waktu yang tetap (pada kecepatan frame target Anda). Sebaiknya Anda menonaktifkan vsync.

Tidak harus semua hal (misalnya sistem partikel) dalam game Anda dapat diulang dengan sempurna, tetapi tindakan yang sama harus memberikan konsekuensi dan hasil yang sama dalam game, yang berarti bahwa gameplay harus sama.

Biaya memori Instrumentasi yang Dipandu Profil

Overhead memori instrumentasi PGO sangat bervariasi berdasarkan library tertentu yang dikompilasi. Dalam pengujian, kami melihat peningkatan secara keseluruhan dari ukuran file pengujian yang dapat dieksekusi sebesar ~2,2x. Peningkatan ukuran ini mencakup kode tambahan yang diperlukan untuk melengkapi blok kode, dan ruang yang diperlukan untuk menyimpan penghitung. Pengujian ini tidak menyeluruh, dan pengalaman Anda mungkin berbeda.

Kapan harus memperbarui atau menghapus data profil

Anda harus memperbarui profil setiap kali membuat perubahan besar pada kode (atau konten game).

Cakupannya bergantung pada lingkungan build dan tahap pengembangan Anda.

Seperti telah disebutkan sebelumnya, Anda tidak boleh membawa data profil ke seluruh perubahan besar pada lingkungan build. Meskipun hal ini tidak akan mencegah Anda mem-build atau merusak build, hal ini akan mengurangi manfaat performa dari penggunaan PGO karena sangat sedikit data profil yang akan berlaku untuk lingkungan build baru. Namun, ini bukanlah satu-satunya kasus saat data profil Anda menjadi usang.

Mari kita mulai dengan asumsi bahwa Anda tidak akan menggunakan PGO sampai mendekati akhir pengembangan, saat Anda bersiap untuk merilis, selain mungkin mengumpulkan rekaman mingguan, sehingga engineer yang berfokus pada performa dapat memastikan bahwa tidak akan ada gangguan yang tidak terduga saat mendekati waktu perilisan.

Hal ini akan berubah saat Anda mendekati periode rilis, ketika tim UM (Uji Mutu) melakukan pengujian setiap hari, dan menjalankan game secara menyeluruh. Selama fase ini, Anda dapat membuat profil dari data tersebut setiap hari, dan menggunakannya untuk menginformasikan build mendatang untuk pengujian performa dan menyesuaikan anggaran performa Anda sendiri.

Saat bersiap untuk rilis, Anda harus mengunci versi build yang direncanakan untuk dirilis, lalu menjalankan UM (Uji Mutu) untuk menghasilkan data profil baru. Selanjutnya, build menggunakan data ini untuk membuat versi final dari file yang dapat dieksekusi.

UM (Uji Mutu) kemudian dapat menjalankan build pengiriman yang dioptimalkan ini untuk terakhir kalinya guna memastikannya siap dirilis.