- En yeni Sep 0.10.0 sürümü, AMD 9950X üzerinde 21 GB/s gibi dikkat çekici bir CSV ayrıştırma hızına ulaşıyor
- AVX-512 desteği ve maske yazmacı sorunlarının aşılmasıyla performans önemli ölçüde arttı
- Yeni AVX-512-to-256 ayrıştırıcısı, AVX2 ve mevcut AVX-512 ayrıştırıcılarını geride bırakan sonuçlar gösteriyor
- Çok iş parçacıklı ortamda 1 milyon satırı 72 ms'de işleyerek 8 GB/s bant genişliği kaydediyor
- Sürekli yazılım ve donanım optimizasyonu sayesinde 2 yılda yaklaşık 3 kat performans artışı sağlandı
Sep 0.10.0 sürümü ve performans artışına genel bakış
- Sep, yakın zamanda çıkan 0.10.0 sürümünde AVX-512 destekli CPU'lar (ör. AMD 9950X, Zen 5) için optimizasyon yaptı ve benchmark sonuçlarını güncelledi
- En son sürümde düşük seviyeli CSV ayrıştırmada 21 GB/s gibi olağanüstü bir sonuç elde edildi
- Bu, önceki sürümdeki 18 GB/s seviyesine kıyasla kayda değer bir artış anlamına geliyor
- İyileştirmelerin ayrıntıları Sep'in GitHub sürüm notlarında ve README dosyasında görülebilir
- Metin, .NET 9.0'ın AVX-512 makine kodundaki verimsizlikleri aşan SIMD tabanlı C# kodunu ve x64 SIMD assembly ile performansın nasıl artırıldığını açıklıyor
Sep'in performans gelişim süreci
- Sep'in ilk 0.1.0 sürümünden 0.10.0'a, .NET 7.0'dan 9.0'a ve AMD 5950X (Zen 3)'ten 9950X (Zen 5)'e uzanan gelişim görsel olarak gösteriliyor
- Benchmark'lar tek iş parçacığı bazında yapılıyor ve sürümler arasında küçük dalgalanmalar olabiliyor
- Temel mesaj, büyük refactor'ların (0.2.0'daki iç yapı yeniden yazımı gibi) ve küçük değişikliklerin birikimli optimizasyonlarla sürekli performans artışı sağlaması
- Donanım ve yazılımın birlikte gelişmesiyle ortalama 2 yıl içinde yaklaşık 3 kat iyileşmeyle 21 GB/s ayrıştırma hızına ulaşıldı
- Sadece donanım nesli değişimi bile (5950X→9950X, 4.9→5.7GHz) 1.2x'in üzerinde bir artışı açıklıyor
AVX-512 kod üretimi ve maske yazmacı sorunu
- Sep, 0.2.3'ten beri AVX-512 desteği sunuyordu ancak AVX-512'nin maske yazmaçlarını (k1-k8) kullanmada sınırlamalar vardı
- .NET 8'de maske yazmaçlarına doğrudan destek olmadığından, normal yazmaçlar arasında tekrarlanan kopyalama ve dönüştürmeler performansı düşürüyordu
- Ayrı bir AVX-512 destekli CPU bulunmayan ilk dönemde, Xeon Silver 4316 üzerinde sınırlı testler yapılarak bunun en hızlı seçenek olduğu doğrulandı
9950X yükseltmesi ve AVX-512 ile AVX2 karşılaştırması
- Yakın zamanda CPU Zen 3 (5950X)'ten Zen 5 (9950X)'e yükseltildiğinde, Sep benchmark'ları 18 GB/s seviyesine ulaştı
- AVX-512 ve AVX2 ayrıştırıcıları doğrudan karşılaştırıldığında, biraz şaşırtıcı biçimde AVX2'nin yaklaşık 20 GB/s ile AVX-512'den yaklaşık %10 daha hızlı olduğu görüldü
- Bu durum, .NET JIT'in maske yazmacı işleme verimsizliğinin hâlâ sorun olduğunu düşündürüyor
Ayrıştırıcı kodu, assembly analizi ve yeni AVX-512-to-256 ayrıştırıcısı
- Sep'teki tüm ayrıştırıcılar 16K boyutlu char span'leri işler ve SIMD yazmaçlarına (
Vector256 vb.) dayalı karşılaştırma işlemlerini kullanır
- SIMD ile özel karakterler (satır sonu, tırnak işareti, ayırıcı vb.) hızlıca belirlenir, ardından bit maskelerine dönüştürülerek küme işlemleri optimize edilir
- AVX-512 tabanlı ayrıştırıcı, maske yazmaçları (
k1 vb.) ile genel yazmaçlar (zmm vb.) arasında sürekli taşıma yaptığı için fazla ek iş üretmekteydi
- 0.10.0'da
MoveMask çağrısı öne alınarak gereksiz maske dönüşümleri en aza indirildi ve assembly komut sayısı azaltıldı
- AVX2 ayrıştırıcısında maske yazmacı olmadığı için yapı çok daha basit kaldı ve pratikte AVX-512'den daha hızlı oldu
- Yeni AVX-512-to-256 ayrıştırıcısı, veriyi AVX-512 ile okuyup 256 bit dönüşüm komutlarıyla maske işleme sorununu doğrudan by-pass ediyor; uygulama daha sade hale gelirken performans 21 GB/s'nin üzerine çıktı
Farklı ayrıştırıcı benchmark'larının özeti
- Ortam değişkeniyle tüm ayrıştırıcı türleri karşılaştırıldığında, AVX-512-to-256 ayrıştırıcısı 21.5 GB/s ile en hızlı sonuç verdi
- AVX2 tabanlı ve
Vector256 tabanlı ayrıştırıcılar da yalnızca %5 içinde kalarak çok yakın performans gösterdi
Vector128 ve Vector512 tabanlı ayrıştırıcılar AVX2'ye göre %5-10 daha yavaştı; özellikle Vector512, Vector128'den bile yavaştı
IndexOfAny ayrıştırıcısı diğer SIMD ayrıştırıcılarına göre belirgin biçimde daha yavaştı. Vector64 ise 9950X üzerinde hızlandırılmadığı için çok düşük performans gösterdi
- AVX-512 ve AVX2 tabanlı SIMD ayrıştırıcıları, benzer CSV ayrıştırıcılara kıyasla ezici bir performans ortaya koyuyor
Üst seviye benchmark: 5950X ve 9950X karşılaştırması
- 1 milyon paket varlığı satırı temel alındığında Sep_MT, 9950X üzerinde 72 ms (8GB/s), 5950X üzerinde ise 119 ms (4.9GB/s) değerlerine ulaştı
- Gerçek yük verilerinde de (float vb.) 9950X üzerinde çok iş parçacıklı olarak ~8GB/s bant genişliği elde edildi
- Nesil değişimiyle (5950X→9950X) gerçek uygulama ayrıştırmasında yaklaşık 1.5-1.6 kat iyileşme görüldü
- Rakip CSV kütüphanelerine (Sylvan, ReadLine, CsvHelper vb.) kıyasla çok daha yüksek throughput ve çok daha düşük kaynak tahsisi sergilendi
Sonuç ve özet
- Sep 0.10.0, yazılım optimizasyonu ile en yeni donanım özelliklerini (AVX-512, yüksek saat hızı) birleştirerek CSV ayrıştırma performans sınırlarını zorluyor
- Modern SIMD algoritma tasarımı, .NET JIT kodu ve assembly yapısındaki iyileştirmeler bu ilerlemenin merkezinde yer alıyor
- Kısa süre içinde görülen birikimli performans iyileşmesi ve mimari nesil değişiminin etkisi dikkat çekici
- Sep, CSV ayrıştırma alanında fiilen sektörün en üst düzeyinde yüksek performans, çoklu platform ve ölçeklenebilirlik sunuyor
1 yorum
Hacker News yorumları
'\n','\r',';','“') ve ardından üçorişlemi yapmak yerine, yaygın bir numarayla 1 kez shuffle, 1 kez karşılaştırma ve 0orişlemi yapılabilir. Bu numarayı anlattığım bir blog yazım var, bakabilirsiniz. Bu arada bu yazıda davpternlogdvevporişlemleriyleorsayısı azaltılmış.deflate). Bir zamanlar CSV'yi NIC kartı hızında Netflow verisi kusan bir kodla uğraşmıştım. Kişisel olarak bu kadar karmaşık iş yapılacaksa protocol buffers kullanmak daha mantıklı diye düşünüyorum. protobuf o kadar da zor bir format değil ama bir türlü yeterince benimsenmiyor.