Topik wawancara representatif

Salah Kompilasi LLVM pada Rust 1.97.1: Bagaimana Anda Merespons Dugaan Regresi Kompiler?

UmumSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Setelah layanan produksi ditingkatkan ke Rust 1.97.0, sebagian kecil input menghasilkan keluaran yang salah, sementara build debug berhasil dan build release gagal. Anda mencurigai adanya salah kompilasi akibat optimasi LLVM. Jelaskan bagaimana Anda membedakan antara bug aplikasi, perilaku tak terdefinisi (undefined behavior), dan regresi kompiler; membendung serta melakukan rollback rilis; dan memverifikasi bahwa Rust 1.97.1 benar-benar mencakup kode Anda.

Perintah dan ruang lingkup

Ini adalah pertanyaan rekayasa rilis dan penilaian insiden. Proyek Rust menyatakan bahwa versi 1.97.1 memperbaiki kesalahan kompilasi (miscompilation) yang disebabkan oleh optimasi LLVM dan menonaktifkan perubahan mendasar pada Rust 1.97.0 yang meningkatkan kemungkinannya; masalah mendasar tersebut mungkin telah ada setidaknya sejak versi 1.87. Anda tidak perlu menebak pass LLVM yang terlibat. Anda memerlukan rantai bukti yang mengidentifikasi regresi, melindungi pengguna, memilih kebijakan versi, dan membuktikan bahwa biner yang diperbaiki berperilaku dengan benar.

Apa yang dievaluasi pewawancara

  • Apakah Anda memisahkan output yang salah berdasarkan input, konfigurasi build, tingkat optimasi, platform, dan versi dependensi sebelum menyalahkan kompiler.
  • Apakah Anda merancang reproducer minimal, build diferensial, dan perbandingan tingkat biner.
  • Apakah Anda membendung risiko ketika bukti belum lengkap dan menentukan kriteria pembatalan (rollback), penonaktifan optimasi, atau penghentian rilis.
  • Apakah Anda memvalidasi menggunakan properti, jawaban yang diketahui, dan matriks versi daripada hanya mengandalkan satu eksekusi yang berhasil.
  • Apakah Anda mengomunikasikan dampak, versi yang diperbaiki, catatan rantai pasok, dan tindakan pencegahan.

Pertanyaan klarifikasi yang perlu diajukan

  • Apakah kegagalan hanya muncul pada Rust 1.97.0, target rustc tertentu, atau tingkat optimasi tertentu?
  • Apakah -C opt-level, LTO, fitur CPU, dan linker identik antara build debug dan release?
  • Bisakah Anda menyimpan input yang gagal, output yang diharapkan, dan perintah build yang dapat direproduksi?
  • Apakah ada perubahan dependensi, makro, unsafe code, atau FFI selama peningkatan versi?
  • Bisakah layanan kembali ke biner sebelumnya dengan cepat, dan apakah operasi penulisan data memerlukan kompensasi?

Jawaban 30 detik

“Saya akan membekukan biner yang dicurigai beserta metadata build, menyimpan input yang gagal dan output yang diharapkan, lalu membandingkan Rust 1.97.0, 1.97.1, dan rilis stabil terakhir yang diketahui berfungsi baik dengan kode sumber yang identik, dependensi terkunci, target, dan pengaturan optimasi yang sama. Secara paralel, saya akan memeriksa unsafe code, FFI, dan undefined behavior agar cacat aplikasi tidak salah diidentifikasi sebagai regresi kompiler. Saya akan melakukan rollback terlebih dahulu dan, jika diperlukan, menurunkan tingkat optimasi sebagai penanganan sementara. Setelah reproducer minimal hanya terpicu pada kompiler yang terdampak dan hilang pada 1.97.1, saya akan memvalidasinya dengan uji properti, eksekusi diferensial, dan matriks multi-platform sebelum melakukan peluncuran bertahap.”

Pembahasan mendalam langkah demi langkah

Langkah 1: Bekukan bukti dan bendung dampak buruk

Simpan permintaan yang gagal, output yang salah, hash biner, rustc -Vv, Cargo.lock, flag kompiler, platform target, dan cache dependensi. Hentikan perluasan rilis dan kembali ke biner stabil terakhir yang diketahui. Jika rollback tidak dapat dilakukan seketika, turunkan tingkat optimasi untuk sementara atau nonaktifkan jalur kode yang memicu masalah sambil mencatat penurunan performa. Jika data yang ditulis kemungkinan sudah salah, isolasi data tersebut dan siapkan kompensasi alih-alih membiarkan deployment yang sukses menyembunyikan kerugian bisnis.

Langkah 2: Bangun kasus diferensial minimal

Gunakan input tetap dan proses build deterministik, lalu pangkas kode bisnis, dependensi, dan makro hingga hanya menyisakan program minimal. Bandingkan debug dan release, nilai opt-level yang berbeda, LTO, CPU target, dan linker. Jalankan biner yang dihasilkan oleh beberapa versi kompiler dari sumber yang sama secara diferensial. Kegagalan yang terisolasi pada satu versi dan kombinasi optimasi tertentu merupakan bukti regresi yang lebih kuat daripada satu insiden acak.

Langkah 3: Singkirkan kemungkinan undefined behavior

Periksa unsafe code, pointer aliasing, batasan array (bounds), data race, FFI ABI, dan memori yang belum diinisialisasi. Gunakan Miri, sanitizer, penambahan assertion, dan input terstruktur untuk membantu menyingkirkan cacat aplikasi, sambil tetap menyatakan batas cakupannya. Sistem tipe aman Rust tidak membuktikan bahwa setiap blok unsafe atau pustaka eksternal sudah benar; jika undefined behavior memang ada, pembaruan kompiler mungkin hanya mengubah gejala yang terlihat.

