2 poin oleh GN⁺ 2026-01-08 | 1 komentar | Bagikan ke WhatsApp
  • Ketimpangan antara kinerja I/O dan kecepatan pemrosesan CPU yang belakangan dibahas diuji lewat eksperimen, dan ditunjukkan bahwa pada praktiknya CPU masih menjadi batas utama
  • Kecepatan baca sekuensial mencapai 1.6GB/s pada cold cache dan 12.8GB/s pada warm cache, tetapi perhitungan frekuensi kata pada single-thread hanya berada di kisaran 278MB/s
  • Struktur branch dalam kode menghambat vectorization, dan bahkan dengan optimasi sederhana pada konversi huruf kecil pun hanya meningkat menjadi sekitar 330MB/s
  • Bahkan perintah wc -w hanya mencapai 245MB/s, menegaskan bahwa komputasi CPU dan pemrosesan branch, bukan disk, adalah bottleneck
  • Dengan vectorization manual berbasis AVX2, throughput berhasil dinaikkan hingga 1.45GB/s, tetapi itu masih hanya sekitar 11% dari kecepatan baca sekuensial, membuktikan bahwa bottleneck ada pada CPU, bukan I/O

Perbandingan kecepatan I/O dan kinerja CPU

  • Mengikuti klaim Ben Hoyt, dilakukan eksperimen untuk melihat apakah peningkatan kecepatan baca sekuensial belakangan ini telah melampaui stagnasi kecepatan CPU
    • Dengan metode pengukuran yang sama, tercatat 1.6GB/s pada cold cache dan 12.8GB/s pada warm cache
  • Namun, saat menjalankan perhitungan frekuensi kata pada single-thread, throughput-nya hanya 278MB/s
    • Ini berarti bahkan saat cache sudah hangat, kecepatannya hanya sekitar seperlima dari kecepatan baca disk

Eksperimen perhitungan frekuensi kata berbasis C

  • Dengan GCC 12, optimized.c dikompilasi menggunakan opsi -O3 -march=native lalu dijalankan pada file input 425MB
    • Hasil: membutuhkan 1.525 detik, dengan throughput 278MB/s
  • Banyak branch dan early exit dalam kode menghambat optimasi vectorization oleh compiler
    • Setelah logika konversi huruf kecil dipindahkan ke luar loop, throughput naik menjadi 330MB/s
    • Saat memakai Clang, vectorization berjalan lebih baik

Perbandingan dengan penghitung kata sederhana (wc -w)

  • Menjalankan perintah wc -w, yang hanya menghitung jumlah kata alih-alih frekuensinya
    • Hasil: 245.2MB/s, lebih lambat dari perkiraan
  • wc menangani berbagai karakter spasi seperti ' ', '\n', '\t' serta karakter locale
    • Karena itu beban komputasinya lebih besar dibanding kode yang hanya membedakan spasi sederhana

Upaya vectorization berbasis AVX2

  • Dengan memanfaatkan fitur CPU modern, implementasi vectorization dibuat menggunakan instruction set AVX2
    • Menggunakan register 256-bit, dengan data disejajarkan ke 32-bit
    • Untuk membandingkan karakter spasi digunakan instruksi VPCMPEQB
  • Deteksi batas kata dilakukan memakai bit mask (PMOVMSKB) dan instruksi Find First Set (ffs)
    • Pendekatannya terinspirasi dari implementasi strlen di Cosmopolitan libc

Hasil performa dan kesimpulan

  • Kode vectorization manual (wc-avx2) mencapai throughput 1.45GB/s
    • Diverifikasi menghasilkan nilai yang sama dengan wc -w (82,113,300 kata)
  • Bahkan pada kondisi cold cache, waktu komputasi di mode user tetap mendominasi
    • Ini menegaskan bahwa bottleneck ada pada komputasi CPU, bukan disk I/O
  • Secara keseluruhan, kecepatan disk sudah cukup tinggi, tetapi pemrosesan branch dan perhitungan hash di CPU tetap menjadi faktor pembatas
  • Kode dan hasil eksperimen dipublikasikan di GitHub (haampie/wc-avx2)

