18 poin oleh GN⁺ 2025-12-23 | 1 komentar | Bagikan ke WhatsApp
  • Saat men-debug masalah latensi pada sistem terdistribusi, hal pertama yang harus diperiksa adalah pengaturan TCP_NODELAY
  • Algoritme Nagle adalah pendekatan yang diusulkan dalam RFC896 pada 1984, dirancang untuk mengurangi overhead header TCP saat mengirim paket-paket kecil
  • Namun, ketika digabungkan dengan mekanisme delayed ACK, pengiriman data tertunda hingga ACK diterima, sehingga memperburuk kinerja aplikasi yang sensitif terhadap latensi
  • Di lingkungan data center modern, RTT sangat pendek, dan sebagian besar sistem sudah mengirim pesan besar, sehingga manfaat algoritme Nagle hampir hilang sepenuhnya
  • Karena itu, pada sistem terdistribusi modern TCP_NODELAY seharusnya diaktifkan secara default, dan algoritme Nagle tidak lagi diperlukan

Latar belakang algoritme Nagle

  • RFC896 karya John Nagle pada 1984 diusulkan untuk menyelesaikan masalah overhead 4000%: 1 byte data dibanding 40 byte header yang muncul saat mengirim data kecil seperti input keyboard
    • Masalah saat itu adalah paket-paket kecil dikirim setiap kali pengguna mengetik satu karakter, sehingga efisiensi jaringan menurun
    • Solusinya adalah membatasi agar segmen baru tidak dikirim selama data sebelumnya belum di-ACK
  • Pendekatan ini efektif pada lingkungan jaringan saat itu, tetapi tidak cocok untuk sistem modern yang mengutamakan latensi
Iklan

Interaksi algoritme Nagle dan delayed ACK

  • Delayed ACK (RFC813, RFC1122) adalah mekanisme di mana pihak penerima tidak langsung mengirim ACK, melainkan menundanya sampai ada data balasan atau timer habis
  • Algoritme Nagle berhenti mengirim sambil menunggu ACK, dan delayed ACK menunda ACK, sehingga terjadi deadlock karena kedua sisi saling menunggu
  • John Nagle sendiri menyebut kombinasi ini sebagai “kombinasi yang mengerikan”, dan menunjukkan bahwa kedua fitur ini diperkenalkan secara terpisah tetapi menimbulkan latensi saat dipakai bersama

Masalah di lingkungan modern

  • RTT di dalam data center sekitar 500μs, dan bahkan dalam region yang sama pun hanya beberapa milidetik
  • Dalam lingkungan seperti ini, menunda transmisi selama satu RTT saja sudah menyebabkan kehilangan performa
  • Selain itu, sistem terdistribusi modern sudah mengirim pesan yang cukup besar karena adanya TLS, serialisasi, dan overhead protokol, sehingga masalah paket satu byte hampir tidak lagi ada
  • Optimasi untuk pesan kecil kini ditangani di lapisan aplikasi

Mengapa TCP_NODELAY diperlukan

  • Pada sistem terdistribusi yang sensitif terhadap latensi, disarankan mengaktifkan TCP_NODELAY untuk menonaktifkan algoritme Nagle
    • Ini bukan pilihan yang “tidak efisien” atau “salah konfigurasi”, melainkan keputusan yang sesuai dengan karakteristik hardware dan lalu lintas modern
  • Penulis berpendapat bahwa TCP_NODELAY seharusnya menjadi nilai default
    • Sebagian kode yang “mengirim pada setiap pemanggilan write()” mungkin menjadi lambat, tetapi kode seperti itu memang harus diperbaiki secara mendasar
    Iklan

Opsi terkait lainnya

  • Opsi TCP_QUICKACK memang mengurangi penundaan ACK, tetapi bukan solusi mendasar karena masalah portabilitas dan perilaku yang tidak konsisten
  • Masalah intinya adalah kernel menahan data lebih lama daripada waktu yang dimaksudkan aplikasi, padahal data seharusnya dikirim segera saat write() dipanggil

Kesimpulan

  • Algoritme Nagle adalah penemuan hebat untuk meningkatkan efisiensi jaringan di masa lalu, tetapi
    dalam lingkungan jaringan berkecepatan tinggi dan sistem terdistribusi modern, ia justru menjadi fitur usang yang menimbulkan latensi
  • Karena itu, selalu mengaktifkan TCP_NODELAY diajukan sebagai prinsip dasar dalam perancangan sistem modern