Langkah 4: Verifikasi batas versi dan perbaikan

Pengumuman Rust 1.97.1 menyatakan bahwa pembaruan ini memperbaiki salah kompilasi akibat optimasi LLVM dan menonaktifkan perubahan mendasar pada Rust 1.97.0 yang meningkatkan kemungkinannya. Ubah reproducer minimal menjadi satu perintah verifikasi langsung, lakukan build dengan 1.97.0, 1.97.1, dan rilis stabil terakhir, lalu periksa output, invarian assembly yang relevan, serta properti runtime. Jika 1.97.1 masih gagal, jangan mengklaim bahwa kode Anda sudah tercakup; terus sederhanakan kasus tersebut dan ikuti panduan resmi atau beralihlah ke versi yang aman.

Langkah 5: Validasi biner produksi secara berlapis

Cakup input normal dan batas (boundary) dengan golden fixtures, uji berbasis properti, pemutaran ulang random seed, dan eksekusi diferensial. Gunakan shadow traffic atau canary kecil untuk layanan kritis, dan amati tingkat kesalahan, konsistensi hasil, crash, latensi, serta perubahan sumber daya. Matriks pengujian harus mencakup target nyata, linker, LTO, set instruksi CPU, dan container rilis; lolos pengujian pada build debug lokal bukanlah bukti kesiapan produksi.

Langkah 6: Komunikasikan dan cegah keberulangan

Catat versi yang terdampak, platform, kombinasi optimasi, karakteristik input, volume data yang rusak, waktu rollback, dan bukti perbaikan. Beritahukan tim on-call, tim rilis, dan tim terdampak mengenai ambang batas tindakan, serta hindari menyebarkan kepastian yang tidak didukung oleh bukti. Jadikan pembaruan kompiler sebagai bagian dari matriks versi, build yang dapat direproduksi, pengujian golden-output, dan rilis bertahap; simpan artefak versi sebelumnya yang telah ditandatangani untuk keperluan rollback.

Contoh jawaban berkualitas tinggi

“Saya akan membekukan metadata build dan sampel yang gagal, menghentikan perluasan peluncuran Rust 1.97.0, dan kembali ke biner stabil terakhir yang diketahui. Kemudian, saya akan mengunci kode sumber, dependensi, target, linker, dan flag optimasi, menyederhanakan kegagalan menjadi reproducer minimal, serta membandingkan debug, release, LTO, dan beberapa versi rustc. Saya juga akan memeriksa unsafe code, FFI, dan undefined behavior agar cacat aplikasi tidak salah dilabeli sebagai regresi kompiler. Rust 1.97.1 mendokumentasikan perbaikan salah kompilasi LLVM, jadi saya akan mem-build reproducer yang sama dengan 1.97.0, 1.97.1, dan rilis stabil terakhir, lalu menggunakan golden test, pengujian berbasis properti, eksekusi diferensial, serta canary pada target nyata. Saya akan melanjutkan rilis bertahap hanya jika kegagalan terbukti pada kombinasi yang terdampak, 1.97.1 berhasil menghilangkannya, dan metrik produksi tetap stabil; jika tidak, saya akan mempertahankan rollback dan menyimpan bukti-bukti yang ada.”

Kesalahan umum

  • Langsung menyalahkan LLVM segera setelah kesalahan terkait versi muncul tanpa membekukan input, target, dan flag build.
  • Hanya membandingkan debug dan release sambil mengabaikan unsafe code, FFI, atau undefined behavior.
  • Meningkatkan ke versi 1.97.1 dan hanya menjalankan satu unit test sebelum mengklaim bahwa masalah telah teratasi.
  • Menonaktifkan optimasi dan melanjutkan peluncuran penuh tanpa memperhitungkan risiko performa dan kebenaran data.
  • Kehilangan biner yang gagal, Cargo.lock, atau metadata rantai pasok yang diperlukan untuk reproduksi.
  • Menggeneralisasi pernyataan perbaikan resmi menjadi klaim bahwa setiap platform dan codebase sudah aman.

Pertanyaan lanjutan dan jawaban

Bagaimana jika kasus minimal hanya terpicu oleh fitur CPU tertentu?

Perlakukan target CPU, flag pembuatan kode (code-generation), dan linker sebagai bagian dari kasus reproduksi. Batasi atau lakukan rollback pada target tersebut, lalu jalankan matriks dengan 1.97.1 dan rilis stabil terakhir pada arsitektur yang terdampak maupun yang tidak terdampak. Satu mesin pengembang tidak dapat mewakili setiap target produksi.

Kapan penurunan optimasi dapat menjadi solusi jangka panjang?

Hanya setelah tinjauan risiko dan alokasi anggaran performa (performance budget) secara eksplisit menyetujuinya sementara akar penyebab masalah belum terselesaikan. Penurunan ini dapat mengubah throughput, latensi, dan tata letak kode, sehingga memerlukan benchmark, pemantauan, dan kondisi keluar (exit condition) yang jelas. Rilis resmi yang telah diperbaiki tetap lebih disukai.

Bagaimana Anda membuktikan bahwa data historis tidak mengalami kerusakan?

Putar ulang data referensi (golden data) dan sampel berdasarkan waktu, versi, target, dan karakteristik input; bandingkan checksum, invarian bisnis, serta perbedaan pada sistem downstream. Buat mekanisme kompensasi atau penghitungan ulang untuk penulisan data yang terkonfirmasi terdampak, dan catat ruang lingkup auditnya. Tingkat kesalahan yang terlihat normal saja tidak membuktikan ketiadaan kerusakan data.

Sumber publik

Pertanyaan terkait