2 puan yazan GN⁺ 2026-01-08 | 1 yorum | WhatsApp'ta paylaş
  • Yakın zamanda tartışılan I/O performansı ile CPU işlem hızı arasındaki dengesizlik deneylerle doğrulanıyor ve gerçekte ana kısıtın hâlâ CPU olduğu gösteriliyor
  • Sıralı okuma hızı, soğuk önbellekte 1.6GB/s, sıcak önbellekte 12.8GB/s seviyesine ulaşsa da, tek iş parçacıklı kelime frekansı hesabı yalnızca 278MB/s düzeyinde kalıyor
  • Koddaki dal (branch) yapısı vektörleştirmeyi (vectorization) engelliyor ve yalnızca basit bir küçük harfe dönüştürme optimizasyonuyla bile ancak yaklaşık 330MB/s seviyesine çıkılabiliyor
  • wc -w komutu bile yalnızca 245MB/s olduğundan, darboğazın diskten çok CPU hesaplaması ve dal işleme olduğu doğrulanıyor
  • AVX2 tabanlı elle vektörleştirme ile hız 1.45GB/s seviyesine çıkarıldı, ancak bu bile hâlâ sıralı okuma hızının yaklaşık %11'i düzeyinde; böylece darboğazın I/O değil, CPU olduğu kanıtlanıyor

I/O hızı ile CPU performansının karşılaştırılması

  • Ben Hoyt'un iddiasından yola çıkılarak, son dönemdeki sıralı okuma hızı artışının CPU hızındaki durgunluğu geçip geçmediği test ediliyor
    • Aynı yöntemle ölçüldüğünde soğuk önbellekte 1.6GB/s, sıcak önbellekte 12.8GB/s elde edildi
  • Ancak tek iş parçacığında kelime frekansı hesabı yapıldığında hız yalnızca 278MB/s oldu
    • Bu, önbellek sıcak olsa bile disk okuma hızının yaklaşık beşte biri düzeyinde

C tabanlı kelime frekansı hesaplama deneyi

  • optimized.c, GCC 12 ile -O3 -march=native seçenekleri kullanılarak derlenip 425MB giriş dosyasında çalıştırıldı
    • Sonuç: 1.525 saniye, 278MB/s işlem hızı
  • Kod içindeki çoklu dallar ve erken çıkışlar, derleyicinin vektörleştirme optimizasyonunu engelliyor
    • Küçük harfe dönüştürme mantığı döngü dışına taşındıktan sonra hız 330MB/s seviyesine çıktı
    • Clang kullanıldığında vektörleştirme daha iyi yapılıyor

Basit kelime sayımı (wc -w) karşılaştırması

  • Frekans hesabı yerine yalnızca toplam kelime sayısını sayan wc -w komutu çalıştırıldı
    • Sonuç: 245.2MB/s, beklenenden yavaş
  • wc, ' ', '\n', '\t' gibi çeşitli boşluk karakterlerini ve yerel ayar karakterlerini işliyor
    • Bu yüzden yalnızca boşluğu ayırıcı kabul eden koda göre daha fazla işlem yapıyor

AVX2 tabanlı vektörleştirme denemesi

  • Modern CPU özelliklerinden yararlanılarak AVX2 komut kümesi ile vektörleştirme uygulandı
    • 256 bit yazmaç kullanıldı, veri 32 bit hizalandı
    • Boşluk karakteri karşılaştırmaları için VPCMPEQB komutu kullanıldı
  • Bit maskesi (PMOVMSKB) ve Find First Set (ffs) komutlarıyla kelime sınırları tespit edildi
    • Fikir, Cosmopolitan libc içindeki strlen uygulamasından alındı

Performans sonuçları ve sonuç

  • Elle vektörleştirilmiş kod (wc-avx2) 1.45GB/s işlem hızına ulaştı
    • wc -w ile aynı sonuç (82,113,300 kelime) doğrulandı
  • Soğuk önbellek durumunda bile hâlâ user modundaki işlem süresi baskın
    • Darboğazın disk I/O'sundan çok CPU hesaplaması olduğu doğrulandı
  • Genel olarak disk hızı yeterince yüksek, ancak dal işleme ve hash hesaplama gibi CPU işlemleri sınırlayıcı etken olmaya devam ediyor
  • Kod ve deney sonuçları GitHub'da (haampie/wc-avx2) yayımlandı

