- lsr, io_uring tabanlı IO kütüphanesi ourio kullanılarak geliştirilmiş yeni bir
ls(1) alternatifidir
- Mevcut
ls ve alternatif araçlara (eza, lsd, uutils ls) kıyasla komut çalıştırma hızı çok yüksektir ve sistem çağrısı sayısı 10 kattan fazla daha azdır
- Dizin açma,
stat, lstat gibi tüm temel IO işlemleri io_uring ile eşzamansız ve toplu olarak işlenerek performans en üst düzeye çıkarılır. Dosya sayısı arttıkça daha da hızlanır
- Bellek ayırmada
mmap çağrılarını en aza indirmek için Zig'in StackFallbackAllocator'ı kullanılır
- Dinamik bağlama olmadan statik olarak derlendiği için çalıştırılabilir dosya boyutu da mevcut
ls'ten daha küçüktür
Giriş ve önemi
- lsr projesi, standart
ls komutunun yerine geçebilecek ve io_uring kullanan hızlı bir dizin listeleme aracıdır
- Mevcut
ls, eza, lsd, uutils ls ile karşılaştırıldığında çalışma hızı ve sistem çağrısı kullanımı açısından üstün performans gösterir
- Mümkün olduğunca fazla IO işlemini doğrudan gerçekleştirmek için kendi geliştirdiği IO kütüphanesi olan ourio'yu kullanır
- Benchmark sonuçları, lsr'nin büyük ölçekli dosya ortamlarında da yüksek performans ve kalite sunduğunu gösterir
Benchmark sonuçları
hyperfine kullanılarak, içinde n adet normal dosya bulunan bir dizinde her komutun çalışma süresi ölçüldü
lsr -al, 10–10.000 dosya aralığında mevcut ls ve alternatiflerine göre açık ara daha kısa çalışma süresi kaydetti
- Örnek: 10.000 dosyada lsr 22.1ms ile, mevcut
ls (38.0ms), eza (40.2ms), lsd (153.4ms), uutils ls (89.6ms) karşısında en yüksek hızı gösterdi
- Sistem çağrısı sayımı
strace -c ile yapıldı
lsr -al: en az 20 çağrıdan (n=10) en fazla 848 çağrıya (n=10.000) kadar çıkarak çok düşük bir çağrı sayısını korudu
ls, en fazla 30.396 çağrıya (n=10.000), lsd ise 100.512 çağrıya ulaştı; diğer alternatifler de binlerce ila yüz binlerce çağrı düzeyindeydi
- Aynı koşullarda lsr, en az 10 kat daha az syscall sayısıyla en yüksek verimliliği sağladı
lsr'nin yapısı ve uygulama yöntemi
- Program argüman ayrıştırma, veri toplama, veri çıktısı olmak üzere 3 aşamada çalışır
- Tüm IO işlemleri ikinci aşama olan veri toplama sırasında gerçekleşir ve mümkün olan tüm dosya erişimi/bilgi sorgulamaları io_uring ile yapılır
- Hedef dizinin açılması,
stat, lstat, zaman/kullanıcı/grup bilgisi sorguları dahil her şey io_uring tabanlı yürütülür
stat işlemlerinin toplu yapılması, sistem çağrısı sayısını çarpıcı biçimde azaltır
- Zig StackFallbackAllocator ile 1MB bellek önceden ayrılarak
mmap gibi ek sistem çağrıları en aza indirilir
Statik derleme ve optimizasyon
- libc dinamik bağlaması olmadan tamamen statik derlendiği için çalışma ek yükü belirgin biçimde düşüktür
- GNU
ls ile karşılaştırıldığında lsr'nin ReleaseSmall derleme boyutu 138.7KB'ye karşı 79.3KB ile daha küçüktür
- Ancak lsr'de locale (dil/bölge) desteği yoktur. Standart
ls, farklı dilleri desteklemek için ek yük taşır
Sistem çağrıları ve performans sorunlarının analizi
lsd, dosya başına clock_gettime'ı 5 kereden fazla çağırıyor; nedeni belirsiz (iç zamanlama ölçümü vb. tahmin ediliyor)
- Sıralama (sorting) işlemi, toplam işin önemli bir kısmını (yaklaşık %30) oluşturuyor
uutils ls, sistem çağrısı verimliliği yüksek olsa da sıralama işlemlerinde yavaşlıyor
- Yalnızca io_uring kullanımıyla bile sunucular gibi yüksek IO yüküne sahip ortamlarda çarpıcı performans artışı potansiyeli doğrulanmış oldu
Sonuç
- Geliştirme süresi de çok uzun sürmedi ve syscall optimizasyonunun etkisi beklenenden büyüktü
- lsr, yüksek hız, az sistem çağrısı ve kompakt boyutu aynı anda sağlayan deneysel bir
ls alternatifidir
- Büyük hacimli dosya ortamları veya yüksek performanslı IO'nun önemli olduğu sistemler için çok uygundur
locale desteği olmaması gibi bazı işlevsel sınırlara rağmen hem pratik kullanımda hem de benchmarklarda yenilikçi sonuçlar gösterir
1 yorum
Hacker News görüşleri
Projenin yazarı olduğunu belirtiyor ve io_uring tabanlı
lsriçin tanıtım yazısının burada okunabileceğini söylüyortim'in (tanıtım bağlantısı) hyperfine'dan daha iyi olabileceğini düşünüyor. Nim ile yazılmış olması zorlayıcı olabilir ama isim benzerliğini tesadüfi olmaktan öte eğlenceli buluyorNFS sunucusunda (özellikle iyi olmayan ağ koşullarında) lsr'nin performansının nasıl olacağını merak ediyor. Güvenilmez ağ hizmetlerinde blocking POSIX syscall kullanmanın NFS tasarımının bariz bir zayıflığı olduğunu düşünüyor. io_uring'in bu tür sorunları ne kadar hafifletebildiği de gözlemlemek istediği bir nokta
syscall çağrı sayısını 35 kat azaltmasına rağmen hız artışının yaklaşık 2 katla sınırlı kalması ilginç bulunuyor
Bunu, io_uring kullanımına dair beklenen uzun vadeli hız kazancı örneğinden çok, bir tutorial veya kullanım örneği olarak daha ilgi çekici buluyor. Mevcut eza gibi araçlara kıyasla bunun neden gerekli olduğuna dair sezgisel motivasyonu olmadığını söylüyor. On bin dosyalık bir listenin 40ms yerine 20ms sürmesi, tek çalıştırma açısından ona göre hissedilir bir fark yaratmaz
lsr güzel olsa da renkler ve ikon desteğinde eza'nın daha iyi olduğunu söylüyor. Kendisinin ayarı "eza --icons=always -1" olduğu için müzik dosyaları (.opus vb.) otomatik olarak ikon ve renklerle görünüyor, ama lsr'de sadece sıradan dosya gibi görünüyor. Yine de lsr'nin hem kolay yamalanabildiğini hem de çok hızlı olduğunu açıkça hissettiğini belirtiyor. Ayrıca cat ve diğer yardımcı araçların da bu şekilde yapılmasını istediğini, tangled.sh ve atproto kullanımını da ilginç bulduğunu söylüyor. Zig ile yazılmış olmasının da bir acemi olarak Rust'tan daha erişilebilir hissettirdiğini ekliyor
Neden tüm CLI araçlarının io_uring kullanmadığını merak ettiğini söylüyor. Kendi deneyiminde nvme'yi usb 3.2 gen2'ye bağladığında sıradan araçlarla hız 740MB/s iken, aio veya io_uring tabanlı araçlarla 1005MB/s'ye çıktığını aktarıyor. Bunun kuyruk uzunluğu stratejisi ya da lock azaltma etkileriyle ilişkili olabileceğini düşünüyor
strace ile bakıldığında lsd'nin dosya başına yaklaşık 5 kez clock_gettime çağırdığı görülüyor. Bunun nedenini tam bilmiyor; muhtemelen her zaman damgası için “kaç dakika/saat/gün önce” hesabı yapıyordur ya da bir kütüphane mirası olabilir
man 7 vDSO'ya bakılabilir). Acaba zig bu yapıyı kullanmıyor olabilir mi diye düşünüyorKonudan biraz sapıyor olabilir ama Mellanox 4 veya 5 gibi üst düzey kurumsal sunucularda, 10G NIC ortamında io_uring'in LD_PRELOAD'a kıyasla soket gecikmesi overhead'ini mikrosaniye düzeyinde ne kadar azalttığına dair gerçek deneyim veya benchmark sayıları merak ediyor. Etkilerin birbirine eklenmediği anlaşılıyor; doğrudan deneyimi olan birinin rakam paylaşmasını isterdi
io_uring getdents'i desteklemediği için asıl fayda bulk stat işlemlerinde (ör. ls -l) görülüyor. getdents işini asenkronlaştırıp üst üste bindirmek mümkün olsa daha iyi olurdu diye düşünüyor
.mjs ve .cjs uzantıları için ikon olmasına rağmen, .c, .h, .sh gibi dosya uzantıları için olmamasını ilginç buluyor