1 komentar

 
GN⁺ 2026-01-08
Komentar Hacker News
  • Saya berpikir bahwa batas performa CPU modern ditentukan oleh jumlah data yang bisa diproses satu inti, yakni kecepatan memcpy()
    Sebagian besar inti x86 berada di kisaran 6GB/s, sedangkan seri Apple M di kisaran 20GB/s
    Angka seperti ‘200GB/s’ yang disebut dalam iklan hanyalah bandwidth gabungan semua inti; satu inti sendiri masih tetap berada di sekitar 6GB/s
    Jadi meskipun menulis parser yang sempurna, batas ini tetap tidak bisa dilampaui
    Namun, dengan memakai format zero-copy, CPU bisa melewati data yang tidak perlu sehingga secara teori bisa ‘melampaui’ 6GB/s
    Format Lite³ yang sedang saya kembangkan memanfaatkan prinsip ini dan menunjukkan performa hingga 120 kali lebih cepat daripada simdjson

    • Saya rasa angka untuk satu inti yang diajukan terlalu rendah
      Misalnya, Zen 1 menunjukkan 25GB/s pada satu inti(tautan referensi)
      Menurut hasil microbenchmark yang saya tulis, Zen 2 mencapai 17GB/s tanpa AVX dan hingga 35GB/s dengan non-temporal AVX
      Pada Apple M3 Max, terukur hingga 125GB/s dengan non-temporal NEON
      Jadi angka 6GB/s untuk x86 dan 20GB/s untuk Apple jauh lebih rendah dari kondisi nyata
    • Saya penasaran dari mana batas ini berasal — apakah karena struktur bus antara inti dan cache, atau dengan pengendali memori
    • Saya penasaran mengapa seri Apple M memiliki bandwidth per inti 3 kali lebih tinggi daripada x86
    • Pada chip modern, CPU saja sulit untuk membuat bandwidth memori jenuh; itu baru mungkin dengan memanfaatkan iGPU
      Karena iGPU bisa mengakses memori terpadu
      Jadi untuk pekerjaan seperti penyalinan memori berukuran besar, parsing paralel, atau kompresi/dekompresi, secara teknis lebih menguntungkan memanfaatkan iGPU sebagai blitter
      Namun, ‘melewati’ yang dimaksud dalam format zero-copy tetap terjadi pada satuan cache line
    • Samsung mengiklankan SSD NVMe dengan kecepatan baca 14GB/s, jadi jika satu inti CPU hanya 6GB/s, hubungan antara keduanya terasa menarik
  • Sepertinya penulis asli salah menafsirkan keluaran perintah time
    Waktu system adalah waktu CPU yang dipakai kernel atas nama proses
    Dalam contoh itu, jika real 0.395s, user 0.196s, dan sys 0.117s, maka CPU total hanya bekerja selama 313ms, dan 82ms sisanya berada dalam keadaan idle
    Artinya, memang bekerja lebih cepat daripada subsistem disk, tetapi selisihnya tidak besar
    Selain itu, jalur I/O berada dalam kondisi CPU-bound — bahkan jika disk dan kodenya tak terbatas cepat, eksekusi kode I/O kernel tetap membutuhkan 117ms

  • Saya penulis artikel itu. Ada lanjutan: I/O is no longer the bottleneck, part 2

    • Dulu saya pernah ikut kompetisi menghitung frekuensi kata
      Tulisan analisis yang membahas berbagai teknik optimasi yang dipakai peserta menarik untuk dibaca
      Pendekatannya berbeda tergantung kompleksitas masalah dan jumlah klasifikasi karakter spasi
    • Jika pengujian ini dijalankan pada satu inti, maka klaim “batas 6GB/s” di atas berarti sudah terbantahkan secara eksperimental
  • Bottleneck performa bukan selalu satu faktor tunggal seperti “CPU atau I/O”, melainkan sumber daya yang pertama kali jenuh dalam workload nyata
    Bisa CPU, bandwidth memori, cache, disk, jaringan, lock, latensi, dan lain-lain
    Karena itu, harus diukur, dibuktikan lewat profiling, lalu diukur lagi setelah perubahan

  • Masalahnya bukan CPU atau I/O, melainkan keseimbangan antara latensi dan throughput
    Sebagian besar perangkat lunak lambat karena mengabaikan latensi
    Jika data ditata secara linear di memori, atau diterapkan batch processing dan paralelisasi, hasilnya bisa jauh lebih cepat

  • Saya membayangkan arsitektur yang hanya terdiri dari CPU ↔ cache ↔ penyimpanan non-volatil
    Jika mmap() punya karakteristik performa yang sama dengan malloc(), program mungkin bisa menetapkan nama file sebagai memori dan menyerahkan persistensi kepada OS
    Banyak desain perangkat lunak masih terikat pada keterbatasan era hard disk

    • Tetapi fsync() tetap lambat
      Untuk persistensi yang sesungguhnya, pendekatan lain tetap diperlukan terlepas dari apakah medianya disk berputar atau bukan
    • Di Linux, hal serupa juga bisa diimplementasikan
      Faktanya, sebagian besar permintaan memori memang terjadi lewat mmap()
      Hanya saja, kernel sulit memprediksi pola akses sehingga bisa lebih lambat daripada read/write
  • Di lingkungan cloud, performa kadang juga menjadi alat untuk mengatur harga paket
    Performa hardware berkembang secara luar biasa, tetapi sebagian perangkat lunak (terutama Windows atau aplikasi messenger) justru terasa makin lambat

    • Dalam praktiknya, performa instance cloud 5 kali lebih lambat daripada M1 MacBook tetapi jauh lebih mahal
      Tidak efisien untuk workstation jarak jauh bagi developer
    • Alasan sebagian besar aplikasi GUI masih lambat tetap karena menunggu I/O
      Telegram atau FB Messenger cepat, tetapi Teams atau Skype tidak
    • Monitor CRT menampilkan data lebih cepat
      Beberapa LCD memiliki latensi 500ms
  • Saat SSD NVMe pertama kali muncul, saya pernah bercanda, “sekarang rasanya seperti punya RAM 2TB”
    Tapi sekarang server GPU benar-benar dilengkapi RAM 2TB — pencapaian engineering yang luar biasa

    • Saya pernah melihat konfigurasi server Epyc bekas dengan 2TB RAM DDR4 seharga 5.000 dolar
      Sekarang saya menyesal tidak membelinya saat itu
  • Berdasarkan pengalaman mengoptimalkan database OLAP di lingkungan dengan konkurensi tinggi, bottleneck-nya sebagian besar adalah kecepatan memori

  • Bottleneck I/O awalnya bukan terkait pembacaan sekuensial, melainkan waktu seek
    Saya paham inti artikelnya, tetapi poin ini tetap ingin saya tekankan

    • Berkat teknologi modern seperti CXL/PCIe, sekarang RAM dan pengendali memori juga bisa dianggap sebagai semacam perangkat I/O
    • Dulu, di kelas database, performa I/O diukur dari waktu seek hard disk
      Kecepatan baca sekuensial tidak bisa diperbaiki lewat kode, jadi inti utamanya adalah optimasi akses non-sekuensial