Mengelompokkan performa build

Laporkan masalah Lihat sumber Per malam · 7,2 · 7,1 · 7,0 · 6,5 · 6,4

Bazel cukup rumit dan melakukan banyak hal yang berbeda selama proses build, yang beberapa di antaranya dapat berdampak pada performa build. Halaman ini mencoba memetakan beberapa konsep Bazel ini hingga implikasinya pada performa build. Meskipun tidak luas, kami telah menyertakan beberapa contoh cara mendeteksi performa build masalah melalui mengekstrak metrik dan apa yang dapat Anda lakukan untuk memperbaikinya. Dengan ini, kami harap Anda dapat menerapkan konsep ini saat menyelidiki regresi performa build.

Build Clean vs. Inkremental

Build yang bersih adalah build yang membangun semuanya dari awal, sedangkan menggunakan kembali beberapa pekerjaan yang sudah selesai.

Sebaiknya lihat clean dan inkremental build secara terpisah, terutama saat Anda mengumpulkan / menggabungkan metrik yang bergantung pada status Cache Bazel (misalnya metrik ukuran permintaan build ). Keduanya juga mewakili dua pengalaman pengguna yang berbeda. Dibandingkan dengan memulai build bersih dari awal (yang membutuhkan waktu lebih lama karena cold cache), inkremental build terjadi jauh lebih sering ketika developer melakukan iterasi pada kode (biasanya lebih cepat karena cache biasanya sudah warm).

Anda dapat menggunakan kolom CumulativeMetrics.num_analyses di BEP untuk mengklasifikasikan build yang berbeda. Jika num_analyses <= 1, maka merupakan build bersih; jika tidak, kita bisa secara luas mengategorikannya agar mungkin menjadi build inkremental - pengguna bisa saja beralih ke penanda yang berbeda atau target yang berbeda, yang menyebabkan build bersih secara efektif. Apa saja definisi inkrementalitas yang lebih ketat mungkin harus dalam bentuk bersifat heuristik, misalnya melihat jumlah paket yang dimuat (PackageMetrics.packages_loaded).

Metrik build yang determenistik sebagai proxy untuk performa build

Mengukur performa build bisa jadi sulit karena sifat yang tidak deterministik metrik tertentu (misalnya waktu CPU Bazel atau waktu antrean pada remote ). Dengan demikian, ada baiknya menggunakan metrik deterministik sebagai {i>proxy<i} untuk jumlah pekerjaan yang dilakukan oleh Bazel, yang pada gilirannya akan mempengaruhi kinerjanya.

Ukuran permintaan build dapat memiliki implikasi yang signifikan pada build tingkat tinggi. Versi yang lebih besar dapat mewakili lebih banyak pekerjaan dalam menganalisis dan dengan membangun grafik build. Pertumbuhan organik build terjadi secara alami dengan semakin banyak dependensi yang ditambahkan/dibuat, sehingga semakin kompleks dan biaya pembuatannya menjadi lebih mahal.

Kita dapat membagi masalah ini ke dalam berbagai fase build, dan menggunakan hal berikut metrik sebagai metrik proxy untuk pekerjaan yang dilakukan di setiap fase:

  1. 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.

    • Hal ini sering disebabkan oleh penambahan dependensi dan keharusan untuk memuat penutupan transitif.
    • Gunakan query / cquery untuk menemukan di mana dependensi baru mungkin telah ditambahkan.
  2. TargetMetrics.targets_configured: mewakili jumlah target dan aspek yang dikonfigurasi dalam build. Regresi menunjukkan lebih banyak pekerjaan di membangun dan menelusuri grafik target yang telah dikonfigurasi.

    • Hal ini sering disebabkan oleh penambahan dependensi dan harus membangun grafik penutupan transitifnya.
    • Gunakan cquery untuk menemukan tempat baru dependensi mungkin telah ditambahkan.
  3. ActionSummary.actions_created: mewakili tindakan yang dibuat dalam build, dan regresi menunjukkan lebih banyak pekerjaan dalam menyusun grafik tindakan. Catatan bahwa hal ini juga mencakup tindakan yang tidak terpakai yang mungkin belum dijalankan.

  4. ActionSummary.actions_executed: jumlah tindakan yang dijalankan, 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 {i>default<i}, 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.
    • Ini akan membantu Anda mengetahui jenis tindakan apa yang telah dilakukan (sebagai tambahan).
  5. BuildGraphSummary.outputArtifactCount: jumlah artefak yang dibuat oleh tindakan yang dijalankan.

    • Jika jumlah tindakan yang dijalankan tidak meningkat, maka ada kemungkinan implementasi aturan diubah.

Semua metrik ini dipengaruhi oleh status cache lokal, sehingga Anda akan ingin memastikan bahwa build yang Anda ekstrak metrik ini berasal clean build.

