1 poin oleh GN⁺ 2025-05-23 | 1 komentar | Bagikan ke WhatsApp
  • Dekoder AV1 rav1d yang ditulis dengan Rust ditemukan sekitar 9% lebih lambat dibandingkan dav1d berbasis C
  • Melalui optimasi inisialisasi buffer dan perbaikan logika perbandingan struct, masing-masing terkonfirmasi memberi peningkatan kecepatan sebesar 1,5% dan 0,7%
  • Dengan memanfaatkan alat profiling samply, penyebab perbedaan performa antara dua versi dapat diidentifikasi secara spesifik
  • Alih-alih implementasi bawaan PartialEq di Rust, efisiensi ditingkatkan dengan metode perbandingan per byte
  • Optimasi kali ini memperbaiki sekitar 30% dari keseluruhan selisih performa, tetapi masih ada ruang untuk optimasi lebih lanjut

Latar belakang dan pendekatan

  • rav1d adalah proyek yang mem-porting dekoder AV1 dav1d ke Rust dengan c2rust, lalu menambahkan fungsi optimasi asm serta peningkatan keamanan khas bahasa Rust
  • Tolok ukur performa dasar telah ditetapkan secara publik, dan rav1d berbasis Rust berada sekitar 5% lebih lambat daripada dav1d berbasis C
  • Alih-alih membahas struktur umum dekoder video yang kompleks, analisis difokuskan pada perbedaan runtime biner untuk input yang sama
  • Perbandingan dilakukan secara sistematis dengan alat pengukur performa (hyperfine) dan profiler (samply)
  • Lingkungan pengujian adalah chip macOS M3, disederhanakan dengan eksekusi single-thread

Pengukuran performa: perbandingan dasar

  • Build dan benchmark dijalankan masing-masing dengan file uji yang sama (Chimera-AV1-8bit-1920x1080-6736kbps.ivf)
  • rav1d: sekitar 73,9 detik, dav1d: sekitar 67,9 detik, sehingga terkonfirmasi ada selisih waktu eksekusi sekitar 6 detik (9%)
  • Masing-masing compiler (Clang, Rustc) menggunakan versi LLVM yang nyaris sama

Analisis profiling

  • Dengan profiler samply, jumlah sampel per fungsi pada masing-masing executable dibandingkan
  • Jalur pemanggilan dan distribusi sampel dari fungsi assembly berbasis NEON (ARM SIMD) diperiksa secara fokus
  • dav1d memisahkan pemanggilan fungsi asm melalui fungsi filter terpisah, sedangkan rav1d mengelola semuanya lewat satu fungsi dispatch
  • Pada fungsi cdef_filter_neon_erased, jumlah sampel Self terlihat sekitar 270 lebih banyak dibandingkan gabungan dua fungsi di dav1d (setara sekitar 1% dari total)
  • Hasil analisis menangkap bagian di mana buffer sementara (zero-initialized buffer) diinisialisasi terlalu besar secara tidak perlu

Optimasi penghapusan inisialisasi buffer

  • Demi keamanan, Rust melakukan zeroing otomatis dengan cara seperti [0u16; LEN]
  • Namun C (dav1d) tidak melakukan zeroing buffer secara eksplisit, dan hanya menulis nilai pada area yang benar-benar digunakan
  • Di Rust, biaya inisialisasi yang tidak perlu dihilangkan dengan menggunakan std::mem::MaybeUninit
  • Sampel Self pada fungsi cdef_filter_neon_erased turun drastis dari 670 menjadi 274
  • Buffer besar Align16 lainnya juga dipindahkan inisialisasinya ke luar loop, sehingga biaya inisialisasi berkurang menjadi satu kali saja
  • Setelah optimasi, benchmark menjadi sekitar 72,6 detik, membaik 1,2 detik (1,5%)

Optimasi perbandingan struct

  • Dari analisis inverted stack pada profiling, ditemukan bahwa fungsi add_temporal_candidate bekerja lebih tidak efisien dari perkiraan
  • Pada perbandingan field struct Mv di dalam fungsi ini (implementasi otomatis PartialEq), dihasilkan kode yang tidak perlu lambat
  • Di C, perbandingan efisien dilakukan per unit uint32_t dengan menggunakan union
  • Di Rust, tanpa menghindari unsafe, perbandingan per byte pada level byte slice diimplementasikan dengan trait zerocopy::AsBytes
  • Optimasi ini kembali menghasilkan peningkatan performa 0,5 detik (sekitar 0,7%)

