Bazel bersifat kompleks dan melakukan banyak hal yang berbeda selama proses build, yang sebagian di antaranya dapat memengaruhi performa build. Halaman ini mencoba memetakan beberapa konsep Bazel ini ke implikasinya pada performa build. Meskipun tidak luas, kami telah menyertakan beberapa contoh cara mendeteksi masalah performa build melalui mengekstrak metrik dan yang dapat Anda lakukan untuk memperbaikinya. Dengan begitu, kami harap Anda dapat menerapkan konsep ini saat menyelidiki regresi performa build.
Build Bersih vs Inkremental
Build bersih adalah build yang membuat semuanya dari awal, sedangkan build inkremental menggunakan kembali beberapa pekerjaan yang sudah selesai.
Sebaiknya lihat build bersih dan inkremental secara terpisah, terutama jika Anda mengumpulkan / menggabungkan metrik yang bergantung pada status cache Bazel (misalnya, metrik ukuran permintaan build ). Build ini juga mewakili dua pengalaman pengguna yang berbeda. Dibandingkan dengan memulai build bersih dari awal (yang memerlukan waktu lebih lama karena cold cache), build inkremental terjadi jauh lebih sering saat developer melakukan iterasi kode (biasanya lebih cepat karena cache biasanya sudah hangat).
Anda dapat menggunakan kolom CumulativeMetrics.num_analyses
di BEP untuk mengklasifikasi
build. Jika num_analyses <= 1
adalah build yang bersih; jika tidak, kami dapat mengategorikannya secara luas
sebagai kemungkinan build inkremental - pengguna mungkin beralih
ke flag yang berbeda atau target yang berbeda yang menyebabkan build yang bersih secara efektif. Definisi
inkremental yang lebih ketat kemungkinan harus hadir dalam bentuk
heuristik, misalnya melihat jumlah paket yang dimuat
(PackageMetrics.packages_loaded
).
Metrik build deterministik sebagai proxy untuk performa build
Mengukur performa build dapat menjadi sulit karena sifat non-deterministik dari metrik tertentu (misalnya waktu CPU atau waktu antrean Bazel pada cluster jarak jauh). Dengan demikian, sebaiknya gunakan metrik deterministik sebagai proxy untuk jumlah pekerjaan yang dilakukan oleh Bazel, yang pada akhirnya memengaruhi performanya.
Ukuran permintaan build dapat memiliki implikasi yang signifikan terhadap performa build. Build yang lebih besar dapat mewakili lebih banyak pekerjaan dalam menganalisis dan membuat grafik build. Pertumbuhan organik build terjadi secara alami dengan pengembangan, karena semakin banyak dependensi yang ditambahkan/dibuat, sehingga semakin kompleks dan menjadi lebih mahal untuk di-build.
Kita dapat membagi masalah ini menjadi berbagai fase build, dan menggunakan metrik berikut sebagai metrik proxy untuk pekerjaan yang dilakukan pada setiap fase:
PackageMetrics.packages_loaded
: jumlah paket yang berhasil dimuat. Regresi di sini mewakili lebih banyak pekerjaan yang perlu dilakukan untuk membaca dan mengurai setiap file BUILD tambahan dalam fase pemuatan.TargetMetrics.targets_configured
: mewakili jumlah target dan aspek yang dikonfigurasi dalam build. Regresi mewakili lebih banyak pekerjaan dalam membuat dan melintasi grafik target yang dikonfigurasi.- Hal ini sering kali disebabkan oleh penambahan dependensi dan harus membuat grafik penutupan transitifnya.
- Gunakan cquery untuk menemukan tempat dependensi baru mungkin telah ditambahkan.
ActionSummary.actions_created
: mewakili tindakan yang dibuat dalam build, dan regresi mewakili lebih banyak pekerjaan dalam membuat grafik tindakan. Perhatikan bahwa hal ini juga mencakup tindakan tidak digunakan yang mungkin belum dieksekusi.- Gunakan aquery untuk men-debug regresi;
sebaiknya mulai dengan
--output=summary
sebelum melihat lebih lanjut dengan--skyframe_state
.
- Gunakan aquery untuk men-debug regresi;
sebaiknya mulai dengan
ActionSummary.actions_executed
: jumlah tindakan yang dieksekusi, regresi secara langsung mewakili lebih banyak pekerjaan dalam menjalankan tindakan ini.- BEP menulis statistik tindakan
ActionData
yang menunjukkan jenis tindakan yang paling banyak dijalankan. Secara default, class ini mengumpulkan 20 jenis tindakan teratas, tetapi Anda dapat meneruskan--experimental_record_metrics_for_all_mnemonics
untuk mengumpulkan data ini untuk semua jenis tindakan yang dieksekusi. - Hal ini akan membantu Anda mengetahui jenis tindakan yang dijalankan (sebagai tambahan).
- BEP menulis statistik tindakan
BuildGraphSummary.outputArtifactCount
: jumlah artefak yang dibuat oleh tindakan yang dieksekusi.- Jika jumlah tindakan yang dieksekusi tidak meningkat, kemungkinan implementasi aturan telah diubah.
Metrik ini dipengaruhi oleh status cache lokal, sehingga Anda harus memastikan bahwa build yang Anda ekstrak metriknya adalah build bersih.
Kami telah mencatat bahwa regresi dalam salah satu metrik ini dapat disertai dengan regresi dalam waktu proses, waktu cpu, dan penggunaan memori.
Penggunaan resource lokal
Bazel menggunakan berbagai resource pada mesin lokal Anda (untuk menganalisis grafik build dan mendorong eksekusi, serta untuk menjalankan tindakan lokal), hal ini dapat memengaruhi performa / ketersediaan mesin Anda dalam menjalankan build, dan juga tugas-tugas lainnya.
Waktu yang dihabiskan
Mungkin metrik yang paling rentan terhadap derau (dan dapat sangat bervariasi dari build ke build) adalah waktu; khususnya - waktu proses, waktu cpu, dan waktu sistem. Anda dapat menggunakan bazel-bench untuk mendapatkan tolok ukur untuk metrik ini, dan dengan jumlah --runs
yang memadai, Anda dapat meningkatkan data statistik yang signifikan dari pengukuran Anda.
Waktu dinding adalah waktu sesungguhnya yang berlalu.
- Jika hanya mengalami regresi waktu proses, sebaiknya kumpulkan profil rekaman aktivitas JSON dan cari perbedaannya. Jika tidak, akan lebih efisien untuk menyelidiki metrik yang mengalami regresi lainnya karena dapat memengaruhi waktu aktivitas.
Waktu CPU adalah waktu yang dihabiskan oleh CPU untuk mengeksekusi kode pengguna.
- Jika waktu CPU mengalami regresi di dua commit project, sebaiknya kumpulkan
profil CPU Starlark. Anda mungkin juga harus menggunakan
--nobuild
untuk membatasi build ke fase analisis karena di sinilah sebagian besar pekerjaan berat CPU dilakukan.
- Jika waktu CPU mengalami regresi di dua commit project, sebaiknya kumpulkan
profil CPU Starlark. Anda mungkin juga harus menggunakan
Waktu sistem adalah waktu yang dihabiskan oleh CPU dalam kernel.
- Jika waktu sistem menurun, sebagian besar berkorelasi dengan I/O saat Bazel membaca file dari sistem file Anda.
Pembuatan profil pemuatan seluruh sistem
Dengan menggunakan flag --experimental_collect_load_average_in_profiler
yang diperkenalkan di Bazel 6.0, profiler trace JSON mengumpulkan rata-rata beban sistem selama pemanggilan.
Gambar 1. Profil yang menyertakan rata-rata beban sistem.
Beban yang tinggi selama pemanggilan Bazel dapat menjadi indikasi bahwa Bazel menjadwalkan
terlalu banyak tindakan lokal untuk mesin Anda secara paralel. Anda mungkin ingin melihat
penyesuaian
--local_cpu_resources
dan --local_ram_resources
,
terutama di lingkungan penampung (setidaknya hingga
#16512 digabungkan).
Memantau penggunaan memori Bazel
Ada dua sumber utama untuk mendapatkan penggunaan memori Bazel, Bazel info
dan
BEP.
bazel info used-heap-size-after-gc
: Jumlah memori yang digunakan dalam byte setelah panggilan keSystem.gc()
.- Bachch Bazel juga memberikan tolok ukur untuk metrik ini.
- Selain itu, ada
peak-heap-size
,max-heap-size
,used-heap-size
, dancommitted-heap-size
(lihat dokumentasi), tetapi kurang relevan.
MemoryMetrics.peak_post_gc_heap_size
BEP: Ukuran ukuran heap JVM puncak dalam byte setelah GC (memerlukan setelan--memory_profile
yang mencoba memaksakan GC penuh).
Regresi dalam penggunaan memori biasanya disebabkan oleh regresi dalam metrik ukuran permintaan build, yang sering kali disebabkan oleh penambahan dependensi atau perubahan dalam penerapan aturan.
Untuk menganalisis jejak memori Bazel pada level yang lebih terperinci, sebaiknya gunakan profiler memori bawaan untuk aturan.
Membuat profil memori pekerja persisten
Meskipun pekerja persisten dapat membantu mempercepat build
secara signifikan (terutama untuk bahasa yang ditafsirkan), jejak memori mereka
dapat bermasalah. Bazel mengumpulkan metrik tentang pekerjanya, khususnya, kolom WorkerMetrics.WorkerStats.worker_memory_in_kb
memberi tahu berapa banyak memori yang digunakan pekerja (berdasarkan mnemonik).
Profiler rekaman aktivitas JSON juga
mengumpulkan penggunaan memori pekerja persisten selama pemanggilan dengan meneruskan flag
--experimental_collect_system_network_usage
(baru di Bazel 6.0).
Gambar 2. Profil yang menyertakan penggunaan memori pekerja.
Menurunkan nilai
--worker_max_instances
(default 4) dapat membantu mengurangi
jumlah memori yang digunakan oleh pekerja persisten. Kami berupaya secara aktif untuk
membuat pengelola dan penjadwal resource Bazel menjadi lebih cerdas, sehingga penyesuaian tersebut
akan jarang dilakukan di masa mendatang.
Memantau traffic jaringan untuk build jarak jauh
Dalam eksekusi jarak jauh, Bazel mendownload artefak yang dibuat sebagai hasil dari tindakan eksekusi. Dengan demikian, bandwidth jaringan Anda dapat memengaruhi performa build.
Jika menggunakan eksekusi jarak jauh untuk build, Anda mungkin ingin mempertimbangkan
pemantauan traffic jaringan selama pemanggilan menggunakan
proto NetworkMetrics.SystemNetworkStats
dari BEP
(memerlukan penerusan --experimental_collect_system_network_usage
).
Selain itu, profil rekaman aktivitas JSON memungkinkan Anda melihat penggunaan jaringan untuk seluruh sistem selama proses build dengan meneruskan flag --experimental_collect_system_network_usage
(baru di Bazel 6.0).
Gambar 3. Profil yang menyertakan penggunaan jaringan tingkat sistem.
Penggunaan jaringan yang tinggi tetapi agak datar saat menggunakan eksekusi jarak jauh mungkin menunjukkan
bahwa jaringan merupakan bottleneck dalam build Anda; jika Anda belum menggunakannya,
pertimbangkan untuk mengaktifkan Build tanpa Byte dengan meneruskan
--remote_download_minimal
.
Hal ini akan mempercepat build dengan menghindari download artefak perantara yang tidak perlu.
Opsi lainnya adalah mengonfigurasi cache disk lokal untuk menghemat bandwidth download.