Kami telah menemukan bahwa regresi dalam metrik ini dapat disertai dengan regresi waktu proses, waktu CPU, dan penggunaan memori.

Penggunaan resource lokal

Bazel menggunakan berbagai sumber daya pada komputer lokal Anda (baik untuk menganalisis grafik build dan mendorong eksekusi, dan untuk menjalankan tindakan lokal), dapat mempengaruhi kinerja / ketersediaan komputer Anda dalam melakukan dibangun, dan juga tugas-tugas lainnya.

Waktu yang dihabiskan

Mungkin metrik yang paling rentan terhadap derau (dan bisa sangat bervariasi dari dibangun) adalah waktu; khususnya - waktu dinding, waktu {i>cpu<i}, dan waktu sistem. Anda dapat gunakan bazel-bench untuk mendapatkan tolok ukur untuk 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 melihat untuk mengetahui perbedaannya. Jika tidak, akan lebih efisien untuk selidiki metrik lainnya yang mengalami regresi karena dapat memengaruhi batasan baik.
  • 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 selesai.
  • Waktu sistem adalah waktu yang dihabiskan oleh CPU dalam {i>kernel<i}.

    • Jika waktu sistem mengalami regresi, hal itu sebagian besar berkorelasi dengan I/O ketika Bazel membaca file dari sistem file Anda.

Pembuatan profil pemuatan seluruh sistem

Menggunakan --experimental_collect_load_average_in_profiler yang diperkenalkan di Bazel 6.0, profiler rekaman aktivitas JSON mengumpulkan beban rata-rata sistem selama pemanggilan.

Profil yang menyertakan beban rata-rata sistem

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. Anda mungkin ingin mempertimbangkan 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 memperoleh data penggunaan memori Bazel, Bazel info dan BEP.

  • bazel info used-heap-size-after-gc: Jumlah memori yang digunakan dalam byte setelah panggilan ke System.gc().

    • Bazel bench juga memberikan tolok ukur untuk metrik ini.
    • Selain itu, ada peak-heap-size, max-heap-size, used-heap-size dan committed-heap-size (lihat dokumentasi), tetapi kurang relevan.
  • BEP MemoryMetrics.peak_post_gc_heap_size: Ukuran ukuran heap JVM puncak dalam byte setelah GC (membutuhkan setelan --memory_profile yang mencoba memaksa GC penuh).

Regresi dalam penggunaan memori biasanya merupakan akibat dari regresi metrik ukuran permintaan build, yang sering kali disebabkan oleh penambahan dependensi atau perubahan aturan terlepas dari implementasi layanan.

Untuk menganalisis jejak memori Bazel pada tingkat 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 memori mereka dapat bermasalah. Bazel mengumpulkan metrik tentang pekerjanya, khususnya, Kolom WorkerMetrics.WorkerStats.worker_memory_in_kb memberi tahu berapa banyak memori digunakan pekerja (dengan mnemonik).

Profiler rekaman aktivitas JSON juga akan mengumpulkan penggunaan memori pekerja persisten selama pemanggilan dengan meneruskan --experimental_collect_system_network_usage flag (baru di Bazel 6.0).

Profil yang menyertakan penggunaan memori pekerja

Gambar 2. Profil yang menyertakan penggunaan memori pekerja.

Menurunkan nilai --worker_max_instances (default 4) mungkin membantu mengurangi jumlah memori yang digunakan oleh pekerja persisten. Kami secara aktif berupaya membuat pengelola sumber daya dan penjadwal Bazel menjadi lebih cerdas sehingga pengaturan akan lebih jarang diperlukan di masa mendatang.

Memantau traffic jaringan untuk build jarak jauh

Dalam eksekusi jarak jauh, Bazel mengunduh artefak yang dibangun sebagai hasil dari melaksanakan tindakan. Dengan demikian, bandwidth jaringan Anda dapat memengaruhi performa dari build Anda.

Jika menggunakan eksekusi jarak jauh untuk build Anda, sebaiknya pertimbangkan memantau traffic jaringan selama pemanggilan NetworkMetrics.SystemNetworkStats proto dari BEP (harus meneruskan --experimental_collect_system_network_usage).

Selain itu, profil rekaman aktivitas JSON memungkinkan Anda melihat penggunaan jaringan seluruh sistem selama build dengan meneruskan tanda --experimental_collect_system_network_usage (baru di Bazel 6.0).

Profil yang berisi penggunaan jaringan seluruh sistem

Gambar 3. Profil yang mencakup penggunaan jaringan seluruh sistem.

Penggunaan jaringan yang tinggi namun agak datar saat menggunakan eksekusi jarak jauh mungkin mengindikasikan jaringan tersebut 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 lain adalah mengonfigurasi cache disk untuk menghemat .