Bazel bersifat kompleks dan melakukan berbagai hal selama proses build, yang beberapa di antaranya dapat berdampak pada performa build. Halaman ini mencoba memetakan beberapa konsep Bazel ini ke implikasinya pada performa build. Meskipun tidak lengkap, kami telah menyertakan beberapa contoh cara mendeteksi masalah performa build melalui pengekstrakan metrik dan tindakan yang dapat Anda lakukan untuk memperbaikinya. Dengan demikian, kami harap Anda dapat menerapkan konsep ini saat menyelidiki regresi performa build.
Build Clean vs. Inkremental
Clean build 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 ). Metrik ini juga mewakili dua pengalaman pengguna yang berbeda. Dibandingkan dengan memulai build bersih dari awal (yang memerlukan waktu lebih lama karena cache yang dingin), 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 mengklasifikasikan
build. Jika num_analyses <= 1
, merupakan build bersih; jika tidak, kita dapat
mengategorikannya secara luas sebagai kemungkinan build inkremental - pengguna dapat beralih
ke flag lain atau target yang berbeda sehingga menghasilkan clean build yang efektif. Definisi inkrementalitas yang lebih ketat kemungkinan harus berupa heuristik, misalnya jumlah paket yang dimuat (PackageMetrics.packages_loaded
).
Metrik build yang determenistik sebagai proxy untuk performa build
Mengukur performa build bisa jadi sulit karena sifat metrik tertentu yang tidak menentukan (misalnya waktu CPU atau waktu antrean Bazel pada cluster jarak jauh). Oleh karena itu, sebaiknya gunakan metrik determenistik sebagai proxy untuk jumlah pekerjaan yang dilakukan Bazel, yang pada akhirnya akan 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, seiring dengan bertambahnya dependensi yang ditambahkan/dibuat, sehingga menimbulkan kompleksitas dan biaya build yang semakin mahal.
Kita dapat membagi 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 menunjukkan lebih banyak pekerjaan dalam membangun dan menjelajahi grafik target yang dikonfigurasi.- Hal ini sering kali disebabkan oleh penambahan dependensi dan keharusan untuk membuat grafik penutupan transitifnya.
- Gunakan cquery untuk menemukan kemungkinan tempat dependensi baru telah ditambahkan.
ActionSummary.actions_created
: merepresentasikan tindakan yang dibuat dalam build, dan regresi mewakili lebih banyak pekerjaan dalam menyusun grafik tindakan. Perlu diperhatikan bahwa hal ini juga mencakup tindakan yang tidak digunakan yang mungkin belum dijalankan.- Gunakan kueri untuk men-debug regresi;
sebaiknya mulai dengan
--output=summary
sebelum melihat perincian lebih lanjut dengan--skyframe_state
.
- Gunakan kueri 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 sering dijalankan. Secara default, model ini mengumpulkan 20 jenis tindakan teratas, tetapi Anda dapat meneruskan--experimental_record_metrics_for_all_mnemonics
untuk mengumpulkan data ini bagi semua jenis tindakan yang dijalankan. - Hal ini akan membantu Anda mengetahui jenis tindakan yang dilakukan (selain itu).
- BEP menulis statistik tindakan
BuildGraphSummary.outputArtifactCount
: jumlah artefak yang dibuat oleh tindakan yang dijalankan.- Jika jumlah tindakan yang dijalankan tidak meningkat, ada kemungkinan bahwa penerapan aturan telah diubah.
Semua metrik ini dipengaruhi oleh status cache lokal. Oleh karena itu, sebaiknya pastikan bahwa build yang Anda ekstrak metrik ini adalah build bersih.
Kami telah mengamati 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 di komputer lokal Anda (baik untuk menganalisis grafik build dan mendorong eksekusi, maupun untuk menjalankan tindakan lokal), hal ini dapat memengaruhi performa / ketersediaan mesin Anda dalam menjalankan build, serta tugas lainnya.
Waktu yang dihabiskan
Mungkin metrik yang paling rentan terhadap derau (dan bisa sangat bervariasi dari build
ke build) adalah waktu; khususnya - waktu dinding, waktu CPU, dan waktu sistem. Anda dapat menggunakan bazel-bench untuk mendapatkan tolok ukur bagi metrik ini, dan dengan jumlah --runs
yang memadai, Anda dapat meningkatkan signifikansi statistik pengukuran.
Waktu dinding adalah waktu dunia nyata yang telah berlalu.
- Jika hanya waktu dinding mengalami regresi, sebaiknya kumpulkan profil rekaman aktivitas JSON dan cari perbedaannya. Jika tidak, investigasi metrik lain yang mengalami regresi akan lebih efisien karena dapat memengaruhi waktu pemrosesan.
Waktu CPU adalah waktu yang dihabiskan oleh CPU untuk mengeksekusi kode pengguna.
- Jika waktu CPU menurun di dua commit project, sebaiknya kumpulkan
profil CPU Starlark. Anda mungkin juga harus menggunakan
--nobuild
untuk membatasi build ke fase analisis, karena di situlah sebagian besar tugas berat CPU diselesaikan.
- Jika waktu CPU menurun di dua commit project, sebaiknya kumpulkan
profil CPU Starlark. Anda mungkin juga harus menggunakan
Waktu sistem adalah waktu yang dihabiskan oleh CPU dalam {i>kernel<i}.
- Jika waktu sistem mengalami regresi, hal ini 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 rekaman aktivitas JSON mengumpulkan
rata-rata beban sistem selama pemanggilan.
Gambar 1. Profil yang mencakup rata-rata beban sistem.
Beban yang tinggi selama pemanggilan Bazel dapat menjadi indikasi bahwa Bazel menjadwalkan terlalu banyak tindakan lokal secara paralel untuk komputer Anda. Sebaiknya Anda mencoba
menyesuaikan
--local_cpu_resources
dan --local_ram_resources
,
terutama di lingkungan container (setidaknya hingga
#16512 digabungkan).
Memantau penggunaan memori Bazel
Ada dua sumber utama untuk mengetahui penggunaan memori Bazel, yaitu Bazel info
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.
MemoryMetrics.peak_post_gc_heap_size
BEP: Ukuran heap JVM puncak dalam byte setelah GC (memerlukan setelan--memory_profile
yang mencoba memaksa 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 implementasi aturan.
Untuk menganalisis jejak memori Bazel pada level yang lebih terperinci, sebaiknya gunakan memory profiler bawaan untuk aturan.
Pembuatan profil memori pekerja persisten
Meskipun pekerja persisten dapat membantu mempercepat build secara signifikan (terutama untuk bahasa pemrograman tafsiran), jejak memorinya dapat menimbulkan masalah. Bazel mengumpulkan metrik pada pekerjanya, khususnya, kolom WorkerMetrics.WorkerStats.worker_memory_in_kb
memberi tahu berapa banyak memori yang digunakan pekerja memori (secara mnemonik).
Profiler rekaman aktivitas JSON juga
mengumpulkan penggunaan memori pekerja persisten selama panggilan dengan meneruskan
tanda --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 secara aktif berupaya
membuat resource manager dan penjadwal Bazel menjadi lebih cerdas, sehingga penyesuaian tersebut
akan lebih jarang diperlukan di masa mendatang.
Memantau traffic jaringan untuk build jarak jauh
Dalam eksekusi jarak jauh, Bazel mendownload artefak yang dibangun sebagai hasil dari tindakan eksekusi. Dengan demikian, bandwidth jaringan Anda dapat memengaruhi performa build.
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 seluruh sistem selama proses build
dengan meneruskan flag --experimental_collect_system_network_usage
(baru di Bazel
6.0).
Gambar 3. Profil yang mencakup penggunaan jaringan seluruh sistem.
Penggunaan jaringan yang tinggi tetapi agak datar saat menggunakan eksekusi jarak jauh dapat menunjukkan
bahwa jaringan merupakan bottleneck dalam build Anda; jika Anda belum menggunakannya,
pertimbangkan untuk mengaktifkan Build tanpa Byte dengan meneruskan
--remote_download_minimal
.
Tindakan ini akan mempercepat build dengan menghindari download artefak perantara yang tidak perlu.
Pilihan lainnya adalah mengonfigurasi cache disk lokal untuk menghemat bandwidth download.