Eksekusi Dinamis

7/0.9/2.5. Lihat sumber Nightly {/3/}

Dynamic execution adalah fitur di Bazel tempat eksekusi lokal dan jarak jauh dari tindakan yang sama dimulai secara paralel, menggunakan output dari cabang pertama yang selesai, sehingga membatalkan cabang lainnya. Platform ini menggabungkan kekuatan eksekusi dan/atau cache bersama yang besar dari sistem build jarak jauh dengan latensi rendah untuk eksekusi lokal, sehingga memberikan yang terbaik dari kedua dunia 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 Remote Execution Overview Bazel terlebih dahulu.

Mengaktifkan eksekusi dinamis?

Modul eksekusi dinamis adalah bagian dari Bazel. Namun, untuk memanfaatkan eksekusi dinamis, Anda harus dapat mengompilasi secara lokal dan jarak jauh dari konfigurasi Bazel yang sama.

Untuk mengaktifkan modul eksekusi dinamis, teruskan flag --internal_spawn_scheduler ke Bazel. Tindakan ini menambahkan strategi eksekusi baru yang disebut dynamic. Kini Anda dapat menggunakan ini sebagai strategi untuk mnemonik yang ingin dijalankan secara dinamis, seperti --strategy=Javac=dynamic. Lihat bagian berikutnya untuk mengetahui cara memilih mnemonik yang akan mengaktifkan eksekusi dinamis.

Untuk setiap mnemonik 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 setelan default untuk cabang lokal eksekusi dinamis yang akan dicoba dengan pekerja atau eksekusi dalam sandbox sesuai urutan tersebut. Meneruskan --dynamic_local_strategy=Javac=worker akan menggantikan default untuk mnemonik Javac saja. Versi jarak jauh berfungsi dengan cara yang sama. Kedua flag dapat ditentukan beberapa kali. Jika tidak dapat dijalankan secara lokal, tindakan akan dijalankan 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 ditemukan cache. Tindakan ini akan menghindari eksekusi lokal yang berjalan jika kemungkinan cache ditemukan lebih banyak. Nilai defaultnya adalah 1.000 md, tetapi harus disesuaikan agar sedikit lebih panjang dari yang biasanya dibutuhkan oleh hit cache. Waktu sebenarnya bergantung pada sistem jarak jauh dan waktu pulang pergi. Biasanya, nilainya akan sama untuk semua pengguna sistem jarak jauh tertentu, kecuali jika beberapa dari mereka cukup jauh untuk menambahkan latensi bolak-balik. Anda dapat menggunakan fitur pembuatan profil Bazel untuk melihat berapa lama waktu yang dibutuhkan saat hit cache biasa.

Eksekusi dinamis dapat digunakan dengan strategi yang di-sandbox lokal serta dengan pekerja persisten. Pekerja persisten akan otomatis dijalankan dengan sandbox saat digunakan dengan eksekusi dinamis, dan tidak dapat menggunakan pekerja multipleks. Di sistem Darwin dan Windows, strategi sandbox mungkin lambat; Anda dapat meneruskan --reuse_sandbox_directories untuk mengurangi overhead pembuatan sandbox di sistem ini.

Eksekusi dinamis juga dapat dijalankan dengan strategi standalone. Namun, karena strategi standalone harus mengambil kunci output saat mulai dieksekusi, strategi tersebut secara efektif memblokir strategi jarak jauh agar tidak selesai terlebih dahulu. Flag --experimental_local_lockfree_output dapat mengatasi masalah ini dengan mengizinkan eksekusi lokal menulis secara langsung ke output, tetapi dibatalkan oleh eksekusi jarak jauh, jika proses tersebut selesai terlebih dahulu.

Jika salah satu cabang eksekusi dinamis selesai terlebih dahulu tetapi mengalami kegagalan, seluruh tindakan akan gagal. Hal ini adalah pilihan disengaja untuk mencegah perbedaan antara eksekusi lokal dan jarak jauh tidak diketahui.

Untuk latar belakang selengkapnya tentang cara kerja eksekusi dinamis dan pengunciannya, lihat postingan blog Julio Merino yang sangat baik

Kapan saya harus menggunakan eksekusi dinamis?

Eksekusi dinamis memerlukan beberapa bentuk sistem eksekusi jarak jauh. Saat ini, penggunaan sistem jarak jauh khusus cache tidak dapat dilakukan, karena cache tidak ditemukan akan dianggap sebagai tindakan yang gagal.

Tidak semua jenis tindakan cocok untuk eksekusi jarak jauh. Kandidat terbaik adalah kandidat yang secara inheren lebih cepat secara lokal, misalnya melalui penggunaan pekerja persisten, atau mereka 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 bagi tindakan yang melakukannya.

