Bazel bersifat kompleks dan melakukan banyak hal berbeda selama proses build, beberapa di antaranya dapat memengaruhi performa build. Halaman ini mencoba memetakan beberapa konsep Bazel ini dengan implikasinya terhadap performa build. Meskipun tidak terlalu banyak, kami telah menyertakan beberapa contoh cara mendeteksi masalah performa build melalui ekstraksi metrik dan tindakan yang dapat Anda lakukan untuk memperbaikinya. Dengan ini, kami berharap Anda dapat menerapkan konsep ini saat menyelidiki regresi performa build.
Build bersih vs. Inkremental
Build bersih adalah build yang membangun semuanya dari awal, sedangkan build inkremental menggunakan kembali beberapa pekerjaan yang sudah selesai.
Sebaiknya lihat build bersih dan inkremental secara terpisah, terutama saat Anda mengumpulkan / menggabungkan metrik yang bergantung pada status cache Bazel (misalnya, metrik ukuran permintaan build). Keduanya juga merepresentasikan dua pengalaman pengguna yang berbeda. Dibandingkan dengan memulai build bersih dari awal (yang membutuhkan waktu lebih lama karena cache dingin), build inkremental terjadi jauh lebih sering saat developer melakukan iterasi pada kode (biasanya lebih cepat karena cache biasanya sudah hangat).
Anda dapat menggunakan kolom CumulativeMetrics.num_analyses
di BEP untuk mengklasifikasikan
build. Jika num_analyses <= 1
, ini adalah build bersih; jika tidak, kita dapat mengategorikannya secara luas sebagai kemungkinan build inkremental - pengguna dapat beralih ke flag atau target yang berbeda sehingga menyebabkan build yang efektif bersih. Definisi inkrementalitas yang lebih ketat kemungkinan harus berbentuk heuristik, misalnya melihat jumlah paket yang dimuat (PackageMetrics.packages_loaded
).
Metrik build deterministik sebagai pengganti performa build
Mengukur performa build bisa jadi sulit karena sifat non-deterministik dari metrik tertentu (misalnya, waktu CPU Bazel atau waktu antrean di cluster jarak jauh). Oleh karena itu, sebaiknya gunakan metrik deterministik sebagai pengganti jumlah pekerjaan yang dilakukan oleh Bazel, yang pada gilirannya memengaruhi performanya.
Ukuran permintaan build dapat memiliki implikasi yang signifikan pada performa build. Build yang lebih besar dapat menunjukkan 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 kompleksitasnya meningkat dan biaya build-nya menjadi lebih mahal.
Kita dapat memecah masalah ini ke dalam berbagai fase build, dan menggunakan metrik berikut sebagai metrik proxy untuk pekerjaan yang dilakukan di setiap fase:
PackageMetrics.packages_loaded
: jumlah paket yang berhasil dimuat. Regresi di sini menunjukkan 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 membangun dan melintasi grafik target yang dikonfigurasi.- Hal ini sering terjadi karena penambahan dependensi dan harus membuat grafik penutupan transitifnya.
- Gunakan cquery untuk menemukan tempat dependensi baru mungkin telah ditambahkan.
ActionSummary.actions_created
: merepresentasikan tindakan yang dibuat dalam build, dan regresi merepresentasikan lebih banyak pekerjaan dalam membuat grafik tindakan. Perhatikan bahwa hal ini juga mencakup tindakan yang tidak digunakan yang mungkin belum dieksekusi.- Gunakan aquery untuk men-debug regresi;
sebaiknya mulai dengan
--output=summary
sebelum menelusuri lebih lanjut dengan--skyframe_state
.
- Gunakan aquery untuk men-debug regresi;
sebaiknya mulai dengan
ActionSummary.actions_executed
: jumlah tindakan yang dijalankan, regresi secara langsung menunjukkan lebih banyak pekerjaan dalam menjalankan tindakan ini.- BEP menulis statistik tindakan
ActionData
yang menunjukkan jenis tindakan yang paling sering dilakukan. Secara default, plugin 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 dijalankan. - Hal ini akan membantu Anda mengetahui jenis tindakan yang telah dilakukan (selain itu).
- BEP menulis statistik tindakan
BuildGraphSummary.outputArtifactCount
: jumlah artefak yang dibuat oleh tindakan yang dijalankan.- Jika jumlah tindakan yang dijalankan tidak meningkat, kemungkinan implementasi aturan telah diubah.
Semua metrik ini dipengaruhi oleh status cache lokal, sehingga Anda harus memastikan bahwa build tempat Anda mengekstrak metrik ini adalah build bersih.
Kami telah mencatat bahwa regresi dalam salah satu metrik ini dapat disertai dengan regresi dalam waktu nyata, waktu CPU, dan penggunaan memori.
Penggunaan resource lokal
Bazel menggunakan berbagai resource di mesin lokal Anda (baik untuk menganalisis grafik build dan mendorong eksekusi, maupun untuk menjalankan tindakan lokal). Hal ini dapat memengaruhi performa / ketersediaan mesin Anda dalam melakukan build, dan juga tugas lainnya.
Waktu yang dihabiskan
Mungkin metrik yang paling rentan terhadap derau (dan dapat sangat bervariasi dari build ke build) adalah waktu; khususnya - waktu nyata, 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 signifikansi statistik pengukuran Anda.
Waktu dinding adalah waktu yang berlalu di dunia nyata.
- Jika waktu dinding saja mengalami regresi, 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 dinding.
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 sebagian besar pekerjaan berat CPU dilakukan di sana.
- 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 di kernel.
- Jika waktu sistem mengalami regresi, hal ini sebagian besar berkorelasi dengan I/O saat Bazel membaca file dari sistem file Anda.
Pembuatan profil beban di seluruh sistem
Dengan menggunakan flag
--experimental_collect_load_average_in_profiler
yang diperkenalkan di Bazel 6.0, pemrofilan rekaman aktivitas JSON mengumpulkan
rata-rata beban sistem selama pemanggilan.
Gambar 1. Profil yang mencakup rata-rata beban sistem.
Beban tinggi selama pemanggilan Bazel dapat menjadi indikasi bahwa Bazel menjadwalkan terlalu banyak tindakan lokal secara paralel untuk mesin Anda. Anda mungkin perlu mempelajari cara menyesuaikan --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, info
Bazel dan
BEP.
bazel info used-heap-size-after-gc
: Jumlah memori yang digunakan dalam byte setelah panggilan keSystem.gc()
.- Bazel bench 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.
BEP’s
MemoryMetrics.peak_post_gc_heap_size
: Ukuran heap JVM puncak dalam byte setelah GC (memerlukan setelan--memory_profile
yang mencoba memaksakan GC penuh).
Regresi dalam penggunaan memori biasanya merupakan akibat dari regresi dalam metrik ukuran permintaan build, yang sering kali disebabkan oleh penambahan dependensi atau perubahan dalam penerapan aturan.
Untuk menganalisis jejak memori Bazel pada tingkat yang lebih terperinci, sebaiknya gunakan profiler memori bawaan untuk aturan.
Pembuatan profil memori pekerja persisten
Meskipun pekerja persisten dapat membantu mempercepat build
secara signifikan (terutama untuk bahasa yang diinterpretasikan), jejak memori mereka dapat
menjadi masalah. Bazel mengumpulkan metrik pada pekerja, khususnya, kolom
WorkerMetrics.WorkerStats.worker_memory_in_kb
memberi tahu jumlah memori yang digunakan pekerja (berdasarkan mnemonik).
Profiler rekaman aktivitas JSON juga mengumpulkan penggunaan memori pekerja persisten selama pemanggilan dengan meneruskan tanda --experimental_collect_system_network_usage
(baru di Bazel 6.0).
Gambar 2. Profil yang mencakup penggunaan memori pekerja.
Menurunkan nilai
--worker_max_instances
(default 4) dapat membantu mengurangi
jumlah memori yang digunakan oleh pekerja persisten. Kami sedang berupaya secara aktif untuk membuat pengelola resource dan penjadwal Bazel lebih cerdas sehingga penyesuaian seperti ini akan lebih jarang diperlukan pada masa mendatang.
Memantau traffic jaringan untuk build jarak jauh
Dalam eksekusi jarak jauh, Bazel mendownload artefak yang dibuat sebagai hasil dari mengeksekusi tindakan. Dengan demikian, bandwidth jaringan Anda dapat memengaruhi performa build Anda.
Jika Anda menggunakan eksekusi jarak jauh untuk build, sebaiknya pertimbangkan untuk memantau 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 di seluruh sistem selama proses build
dengan meneruskan tanda --experimental_collect_system_network_usage
(baru di Bazel
6.0).
Gambar 3. Profil yang mencakup penggunaan jaringan di seluruh sistem.
Penggunaan jaringan yang tinggi tetapi cukup datar saat menggunakan eksekusi jarak jauh dapat menunjukkan bahwa jaringan adalah hambatan dalam build Anda; jika Anda belum menggunakannya, pertimbangkan untuk mengaktifkan Build tanpa Byte dengan meneruskan --remote_download_minimal
.
Tindakan ini akan mempercepat build Anda dengan menghindari download artefak perantara yang tidak perlu.
Opsi lainnya adalah mengonfigurasi cache disk lokal untuk menghemat bandwidth download.