2 poin oleh GN⁺ 2025-07-19 | 1 komentar | Bagikan ke WhatsApp
  • lsr adalah program pengganti ls(1) baru yang dikembangkan dengan memanfaatkan ourio, pustaka IO berbasis io_uring
  • Dibandingkan ls dan alat alternatif yang ada (eza, lsd, uutils ls), kecepatan eksekusi perintahnya sangat tinggi, dan jumlah system call-nya lebih dari 10x lebih sedikit
  • Dengan memproses semua IO utama seperti pembukaan direktori, stat, dan lstat secara asinkron dan batch dengan io_uring, performa dimaksimalkan. Semakin banyak file, semakin cepat keunggulannya terlihat
  • StackFallbackAllocator milik Zig digunakan untuk meminimalkan pemanggilan mmap saat alokasi memori
  • Dibangun secara statis tanpa dynamic linking, sehingga ukuran executable-nya bahkan lebih kecil daripada ls lama

Pengenalan dan signifikansi

  • Proyek lsr adalah alat listing direktori cepat yang memanfaatkan io_uring sebagai pengganti perintah ls biasa
  • Dibandingkan ls, eza, lsd, dan uutils ls, alat ini menunjukkan kinerja unggul dalam kecepatan eksekusi dan penggunaan system call
  • Sebisa mungkin menjalankan banyak IO secara langsung dengan pustaka io buatan sendiri, ourio
  • Melalui benchmark, lsr membuktikan performa cepat dan kualitasnya bahkan di lingkungan dengan file dalam jumlah besar

Hasil benchmark

  • Menggunakan hyperfine untuk mengukur waktu eksekusi tiap perintah pada direktori yang berisi n file biasa
    • lsr -al mencatat waktu eksekusi yang jauh lebih singkat dibanding ls/alat alternatif pada rentang 10–10.000 file
    • Contoh: pada 10.000 file, lsr mencatat 22,1ms, mengungguli ls lama (38,0ms), eza (40,2ms), lsd (153,4ms), dan uutils ls (89,6ms) sebagai yang tercepat
  • Agregasi system call dilakukan dengan strace -c
    • lsr -al: mempertahankan jumlah call yang sangat rendah, dari minimum 20 kali (n=10) hingga maksimum 848 kali (n=10.000)
    • ls mencapai maksimum 30.396 kali (n=10.000), lsd 100.512 kali, dan alternatif lain juga berada di kisaran ribuan hingga ratusan ribu
    • Dalam kondisi yang sama, lsr mencapai efisiensi terbaik dengan jumlah syscall setidaknya 10x lebih sedikit

Struktur dan cara implementasi lsr

  • Program berjalan dalam 3 tahap: parsing argumen, pengumpulan data, dan output data
  • Semua IO terjadi pada tahap kedua, yaitu pengumpulan data, dan semua akses file/pengambilan informasi yang memungkinkan diproses dengan io_uring
    • Pembukaan direktori target, stat, lstat, serta pengambilan informasi waktu/pengguna/grup semuanya dijalankan berbasis io_uring
    • stat diproses secara batch untuk memangkas jumlah system call secara drastis
  • Dengan Zig StackFallbackAllocator, memori 1MB dialokasikan lebih dulu untuk meminimalkan system call tambahan seperti mmap

Build statis dan optimasi

  • Karena merupakan build statis penuh tanpa dynamic linking libc, overhead eksekusinya sangat kecil
  • Dibanding GNU ls, ukuran build ReleaseSmall lsr lebih kecil, yaitu 138,7KB vs 79,3KB
  • Namun, lsr tidak mendukung locale (bahasa/wilayah). ls biasa memiliki overhead untuk mendukung berbagai bahasa

Analisis system call dan isu performa

  • lsd memanggil clock_gettime lebih dari 5 kali per file; alasannya tidak jelas (diduga untuk pengukuran timing internal, dll.)
  • Pekerjaan sorting mengambil porsi besar dari keseluruhan proses (sekitar 30%)
    • uutils ls efisien dari sisi system call, tetapi melambat pada pemrosesan sorting
  • Hanya dengan mengadopsi io_uring saja, terlihat potensi peningkatan performa yang revolusioner di lingkungan IO berbeban tinggi seperti server

Kesimpulan

  • Waktu pengembangannya pun tidak lama, dan efek optimasi syscall melebihi ekspektasi
  • lsr adalah pengganti ls eksperimental yang sekaligus mencapai kecepatan tinggi, sedikit system call, dan ukuran ringkas
  • Sangat cocok untuk lingkungan dengan file dalam jumlah besar atau sistem yang mengutamakan IO berperforma tinggi
  • Meski ada keterbatasan fitur seperti tidak adanya dukungan locale, hasilnya tetap inovatif baik dalam praktik maupun benchmark

