2 poin oleh GN⁺ 2024-11-30 | 1 komentar | Bagikan ke WhatsApp

Mengapa pipe "macet": buffering

  • Penjelasan masalah: Saat menjalankan perintah tail -f /some/log/file | grep thing1 | grep thing2 untuk mencari output tertentu di file log, jika baris log ditambahkan dengan lambat, output bisa tidak muncul. Ini terlihat seperti pipe macet, tetapi sebenarnya program tidak menulis data ke pipe.

Penyebab buffering

  • Alasan buffering: Umumnya program melakukan buffering sebelum menulis data ke pipe atau file. Ini dilakukan untuk meningkatkan performa, dengan mengumpulkan sejumlah data lalu menulisnya sekaligus, alih-alih langsung menulis setiap output.
  • Contoh: grep thing1 menyimpan data yang cocok sampai terkumpul 8KB, sehingga output mungkin tidak segera muncul.

Tidak melakukan buffering saat menulis ke terminal

  • Perbedaan terminal dan pipe: grep menggunakan line buffering saat output diarahkan ke terminal, tetapi menggunakan block buffering saat diarahkan ke pipe. Ini ditentukan melalui fungsi isatty.

Perintah yang melakukan buffering dan yang tidak

  • Perintah yang tidak melakukan buffering: tail, cat, tee, dan lainnya tidak melakukan buffering.
  • Perintah yang melakukan buffering: grep, sed, awk, tcpdump, jq, tr, cut, dan lainnya melakukan buffering, dan sebagian dapat menonaktifkannya dengan flag tertentu.

Buffering output bawaan pada bahasa pemrograman

  • Bahasa yang melakukan buffering: C, Python, Ruby, Perl, dan lainnya secara default melakukan buffering output, dan dapat dinonaktifkan dengan cara tertentu.

Kehilangan isi buffer saat menekan Ctrl-C

  • Penjelasan masalah: Saat menekan Ctrl-C, isi yang masih ada di buffer akan hilang. Ini terjadi karena sinyal SIGINT dikirim lebih dulu.
  • Solusi: Cari PID tcpdump lalu jalankan kill -TERM $PID untuk mem-flush buffer.

Buffering juga terjadi saat redirect ke file

  • Redirect ke file: Saat diarahkan ke file, buffering juga tetap terjadi, tetapi masalah kehilangan buffer akibat Ctrl-C tidak terjadi.

Beberapa cara menghindari buffering

  • Solusi 1: Jalankan program yang cepat selesai.
  • Solusi 2: Gunakan flag --line-buffered pada grep.
  • Solusi 3: Gunakan awk.
  • Solusi 4: Gunakan stdbuf.
  • Solusi 5: Gunakan unbuffer.

Variabel lingkungan untuk menonaktifkan buffering

  • Ide: Ada pendapat bahwa akan bagus jika tersedia variabel lingkungan standar seperti PYTHON_UNBUFFERED. Variabel seperti NO_BUFFER diusulkan.

Isi yang dihilangkan

  • Topik yang dihilangkan: Perbedaan antara line buffering dan non-buffering penuh, perbedaan buffering pada stderr dan stdout, buffering driver TTY di sistem operasi, dan sebagainya.

1 komentar

 
GN⁺ 2024-11-30
Komentar Hacker News
  • Akses yang dibuffer harus di-flush setelah jumlah byte atau waktu tertentu berlalu. Ini adalah cara umum untuk menyelesaikan masalah serupa pada antarmuka perangkat keras

    • Library yang melakukan buffering di ruang pengguna harus menetapkan timer yang sesuai saat pertama kali membuffer data
    • Parameter timeout sebaiknya diteruskan sebagai argumen, atau sedikit di bawah skala waktu manusia, atau proporsional terhadap bandwidth/ambang batas, atau proporsional terhadap overhead flushing
    • Ini berlaku baik untuk penulisan maupun pembacaan, dan bisa berbeda tergantung kanal data
  • Saat seluruh CPU sistem menjadi idle, rasanya ingin mem-flush semua buffer

    • Buffering pada umumnya adalah teknik untuk menghemat CPU
    • Saat CPU menjadi idle, seharusnya ada sinyal yang dikirim ke semua proses untuk "flush buffer"
  • Saya sudah berkutat dengan sistem NIX selama lebih dari 20 tahun, tetapi selalu lupa soal masalah buffering

  • Saya sudah memakai Unix selama lebih dari 35 tahun, tetapi belum pernah benar-benar memahami cara kerja buffering. Penjelasan ini bermanfaat

  • Ada kebingungan antara "unbuffered" dan "line buffering"

    • Unbuffered dapat menurunkan performa, dan jika beberapa sumber menulis ke pipe yang sama, bisa menghasilkan output yang salah
    • Line buffering adalah default untuk terminal, dan cocok untuk pipe
  • Buffer ada karena menulis ke buffer relatif jauh lebih lambat daripada mencetak output ke layar

    • Ini adalah masalah yang sering muncul saat bekerja dengan UART, dan ada berbagai solusi
    • Ada beragam pendekatan seperti penggunaan karakter khusus, pendekatan berbasis panjang, dan pendekatan berbasis waktu
  • Jika menekan Ctrl-C, isi buffer bisa hilang

    • Kebanyakan program saya kira akan mem-flush buffer saat menerima SIGINT
  • Pernah mengalami masalah buffering di Unix, dan tidak semua implementasi 'awk' berperilaku sama

  • Saya merasa melewatkan lelucon tentang pipe yang membeku