1 yorum

 
GN⁺ 2026-01-08
Hacker News yorumları
  • Modern CPU'larda performans sınırının, tek bir çekirdeğin işleyebildiği veri miktarı, yani memcpy() hızı tarafından belirlendiğini düşünüyor
    Çoğu x86 çekirdeği yaklaşık 6GB/s, Apple M serisi ise yaklaşık 20GB/s seviyesinde
    Reklamlarda söylenen “200GB/s” gibi rakamlar yalnızca tüm çekirdeklerin toplam bant genişliği; tek çekirdek hâlâ 6GB/s civarında kalıyor
    Bu nedenle mükemmel bir parser yazsanız bile bu sınırı aşamazsınız
    Ancak zero-copy formatlar kullanılırsa CPU gereksiz verileri atlayabildiği için teorik olarak 6GB/s'nin “üzerine” çıkılabilir
    Geliştirdiği Lite³ formatı bu ilkeyi kullanıyor ve simdjson'dan 120 kata kadar daha hızlı performans gösteriyor

    • Verilen tek çekirdek rakamlarının fazla düşük olduğunu düşünüyor
      Örneğin Zen 1 tek çekirdekte 25GB/s gösteriyor (referans bağlantı)
      Kendisinin yazdığı microbenchmark sonuçlarına göre Zen 2, AVX kullanılmadığında 17GB/s, non-temporal AVX kullanıldığında ise 35GB/s'ye kadar çıkıyor
      Apple M3 Max'te non-temporal NEON ile 125GB/s'ye kadar ölçülmüş
      Dolayısıyla x86 için 6GB/s, Apple için 20GB/s rakamları gerçeğin oldukça altında
    • Bu sınırın kaynağını merak ediyor — çekirdek ile cache ya da bellek denetleyicisi arasındaki veri yolu yapısından mı geldiğini soruyor
    • Apple M serisinin neden x86'dan çekirdek başına 3 kat daha yüksek bant genişliğine sahip olduğunu merak ediyor
    • Modern çiplerde yalnızca CPU ile bellek bant genişliğini doyurmak zor; bunu başarmak için iGPU kullanmak gerekiyor
      Çünkü iGPU birleşik belleğe erişebiliyor
      Bu yüzden büyük bellek kopyalamaları, paralel parsing, sıkıştırma/açma gibi işlerde iGPU'yu bir blitter olarak kullanmak teknik açıdan avantajlı
      Yine de zero-copy formatlarda sözü edilen “atlama” cache line düzeyinde gerçekleşiyor
    • Samsung NVMe SSD'lerin 14GB/s okuma hızı reklamı yaptığını, CPU tek çekirdeği 6GB/s ise bununla ilişkinin ilginç olduğunu söylüyor
  • Orijinal yazının yazarının time komutunun çıktısını yanlış yorumlamış gibi göründüğünü söylüyor
    system zamanı, kernelin süreç adına kullandığı CPU süresidir
    Örnekte real 0.395s, user 0.196s, sys 0.117s ise CPU toplamda yalnızca 313ms çalışmış, kalan 82ms ise boşta kalmıştır
    Yani disk alt sisteminden daha hızlı çalışmış olsa da aradaki fark büyük değildir
    Ayrıca I/O yolu CPU-bound durumda — disk ve kod sonsuz hızlı olsa bile kernel I/O kodunu çalıştırmak için 117ms gerekir

  • Yazının yazarı kendisi olduğunu ve bir devam yazısı bulunduğunu söylüyor: I/O is no longer the bottleneck, part 2

    • Geçmişte bir kelime frekansı hesaplama yarışmasına katıldığını söylüyor
      Katılımcıların kullandığı çeşitli optimizasyon tekniklerini ele alan analiz yazısını ilgi çekici buluyor
      Problemin karmaşıklığına veya boşluk karakteri sınıflandırmalarının sayısına göre yaklaşım değişmiş
    • Eğer bu test tek çekirdekte yapıldıysa, yukarıda öne sürülen “6GB/s sınırı” deneysel olarak çürütülmüş oluyor
  • Performans darboğazının her zaman “CPU mu I/O mu” gibi tek bir etken değil, gerçek iş yükünde ilk önce doygunluğa ulaşan kaynak olduğunu söylüyor
    Bu kaynak CPU, bellek bant genişliği, cache, disk, ağ, lock ya da gecikme olabilir
    Bu yüzden ölçmek, profiling ile kanıtlamak ve değişiklikten sonra yeniden ölçmek gerekir

  • Sorunun CPU ya da I/O değil, latency ile throughput arasındaki denge olduğunu söylüyor
    Çoğu yazılım gecikmeyi göz ardı ettiği için yavaş
    Veriyi bellekte doğrusal yerleştirmek ya da batch processing ve paralellik uygulamak çok daha yüksek hız sağlayabilir

  • CPU ↔ cache ↔ kalıcı depolama yapısından oluşan bir mimari hayal ediyor
    Eğer mmap() malloc() ile aynı performans özelliklerine sahip olsaydı, program belleği dosya adıyla tanımlanıp kalıcılık OS'e bırakılabilirdi
    Hâlâ birçok yazılım tasarımı sabit disk çağının kısıtlarına bağlı durumda

    • Ancak fsync() hâlâ yavaş
      Gerçek kalıcılık için döner disk olup olmamasından bağımsız olarak farklı bir yaklaşım gerekiyor
    • Linux'ta da benzer bir şey yapılabileceğini söylüyor
      Nitekim çoğu bellek isteği mmap() üzerinden gerçekleşiyor
      Ancak kernel erişim desenlerini tahmin etmekte zorlandığı için read/write'dan daha yavaş olabilir
  • Bulut ortamında performans bazen fiyatlandırmayı ayarlama aracı hâline gelebiliyor
    Donanım performansı şaşırtıcı derecede ilerledi ama bazı yazılımlar, özellikle Windows ya da mesajlaşma uygulamaları, buna rağmen daha yavaş hissediliyor

    • Gerçekte bulut instance performansı M1 MacBook'tan 5 kat daha yavaşken çok daha pahalı
      Geliştirici uzaktan çalışma istasyonu olarak verimsiz
    • Çoğu GUI uygulamasının yavaş olmasının nedeni hâlâ I/O beklemesi
      Telegram ve FB Messenger hızlı, ama Teams ve Skype öyle değil
    • CRT monitörler veriyi daha hızlı gösterirdi
      Bazı LCD'lerde 500ms gecikme var
  • NVMe SSD'ler ilk çıktığında “artık 2TB RAM'imiz var” diye şaka yaptığını söylüyor
    Ancak bugün GPU sunucuları gerçekten 2TB RAM taşıyor — etkileyici bir mühendislik başarısı

    • Geçmişte ikinci el bir Epyc sunucuda 2TB DDR4 RAM yapılandırmasını 5 bin dolara gördüğünü söylüyor
      Keşke o zaman alsaydım diye hayıflanıyor
  • OLAP veritabanı optimizasyonunu yüksek eşzamanlılık ortamında yapma deneyimine göre darboğaz çoğunlukla bellek hızıydı

  • I/O darboğazı kavramının aslında ardışık okuma ile değil, seek süresiyle ilişkili olduğunu söylüyor
    Yazının ana fikrini anladığını ama bu noktayı belirtmek istediğini ekliyor

    • CXL/PCIe gibi modern teknolojiler sayesinde artık RAM ve bellek denetleyicisi de bir tür I/O aygıtı sayılabilir
    • Geçmişteki veritabanı derslerinde I/O performansı sabit diskin seek süresiyle ölçülürdü
      Ardışık okuma hızı kodla iyileştirilemediği için asıl önemli olan ardışık olmayan erişimin optimize edilmesiydi