1 komentar

 
GN⁺ 2025-07-19
Komentar Hacker News
  • Mengungkapkan bahwa dirinya adalah penulis proyek tersebut, sekaligus membagikan tulisan pengantar tentang lsr berbasis io_uring yang bisa dibaca di sini

    • Membagikan pengalaman pernah mengerjakan proyek I18N di Sun. Untuk mendukung berbagai lingkungan (lokalisasi, utf8, dll.), program perlu ditambahi banyak penanganan, sehingga terasa bahwa biaya untuk menghasilkan output dan kecepatan berbanding terbalik. Awalnya UNIX ls(1) sangat cepat karena desainnya sederhana, tetapi setelah ditambah berbagai fitur, virtual file system (VFS), beragam charset, dukungan warna, dan lain-lain, akumulasi biaya kecil itu membuatnya melambat. Menurutnya ini diskusi yang menarik tentang biaya abstraksi yang ditangani io_uring
    • Proyek bfs juga menggunakan io_uring (tautan kode sumber). Jadi menarik untuk membandingkan performa lsr dengan bfs -ls. Saat ini bfs hanya memakai io_uring saat multithreading, tetapi layak dipikirkan apakah bisa dimanfaatkan juga pada single thread (bfs -j1)
    • Jika mengukur waktu dengan tim (tautan pengantar), hasilnya mungkin akan lebih baik daripada hyperfine. Karena ditulis dengan Nim, ini bisa jadi tantangan, tetapi lucu juga bahwa namanya mirip, meski kebetulan
    • Sedang mempertimbangkan untuk mem-porting proyek C++ ke Zig. libevring buatannya sendiri juga masih tahap awal, jadi ia terbuka untuk menggantinya dengan ourio bila perlu. Menurutnya, jika proyek berbasis Zig mendukung binding C/C++, itu akan berguna saat bermigrasi dari C/C++ ke Zig
    • Karena tulisan pengantar tersebut menjelaskan latar belakang dengan lebih baik, ia berencana menjadikannya tautan utama, lalu menambahkan thread repo di atas
  • Penasaran bagaimana performa lsr pada server NFS, terutama dalam kondisi jaringan yang buruk. Sudah jelas bahwa penggunaan blocking POSIX syscall pada layanan jaringan yang tidak stabil adalah kelemahan desain NFS. Seberapa jauh io_uring bisa meredakan masalah ini juga menarik untuk diamati

    • Perancang NFS membuat sistem terdistribusi bekerja sangat konsisten layaknya hard drive. Keuntungannya, alat yang sudah ada (seperti ls) tidak perlu menangani langsung kondisi error jaringan. Protokol NFS awalnya stateless, jadi klien bisa pulih otomatis meski server reboot. Ia penasaran apakah io_uring meneruskan error dengan benar dalam kasus seperti ini. Ia juga tertarik bagaimana timeout NFS ditangani
    • Di rumah, ia memakai NFS $HOME dari beberapa PC, dan selama jaringannya baik serta menghindari kasus sulit seperti penulisan paralel, pengalaman penggunaan NFS secara umum cukup memuaskan. Namun saat kabel jaringan bermasalah, ia pernah kesulitan karena koneksi sering putus-putus
    • Sudah dikenal sebagai ketidaknyamanan bahwa pada aplikasi yang sedang membaca folder NFS, ctrl+c kadang tidak mempan. Secara teori, opsi mount intr mendukung penghentian dengan meneruskan sinyal ke operasi pada server jarak jauh yang sedang berjalan, tetapi di Linux ini sudah lama dihapus (dan sekarang pada dasarnya hanya ada opsi soft) (referensi1, referensi2(dukungan FreeBSD))
    • Samba juga punya masalah serupa
  • Menarik bahwa meskipun jumlah pemanggilan syscall berkurang 35 kali, peningkatan kecepatannya hanya sekitar 2 kali

    • Kebanyakan syscall dilakukan melalui VDSO, jadi biayanya tidak terlalu besar
    • Dalam benchmark terkait io_uring yang pernah ia baca dulu, syscall berbasis io_uring justru kadang terlihat lebih berat daripada syscall biasa. Meski begitu, secara terasa ini tetap peningkatan yang cukup besar. Ia tidak ingat sumber pastinya, tetapi kesannya masih membekas
  • Proyek ini lebih menarik sebagai contoh pemanfaatan io_uring untuk keuntungan performa jangka panjang yang diharapkan, atau sebagai tutorial penggunaannya. Dibanding alat yang sudah ada seperti eza, ia tidak merasa ada motivasi praktis yang kuat mengapa ini dibutuhkan. Kalau menjalankan daftar 10 ribu file bedanya 40ms vs 20ms, rasanya dalam sekali eksekusi orang tidak akan merasakan perbedaannya

    • Ini proyek eksperimental yang dibuat demi bersenang-senang sambil belajar cara memakai io_uring. Penghematan waktu praktisnya kecil sekali (mungkin total cuma menghemat 5 detik seumur hidup), dan itu memang bukan poin utamanya
    • Dalam praktiknya, pada direktori yang berisi jutaan file JSON, menjalankan ls/du bisa memakan waktu beberapa menit. Perintah dasar coreutils sering tidak mampu memanfaatkan performa SSD modern dengan baik
  • lsr memang bagus, tetapi dukungan pewarnaan dan ikon lebih unggul di eza. Ia memasang eza --icons=always -1, jadi file musik (.opus, dll.) otomatis tampil dengan ikon dan warna, sedangkan di lsr hanya terlihat sebagai file biasa. Meski begitu, lsr jelas terasa sangat cepat dan mudah di-patch. Ia juga berharap cat dan utilitas lain dibuat dengan pendekatan seperti ini, menganggap penggunaan tangled.sh dan atproto menarik, dan merasa Zig lebih mudah didekati pemula dibanding Rust

    • bat adalah pengganti cat modern (tautan ke bat)
    • Untuk dukungan warna, sepertinya yang terbaik adalah menerapkan cara standar seperti LS_COLORS/dircolors. Warna pada GNU ls terlihat bagus
  • Ia penasaran kenapa tidak semua alat CLI memakai io_uring. Saat menghubungkan nvme ke usb 3.2 gen2, dengan alat biasa kecepatannya 740MB/s, sedangkan dengan alat berbasis aio atau io_uring bisa naik sampai 1005MB/s. Menurutnya ini juga terkait strategi queue length dan pengurangan lock

    • Demi portabilitas, secara tradisional banyak program ditulis tanpa percabangan makro seperti #ifdef, sehingga adopsi teknologi baru yang spesifik platform/versi menjadi lambat. Sekarang ia merasa keuntungan kompatibilitas antar berbagai platform posixy tidak lagi sebesar dulu
    • Untuk memakai io_uring secara efisien, diperlukan model berbasis event asinkron. Kebanyakan alat CLI lama ditulis secara intuitif dan berurutan. Jika async terasa alami di tingkat bahasa, porting mungkin akan lebih mudah, tetapi saat ini dibutuhkan refactor besar. io_uring sendiri juga belum sepenuhnya matang, jadi mungkin orang akan menunggu teknologi baru lain, atau muncul alat porting otomatis/AI
    • Pada masa awal adopsinya, io_uring sempat punya isu keamanan besar (sekitar 2 tahun lalu). Sekarang banyak yang sudah diperbaiki, tetapi itu tetap berdampak buruk pada penyebarannya
    • io_uring sangat sulit dari sisi keamanan
    • Karena io_uring masih teknologi yang sangat baru, sedangkan coreutils (dan paket pendahulunya) punya sejarah puluhan tahun, adopsinya akan butuh waktu lebih lama. Agar sistem call bergaya “shared ring buffer” menjadi standar pengganti cara sinkron yang ada sekarang, memang perlu waktu
  • Dengan strace terlihat bahwa lsd memanggil clock_gettime sekitar 5 kali per file. Ia tidak tahu pasti penyebabnya; mungkin untuk menghitung “berapa menit/jam/hari yang lalu” untuk tiap timestamp, atau mungkin warisan dari library lama

    • Saat ini clock_gettime sebenarnya bukan syscall sungguhan, melainkan diproses lewat vDSO (lihat man 7 vDSO). Mungkin saja Zig tidak memanfaatkan struktur ini
  • Agak melenceng dari topik, tetapi ia ingin tahu pengalaman nyata atau angka benchmark tentang seberapa besar io_uring mengurangi overhead latensi socket dalam satuan mikrodetik dibanding LD_PRELOAD pada lingkungan 10G NIC di server enterprise kelas tinggi seperti Mellanox 4 atau 5. Tampaknya efek keduanya tidak saling menumpuk, jadi kalau ada pengalaman langsung ia ingin mendengar angkanya

  • Karena io_uring tidak mendukung getdents, keuntungan yang benar-benar terasa muncul pada bulk stat (misalnya ls -l). Ia merasa sayang karena akan bagus bila pemrosesan getdents bisa dibuat asinkron dan diproses tumpang tindih

    • Jika POSIX menstandarkan operasi NFS “readdirplus” (getdents + stat), maka sebagian keunggulan khas io_uring kemungkinan akan berkurang
  • Menurutnya lucu bahwa ada ikon untuk ekstensi .mjs dan .cjs, tetapi tidak ada untuk ekstensi file seperti .c, .h, atau .sh