1 komentar

 
GN⁺ 2025-12-23
Komentar Hacker News
  • Menjelaskan latar belakang algoritma Nagle yang dibuat pada masa jaringan multipoint dulu
    Saat itu banyak host berbagi satu kanal Ethernet, sehingga CSMA/CD digunakan untuk menghindari tabrakan
    Namun saat ini sebagian besar Ethernet memakai struktur point-to-point, dengan lingkungan full-duplex yang memungkinkan kirim dan terima secara bersamaan
    Karena itu CSMA tidak lagi diperlukan, dan menurutnya menonaktifkan algoritma Nagle dengan mengatur TCP_NODELAY adalah pilihan yang masuk akal dalam kebanyakan kasus
    • Penasaran apakah motivasi terkait CSMA benar-benar ada dalam perancangan algoritma Nagle, atau itu hanya penyebutan konteks zamannya saja
    • Sebenarnya algoritma Nagle murni ditujukan untuk penggabungan paket (coalescing)
      Fakta bahwa ini dijadikan default menurut saya adalah salah satu kesalahan besar dalam sejarah jaringan
    • Sebagai catatan, Ethernet memakai CSMA/CD, sedangkan WiFi memakai CSMA/CA
      Sekitar tahun 2014, saat mengganti switch data center, saya pernah harus mempertahankan beberapa perangkat lama karena tidak mendukung 10Mbit half-duplex
    • Nagle cukup masuk akal ketika aplikasi tidak memedulikan ukuran paket atau tidak sensitif terhadap latensi
      Ini membantu mencegah terciptanya paket yang terlalu kecil
    • Sepertinya ada kekeliruan layer jaringan
      Nagle adalah optimasi di lapisan TCP, berfungsi menggabungkan paket kecil agar lebih efisien
      CSMA adalah masalah lapisan fisik/data link, jadi terpisah dari Nagle
  • Saya menemukan tulisan ini saat men-debug masalah latensi jaringan selama pengembangan game
    Backend yang ditulis dengan Go secara default sudah mengaktifkan TCP_NODELAY, jadi itu bukan penyebabnya, tetapi bagian tentang bagaimana orang memandang masalah Nagle terasa menarik
    Ada diskusi lama juga, lihat thread ini
    • Saya juga merekomendasikan tulisan bagus dari Julia Evans
      Pada komunikasi bergaya chatty seperti protokol DICOM, mengatur TCP_NODELAY=1 bisa sangat meningkatkan throughput
    • Penasaran sedang mengembangkan game apa. Saya juga senang membuat game dengan Ebitengine dan Golang, jadi tertarik
  • Nagle sendiri pernah berkata sekitar 10 tahun lalu bahwa masalah yang sebenarnya adalah delayed ACK
    Lihat tautan terkait
    Saya rasa delayed ACK tidak lagi memberi banyak keuntungan pada workload modern
    Dalam lingkungan modern yang berpusat pada HTTP, menurut saya lebih baik mematikan Nagle dan delayed ACK sekaligus
    • Ini juga dibahas di tulisan aslinya
      Karena RTT antar-data center hanya ratusan mikrodetik, menunda bahkan satu RTT bisa malah merugikan
  • Dalam bahasa Polandia, “nagle” berarti “tiba-tiba”, dan saya terkejut betapa cocoknya itu dengan nama algoritmanya
    • Rasanya seperti contoh lain dari nominative determinism
      Tautan wiki
    • Menariknya, saat “NODELAY on” data dikirim tiba-tiba, sedangkan saat “off” dikirim sekaligus, jadi makna katanya seolah mencakup kedua pengaturan itu
    • Sebenarnya ini adalah algoritma berdasarkan RFC 896 yang ditulis oleh John Nagle
  • Menurut saya aneh bahwa algoritma Nagle dijadikan default kernel
    Aplikasi seharusnya yang memutuskan kapan mengirim dan kapan melakukan buffering
  • Saya heran tulisan itu tidak menyebut MSG_MORE
    Di Linux, ini adalah hint ke kernel bahwa data tambahan akan segera dikirim, berguna saat header dan data dikirim terpisah
    Bila dipakai bersama io_uring, hasilnya bisa lebih efisien
    • Sebenarnya beberapa potong data juga bisa dikirim dalam satu system call tanpa copy
  • Menurut saya masalah algoritma Nagle adalah API socket tidak punya fitur flush untuk kirim langsung
    Akan bagus jika ada cara untuk mengosongkan buffer dan mengirim setelah pesan yang memerlukan respons segera
    Kanal TCP modern sering mencampur pesan sinkron dan asinkron, jadi ini makin rumit
    Saya berharap protokol seperti SCTP dipakai lebih luas
    • Saya setuju bahwa API stream tidak punya fungsi flush. Menurut saya ini jelas kelalaian desain
    • Saya paham filosofi UNIX yang ingin memperlakukan network I/O seperti file, tetapi jika sejak awal ada API yang berorientasi pesan, masalah seperti ini mungkin tidak akan muncul
      Bahkan pada wrapping seperti TLS, mencari batas pesan itu merepotkan
    • Mungkin kita bisa mendapat efek flush secara tidak langsung dengan menambahkan MSG_MORE pada semua send dan hanya menghapusnya pada yang terakhir
    • API stream memang tidak nyaman dalam banyak hal
      Secara ideal, harus ada bit “buffering diizinkan” untuk memecah transfer besar, lalu “kirim langsung” pada akhirnya
      TCP_CORK setidaknya adalah alternatif yang agak mirip, meski terasa kasar
      File I/O juga mengalami masalah serupa
    • Penasaran apa itu TCP_CORK
  • Diskusi sebelumnya pada (2024) ada di tautan ini
  • Episode podcast Oxide and Friends membahas topik ini
    Isinya cukup menarik
    • Oxide adalah perusahaan yang merancang ulang server OS dan hardware, jadi pendekatan mereka yang meninjau ulang protokol tradisional sangat cocok dengan filosofi brand mereka
  • Algoritma Nagle terasa canggung karena seperti memasukkan kebijakan ke dalam kernel
    Aplikasi seharusnya bisa langsung mengatur sendiri keseimbangan antara latensi dan throughput
    • Saat tidak ada delayed ack, ini adalah algoritma yang masuk akal, dan alasan ia ada sebagai bagian dari stack TCP adalah karena masalah itu memang dicoba diselesaikan di layer tersebut
      Namun bila diimplementasikan di level aplikasi, perlu mengetahui unacked data, sehingga jadi tidak efisien
    • Secara teori benar, tetapi dalam praktiknya sebagian besar kode userspace tidak memedulikan detail bawah jaringan
      Bahkan sekadar timer flush 20ms pun akan jauh lebih baik
    • Sebenarnya TCP_NODELAY diatur per socket, jadi ini bisa dianggap lebih dekat ke keputusan userspace yang dipilih langsung oleh aplikasi
    • Trade-off satu program bisa memengaruhi program lain, jadi menurut saya kernel memang perlu berperan sebagai penengah dari sudut pandang seluruh sistem