Eksekusi dinamis adalah fitur di Bazel yang memungkinkan eksekusi lokal dan jarak jauh dari tindakan yang sama dimulai secara paralel, menggunakan output dari cabang pertama yang selesai, dan membatalkan cabang lainnya. Fitur ini menggabungkan daya eksekusi dan/atau cache bersama yang besar dari sistem build jarak jauh dengan latensi rendah dari eksekusi lokal, sehingga memberikan yang terbaik dari keduanya untuk build bersih dan inkremental.
Halaman ini menjelaskan cara mengaktifkan, menyesuaikan, dan men-debug eksekusi dinamis. Jika Anda telah menyiapkan eksekusi lokal dan jarak jauh serta mencoba menyesuaikan setelan Bazel untuk performa yang lebih baik, halaman ini cocok untuk Anda. Jika Anda belum menyiapkan eksekusi jarak jauh, buka Ringkasan Eksekusi Jarak Jauh Bazel terlebih dahulu.
Mengaktifkan eksekusi dinamis?
Modul eksekusi dinamis adalah bagian dari Bazel, tetapi untuk menggunakan eksekusi dinamis, Anda harus sudah dapat mengompilasi secara lokal dan jarak jauh dari setelan Bazel yang sama.
Untuk mengaktifkan modul eksekusi dinamis, teruskan flag --internal_spawn_scheduler ke Bazel. Tindakan ini akan menambahkan strategi eksekusi baru yang disebut dynamic. Sekarang Anda dapat menggunakannya sebagai strategi untuk mnemonik yang ingin Anda jalankan secara dinamis, seperti --strategy=Javac=dynamic. Lihat bagian berikutnya untuk mengetahui cara memilih mnemonik yang akan mengaktifkan eksekusi dinamis.
Untuk mnemonik apa pun yang menggunakan strategi dinamis, strategi eksekusi jarak jauh diambil dari flag --dynamic_remote_strategy, dan strategi lokal dari flag --dynamic_local_strategy. Meneruskan --dynamic_local_strategy=worker,sandboxed akan menetapkan default untuk cabang lokal eksekusi dinamis agar mencoba dengan pekerja atau eksekusi sandbox dalam urutan tersebut. Meneruskan --dynamic_local_strategy=Javac=worker akan mengganti default hanya untuk mnemonik Javac. Versi jarak jauh berfungsi dengan cara yang sama. Kedua flag dapat ditentukan beberapa kali. Jika tindakan tidak dapat dieksekusi secara lokal, tindakan tersebut akan dieksekusi dari jarak jauh seperti biasa, dan sebaliknya.
Jika sistem jarak jauh Anda memiliki cache, flag --dynamic_local_execution_delay akan menambahkan penundaan dalam milidetik ke eksekusi lokal setelah sistem jarak jauh menunjukkan cache hit. Hal ini akan menghindari eksekusi lokal saat kemungkinan ada lebih banyak cache hit. Nilai default-nya adalah 1000 md, tetapi harus disesuaikan agar sedikit lebih lama daripada waktu yang biasanya diperlukan untuk cache hit. Waktu sebenarnya bergantung pada sistem jarak jauh dan waktu yang diperlukan untuk perjalanan pulang pergi. Biasanya, nilainya akan sama untuk semua pengguna sistem jarak jauh tertentu, kecuali jika beberapa di antaranya berada cukup jauh sehingga menambahkan latensi pulang pergi. Anda dapat menggunakan fitur pembuatan profil Bazel untuk melihat waktu yang diperlukan untuk cache hit
biasa.
Eksekusi dinamis dapat digunakan dengan strategi sandbox lokal serta dengan
pekerja persisten. Pekerja persisten akan otomatis
berjalan dengan sandbox saat digunakan dengan eksekusi dinamis, dan tidak dapat menggunakan multiplex
pekerja. Pada sistem Darwin dan Windows, strategi sandbox dapat berjalan lambat; Anda dapat meneruskan --reuse_sandbox_directories untuk mengurangi overhead pembuatan sandbox pada sistem ini.
Eksekusi dinamis juga dapat berjalan dengan strategi standalone, meskipun strategi standalone harus mengambil kunci output saat mulai dieksekusi, sehingga secara efektif memblokir strategi jarak jauh agar tidak selesai terlebih dahulu. Flag --experimental_local_lockfree_output memungkinkan cara untuk mengatasi masalah ini dengan mengizinkan eksekusi lokal untuk menulis langsung ke output, tetapi dibatalkan oleh eksekusi jarak jauh, jika eksekusi jarak jauh selesai terlebih dahulu.
Jika salah satu cabang eksekusi dinamis selesai terlebih dahulu tetapi gagal, seluruh tindakan akan gagal. Hal ini merupakan pilihan yang disengaja untuk mencegah perbedaan antara eksekusi lokal dan jarak jauh tidak diperhatikan.
Untuk mengetahui latar belakang selengkapnya tentang cara kerja eksekusi dinamis dan pengunciannya, lihat postingan blog Julio Merino yang sangat bagus blog posts
Kapan saya harus menggunakan eksekusi dinamis?
Eksekusi dinamis memerlukan beberapa bentuk sistem eksekusi jarak jauh. Saat ini, Anda tidak dapat menggunakan sistem jarak jauh khusus cache, karena cache miss akan dianggap sebagai tindakan yang gagal.
Tidak semua jenis tindakan cocok untuk eksekusi jarak jauh. Kandidat terbaik adalah tindakan yang secara inheren lebih cepat secara lokal, misalnya melalui penggunaan pekerja persisten, atau tindakan yang berjalan cukup cepat sehingga overhead eksekusi jarak jauh mendominasi waktu eksekusi. Karena setiap tindakan yang dieksekusi secara lokal mengunci sejumlah resource CPU dan memori, menjalankan tindakan yang tidak termasuk dalam kategori tersebut hanya akan menunda eksekusi untuk tindakan yang termasuk.
Mulai dari rilis
5.0.0-pre.20210708.4,
pembuatan profil performa berisi data
tentang eksekusi pekerja, termasuk waktu yang dihabiskan untuk menyelesaikan permintaan kerja setelah
kalah dalam kompetisi eksekusi dinamis. Jika Anda melihat thread pekerja eksekusi dinamis menghabiskan banyak waktu untuk mendapatkan resource, atau banyak waktu di async-worker-finish, Anda mungkin memiliki beberapa tindakan lokal yang lambat yang menunda thread pekerja.
Dalam profil di atas, yang menggunakan 8 pekerja Javac, kita melihat banyak pekerja Javac yang kalah dalam kompetisi dan menyelesaikan pekerjaannya di thread async-worker-finish. Hal ini disebabkan oleh mnemonik non-pekerja yang menggunakan resource yang cukup untuk menunda pekerja.
Jika hanya Javac yang dijalankan dengan eksekusi dinamis, hanya sekitar setengah dari pekerja yang dimulai yang kalah dalam kompetisi setelah memulai pekerjaannya.
Flag --experimental_spawn_scheduler yang sebelumnya direkomendasikan tidak digunakan lagi.
Flag ini mengaktifkan eksekusi dinamis dan menetapkan dynamic sebagai strategi default untuk semua mnemonik, yang sering kali menyebabkan masalah semacam ini.
Performa
Pendekatan eksekusi dinamis mengasumsikan bahwa ada cukup resource yang tersedia secara lokal dan jarak jauh sehingga layak untuk menghabiskan beberapa resource tambahan guna meningkatkan performa secara keseluruhan. Namun, penggunaan resource yang berlebihan dapat memperlambat Bazel itu sendiri atau mesin tempat Bazel berjalan, atau memberikan tekanan yang tidak terduga pada sistem jarak jauh. Ada beberapa opsi untuk mengubah perilaku eksekusi dinamis:
--dynamic_local_execution_delay menunda dimulainya cabang lokal dengan sejumlah milidetik setelah cabang jarak jauh dimulai, tetapi hanya jika ada cache hit jarak jauh selama build saat ini. Hal ini membuat build yang memanfaatkan cache jarak jauh tidak membuang resource lokal jika kemungkinan besar sebagian besar output dapat ditemukan dalam cache. Bergantung pada kualitas cache, mengurangi hal ini dapat meningkatkan kecepatan build, dengan mengorbankan penggunaan lebih banyak resource lokal.
--experimental_dynamic_local_load_factor adalah opsi pengelolaan resource lanjutan eksperimental. Opsi ini menggunakan nilai dari 0 hingga 1, dengan 0 menonaktifkan fitur ini.
Jika ditetapkan ke nilai di atas 0, Bazel akan menyesuaikan jumlah tindakan yang dijadwalkan secara lokal saat banyak tindakan menunggu untuk dijadwalkan. Menetapkannya ke 1 memungkinkan sebanyak mungkin tindakan dijadwalkan sesuai dengan jumlah CPU yang tersedia (sesuai dengan --local_cpu_resources). Nilai yang lebih rendah menetapkan jumlah tindakan yang dijadwalkan menjadi lebih sedikit karena jumlah tindakan yang lebih tinggi tersedia untuk dijalankan. Hal ini mungkin terdengar tidak intuitif, tetapi dengan sistem jarak jauh yang baik, eksekusi lokal tidak banyak membantu saat banyak tindakan dijalankan, dan CPU lokal lebih baik digunakan untuk mengelola tindakan jarak jauh.
--experimental_dynamic_slow_remote_time memprioritaskan memulai cabang lokal saat cabang jarak jauh telah berjalan setidaknya selama ini. Biasanya, tindakan yang paling baru dijadwalkan akan diprioritaskan, karena memiliki peluang terbesar untuk memenangkan kompetisi, tetapi jika sistem jarak jauh terkadang hang atau memerlukan waktu yang sangat lama, hal ini dapat membuat build bergerak. Opsi ini tidak diaktifkan secara default, karena dapat menyembunyikan masalah pada sistem jarak jauh yang seharusnya diperbaiki. Pastikan untuk memantau performa sistem jarak jauh jika Anda mengaktifkan opsi ini.
--experimental_dynamic_ignore_local_signals dapat digunakan untuk memungkinkan cabang jarak jauh mengambil alih saat spawn lokal keluar karena sinyal tertentu. Hal ini
terutama berguna bersama dengan batas resource pekerja (lihat
--experimental_worker_memory_limit_mb,
--experimental_worker_sandbox_hardening,
dan
--experimental_sandbox_memory_limit_mb)),
yang mana proses pekerja dapat dihentikan jika menggunakan terlalu banyak resource.
Profil pelacakan JSON berisi sejumlah grafik terkait performa yang dapat membantu mengidentifikasi cara meningkatkan kompromi performa dan penggunaan resource.
Pemecahan masalah
Masalah dengan eksekusi dinamis dapat bersifat halus dan sulit di-debug, karena hanya dapat muncul dalam beberapa kombinasi eksekusi lokal dan jarak jauh tertentu.
--debug_spawn_scheduler menambahkan output tambahan dari sistem eksekusi dinamis yang dapat membantu men-debug masalah ini. Anda juga dapat menyesuaikan flag --dynamic_local_execution_delay dan jumlah tugas jarak jauh vs. lokal untuk memudahkan mereproduksi masalah.
Jika Anda mengalami masalah dengan eksekusi dinamis menggunakan strategi standalone, coba jalankan tanpa --experimental_local_lockfree_output, atau jalankan tindakan lokal Anda di sandbox. Hal ini mungkin akan sedikit memperlambat build Anda (lihat di atas jika Anda menggunakan Mac atau Windows), tetapi menghapus beberapa kemungkinan penyebab kegagalan.