Mulai 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 perlombaan eksekusi dinamis. Jika Anda melihat thread pekerja eksekusi dinamis yang menghabiskan banyak waktu untuk mendapatkan resource, atau banyak waktu dalam async-worker-finish, Anda mungkin memiliki beberapa tindakan lokal yang lambat yang menunda thread pekerja.

Membuat profil data dengan performa eksekusi dinamis yang buruk

Pada profil di atas, yang menggunakan 8 pekerja Javac, kita melihat banyak pekerja Javac yang kehilangan proses dan menyelesaikan pekerjaan mereka di thread async-worker-finish. Hal ini disebabkan oleh mnemonik non-pekerja yang mengambil cukup resource untuk menunda pekerja.

Membuat profil data dengan performa eksekusi dinamis yang lebih baik

Jika hanya Javac yang dijalankan dengan eksekusi dinamis, hanya sekitar setengah dari pekerja yang dimulai akan kehilangan perlombaan setelah memulai pekerjaannya.

Flag --experimental_spawn_scheduler yang sebelumnya direkomendasikan sudah tidak digunakan lagi. Tindakan ini mengaktifkan eksekusi dinamis dan menetapkan dynamic sebagai strategi default untuk semua mnemonik, yang sering kali akan menyebabkan masalah semacam ini.

Performa

Pendekatan eksekusi dinamis mengasumsikan bahwa ada cukup resource yang tersedia secara lokal dan jarak jauh, sehingga layak untuk membelanjakan beberapa resource tambahan untuk meningkatkan performa secara keseluruhan. Namun, penggunaan resource yang berlebihan dapat memperlambat Bazel atau mesin yang menjalankannya, atau memberikan tekanan tak terduga pada sistem jarak jauh. Ada beberapa opsi untuk mengubah perilaku eksekusi dinamis:

--dynamic_local_execution_delay menunda dimulainya cabang lokal sebesar jumlah milidetik setelah cabang jarak jauh dimulai, tetapi hanya jika terdapat cache jarak jauh selama build saat ini. Hal ini membuat build yang mendapatkan manfaat dari cache jarak jauh tidak menyia-nyiakan resource lokal jika sebagian besar output dapat ditemukan di 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 yang bersifat eksperimental. Dibutuhkan nilai dari 0 hingga 1, 0 untuk menonaktifkan fitur ini. Jika disetel ke nilai di atas 0, Bazel akan menyesuaikan jumlah tindakan yang dijadwalkan secara lokal saat banyak tindakan yang menunggu untuk dijadwalkan. Menyetelnya ke 1 akan memungkinkan sebanyak mungkin tindakan dijadwalkan sesuai jumlah CPU yang tersedia (berdasarkan --local_cpu_resources). Nilai yang lebih rendah menetapkan jumlah tindakan yang dijadwalkan agar lebih sedikit karena jumlah tindakan yang lebih tinggi tersedia untuk dijalankan. Hal ini mungkin terdengar kontra-intuitif, tetapi dengan sistem jarak jauh yang baik, eksekusi lokal tidak akan banyak membantu saat banyak tindakan sedang dijalankan, dan CPU lokal lebih efektif untuk mengelola tindakan jarak jauh.

--experimental_dynamic_slow_remote_time memprioritaskan untuk memulai cabang lokal saat cabang jarak jauh telah berjalan setidaknya selama ini. Biasanya tindakan yang dijadwalkan paling baru akan diprioritaskan karena memiliki peluang terbesar untuk memenangkan perlombaan, tetapi jika sistem jarak jauh terkadang macet atau memakan waktu lebih lama, build dapat melanjutkan proses ini. Tindakan ini tidak diaktifkan secara default karena dapat menyembunyikan masalah dengan sistem jarak jauh yang sebaiknya 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)), saat proses pekerja dapat dihentikan jika menggunakan terlalu banyak resource.

Profil rekaman aktivitas JSON berisi sejumlah grafik terkait performa yang dapat membantu mengidentifikasi cara untuk meningkatkan keseimbangan performa dan penggunaan resource.

Pemecahan masalah

Masalah dengan eksekusi dinamis dapat menjadi hal yang kecil dan sulit di-debug, karena hanya dapat muncul pada beberapa kombinasi tertentu dari eksekusi lokal dan jarak jauh. --debug_spawn_scheduler menambahkan output ekstra dari sistem eksekusi dinamis yang dapat membantu men-debug masalah ini. Anda juga dapat menyesuaikan tanda --dynamic_local_execution_delay dan jumlah tugas jarak jauh vs. lokal untuk memudahkan reproduksi masalah.

Jika Anda mengalami masalah dengan eksekusi dinamis menggunakan strategi standalone, coba jalankan tanpa --experimental_local_lockfree_output, atau jalankan tindakan lokal dalam sandbox. Tindakan ini mungkin sedikit memperlambat build Anda (lihat di atas jika Anda menggunakan Mac atau Windows), tetapi menghapus beberapa kemungkinan penyebab kegagalan.