Hasil dan ringkasan

  • Dua optimasi sederhana (penghapusan inisialisasi buffer dan perbandingan struct per byte) menghasilkan pemangkasan runtime lebih dari sekitar 2%
  • Masih tersisa selisih performa sekitar 6%, dan ruang optimasi tambahan masih besar
  • Dipastikan bahwa metode perbandingan antar snapshot profiler sangat efektif
  • Potensi optimasi lanjutan berbasis analisis snapshot rav1d dan dav1d dinilai tinggi
  • Berkat umpan balik aktif dan kerja sama dari para maintainer proyek, perbaikan berhasil dicapai tanpa mengorbankan keamanan

Ringkasan

  • Selisih runtime 6 detik (9%) antara rav1d dan dav1d dianalisis secara presisi dengan alat profiler (samply) dan benchmark (hyperfine)
  • Dua optimasi utama:
    • Menghapus zeroing buffer yang tidak perlu pada kode khusus ARM (1,2 detik, -1,6%)
    • Mengubah implementasi PartialEq untuk struct numerik kecil menjadi perbandingan byte yang lebih cepat (0,5 detik, -0,7%)
  • Masing-masing optimasi tetap ringkas, dalam hitungan beberapa puluh baris, tanpa kode unsafe baru
  • Melalui kolaborasi maintainer dan review PR, keandalan dan kualitas berhasil ditingkatkan sekaligus
  • Karena masih ada kesenjangan performa sekitar 6%, ruang untuk riset optimasi lanjutan berbasis perbandingan profiler masih sangat terbuka

Silakan coba sendiri! Mungkin suatu hari rav1d bisa menjadi lebih cepat daripada dav1d 👀🦀.

