Apakah tee memperlambat jalur pipa?

10

Saya bertanya-tanya apakah tee memperlambat jalur pipa. Menulis data ke disk lebih lambat daripada mem-pipkannya.

Apakah tee menunggu dengan mengirimkan data ke pipa berikutnya sampai ditulis ke disk? (Jika tidak, saya kira tee harus mengantri data yang telah dikirim, tetapi tidak ditulis ke disk, yang sepertinya tidak mungkin bagi saya.)

$ program1 input.txt | tee intermediate-file.txt | program2 ...
Kucing Unfun
sumber
Tidak, "pipa berikutnya" adalah hal pertama yang ditulisnya (juga disebutkan di sini ).
ManRow

Jawaban:

12

Ya, itu memperlambat segalanya. Dan pada dasarnya memang ada antrian data tidak tertulis, meskipun itu sebenarnya dikelola oleh kernel — semua program memilikinya, kecuali mereka secara eksplisit meminta sebaliknya.

Misalnya, ini adalah penggunaan pipa sepele pv, yang bagus karena menampilkan kecepatan transfer:

$ pv -s 50g -S -pteba /dev/zero | cat > /dev/null 
  50GiB 0:00:09 [ 5.4GiB/s] [===============================================>] 100%

Sekarang, mari kita tambahkan teedi sana, bahkan tidak menulis salinan tambahan — hanya meneruskan saja:

$ pv -s 50g -S -pteba /dev/zero | tee | cat > /dev/null 
  50GiB 0:00:20 [2.44GiB/s] [===============================================>] 100%            

Jadi, itu sedikit lebih lambat, dan bahkan tidak melakukan apa-apa! Itulah overhead tee menyalin STDIN ke STDOUT secara internal. (Menariknya, menambahkan satu detik pvdi sana tetap di 5.19GiB / s, jadi pvsecara substansial lebih cepat daripada tee. pvMenggunakan splice(2), teekemungkinan tidak.)

Pokoknya, mari kita lihat apa yang terjadi jika saya meminta teeuntuk menulis ke file di disk. Dimulai dengan cukup cepat (~ 800MiB / s) tetapi seiring berjalannya waktu, ia terus melambat — akhirnya turun ke ~ 100MiB / s, yang pada dasarnya 100% dari bandwidth disk write. (Awal yang cepat adalah karena kernel melakukan caching pada penulisan disk, dan perlambatan pada kecepatan penulisan disk adalah kernel yang menolak untuk membiarkan cache tumbuh tanpa batas.)

Apakah itu penting?

Di atas adalah kasus terburuk. Di atas menggunakan pipa untuk memuntahkan data secepat mungkin. Satu-satunya penggunaan di dunia nyata yang bisa saya pikirkan adalah memipipkan data YUV mentah ke / dari ffmpeg.

Saat Anda mengirim data dengan kecepatan lebih lambat (karena Anda memprosesnya, dll.) Itu akan menjadi efek yang jauh lebih kecil.

derobert
sumber
Penjelasan yang bagus
shubham
5

Tidak ada yang mengejutkan di sini

> POSIX berkata ,

DESKRIPSI

The tee utilitas akan menyalin standar input ke output standar, membuat salinan di nol atau lebih file. The tee utilitas tidak akan buffer output.

Dan juga itu

ALASAN

Persyaratan buffering berarti tee tidak diperbolehkan untuk menggunakan penulisan standar buffer penuh atau buffer-line ISO C. Itu tidak berarti bahwa tee harus melakukan pembacaan 1 byte diikuti oleh penulisan 1 byte.

Jadi, tanpa menjelaskan "alasan", teemungkin hanya akan membaca dan menulis hingga berapa banyak byte yang dapat masuk ke buffer pipa Anda sekaligus, membilas output pada setiap penulisan.

Dan ya, tergantung pada aplikasinya, ini bisa jadi agak tidak efisien - jadi silakan saja menghapus / mengomentari semua ini:
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L208
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L224

ManRow
sumber
+1 untuk tautan ke kode sumber yang bertanggung jawab. Apakah bagian-bagian itu benar-benar semua yang bertanggung jawab atas perilaku ini, sehingga menghapus / berkomentar akan membuat teeberjalan lebih cepat?
Hashim
1
Sepertinya itu yang terjadi! Tee mengesampingkan skema buffering yang jika tidak dipilih oleh OS
ManRow