1 komentar

 
GN⁺ 2025-05-23
Opini Hacker News
  • Ada yang berbagi pendapat bahwa isu membandingkan dua u16 adalah topik yang menarik, serta memberikan tautan isu terkait https://github.com/rust-lang/rust/issues/140167
    • Mengungkapkan keheranan bahwa store forwarding tidak disebut dalam diskusi; hasil generasi kode pada -O3 memang berlebihan, tetapi pada -O2 masih masuk akal. Dijelaskan secara spesifik bahwa bila salah satu struktur baru saja dipakai dalam operasi, percobaan load 32-bit bisa gagal melakukan store forwarding sehingga peningkatan performa menjadi tidak berarti. Juga ditunjukkan bahwa dalam kondisi non-inline/non-PGO, kompiler kekurangan informasi yang dibutuhkan untuk menilai kelayakan optimasi
    • Kesan positif karena diskusi isu tersebut tidak dipenuhi komentar semacam “saya juga mengalaminya” atau “kapan diperbaiki”; sebagai web developer, ia juga secara jujur menyampaikan ketidakpuasannya terhadap GitHub Issues
    • Ada pendapat bahwa kasus ini menunjukkan betapa rumitnya pengembangan kompiler, dan keyakinan bahwa kompiler keluarga C pun tidak akan menangani isu semacam ini dengan jauh lebih baik
  • Ada yang penasaran bagaimana hasil profiler disisipkan ke dalam blog post, dan bertanya apakah node HTML-nya disalin begitu saja
  • Menilai menarik bahwa tulisan tentang keuntungan performa dari menghilangkan inisialisasi buffer (zeroing) muncul beberapa hari setelah tulisan terkait sebelumnya, sambil membagikan tautan tulisan lama https://news.ycombinator.com/item?id=44032680
  • Ada yang menilai judul artikel utama terlalu meremehkan dibanding hasil sebenarnya; ditekankan bahwa sebenarnya ada peningkatan kecepatan 2.3% berkat dua optimasi yang bagus
    • Ada pendapat bahwa peningkatan 1.5% hanya berlaku untuk aarch64, jadi agak kurang adil bila disebut sebagai angka keseluruhan; dengan mempertimbangkan proporsi arm/x86, angka yang lebih tepat mungkin sekitar setengahnya
  • Menilai postingan itu informatif, dan penemuan kode tidak efisien dalam perbandingan pasangan integer 16-bit terasa mengesankan
    • Penasaran apakah para pengembang Rust/LLVM bisa menerapkan optimasi ini secara otomatis saat memungkinkan, sambil menyebut bahwa di Rust informasi terkait inisialisasi memori jauh lebih akurat
  • Berpendapat bahwa jika semua syarat lain sama, codec seperti ini seharusnya ditangani dalam bahasa seperti WUFFS atau bahasa tujuan khusus yang sejenis ketimbang Rust. Ia berbagi kesan bahwa mengubah kode serumit dav1d ke WUFFS jauh lebih sulit daripada sekadar menerjemahkan dan merapikan kode C yang ada. Meski begitu, upaya seperti ini tetap dianggap bernilai dan layak didanai sebagai investasi peradaban
    • Dijelaskan bahwa WUFFS cocok untuk parsing kontainer seperti Matroska, webm, dan mp4, tetapi sama sekali tidak cocok untuk video decoder. Karena tidak ada alokasi memori dinamis, penanganan data dinamis menjadi menantang; ditekankan bahwa codec video bukan sekadar parsing file, melainkan membutuhkan pengelolaan state dinamis yang sangat beragam
  • Ada yang bertanya setengah bergumam karena penasaran dengan perkembangan bounty rav1d, lalu merasa relate karena ternyata ada orang lain yang punya kekhawatiran serupa
  • Kesan bahwa tulisan yang dibuka dengan meme lucu biasanya pertanda postingan yang bagus, sambil menyinggung keterkaitannya dengan diskusi yang baru-baru ini ramai, “Rav1d AV1 Decoder Rust optimization $20k bounty”, serta menambahkan tautan terkait https://news.ycombinator.com/item?id=43982238
    • Ada komentar bercanda bahwa ini adalah contoh jelas dari Nominative determinism (efek penamaan)
  • Secara jujur ada yang merasa agak terkejut karena optimasi pertama adalah tipe yang umum dan biasanya mudah ditemukan hanya dengan menggunakan perf dengan baik; isu zeroing pun dikira sudah dibahas di postingan pertama. Optimasi kedua dianggap lebih rumit dan menarik, tetapi tetap ditekankan bahwa arahnya juga dipandu oleh perf; disarankan agar kegunaan tool perf tidak diremehkan
    • Dijelaskan lebih tepat bahwa bukan hanya memakai perf, tetapi juga melalui proses differential profiling antara versi C dan versi Rust serta pencocokan manual. Disebutkan bahwa fitur perf diff memang ada, tetapi perbedaan nama simbol membuat pencocokan otomatis sulit dilakukan
    • Disebutkan bahwa pendekatan ini diambil dari sudut pandang perangkat Apple berbasis aarch64; dari pengalaman, orang dengan latar belakang berbeda bisa lebih cepat menangkap hal-hal yang belakangan terasa “sudah jelas”
  • Ada dugaan bahwa isu kali ini menjadi latar belakang mengapa akun Twitter ffmpeg baru-baru ini sampai mengeluarkan pernyataan terkait isu Rust, sambil membagikan tautan tweet tersebut https://x.com/ffmpeg/status/1924137645988356437?s=46
    • Setelah membaca akun Twitter ffmpeg, ada yang secara jujur merasa makin ragu menggunakan ffmpeg. Disayangkan karena nyaris tak ada alternatif, dan komunitas pengembangnya dianggap sangat toksik. Disebutkan bahwa performa maksimum memang penting, tetapi di lingkungan yang bertukar data dengan pihak luar, ffmpeg bisa menghadapi beberapa kerentanan jarak jauh (CVE) setiap tahun; dari sisi keamanan, sandbox yang ketat dianggap penting. Ada pendapat bahwa dibutuhkan titik tengah untuk membangun solusi yang cepat sekaligus aman, sambil membagikan tautan terkait https://ffmpeg.org/security.html
    • Ada usulan bahwa respons yang lebih baik adalah menjawabnya dengan peningkatan performa dav1d; digunakan analogi olahraga bahwa sekadar memperbaiki catatan waktu terasa kurang mengesankan dibanding benar-benar mencetak rekor baru. Penjelasan penutupnya bernada ringan: solusi yang sesungguhnya adalah hasil yang benar-benar cepat dan inovatif