Utilitas untuk menyangga jumlah data yang tidak terbatas dalam pipa?

13

Apakah ada utilitas yang bisa saya tempelkan dalam saluran pipa untuk memisahkan kecepatan baca dan tulis?

$ producer | buf | consumer

Pada dasarnya, saya ingin sebuah utilitas bufyang membaca inputnya secepat mungkin, menyimpannya dalam memori sehingga consumerdapat mengambil waktu yang manis sambil producerberjalan secepat mungkin.

Dokter J
sumber
Saya juga ingin melihatnya
Antti Haapala
The stdbufalat tampaknya menjadi sizeparameter. Saya tidak yakin apakah itu berhasil.
CMCDragonkai

Jawaban:

13

The pv(pipa viewer) utilitas dapat melakukan hal ini (dengan -Bopsi) dan lebih banyak, termasuk memberikan laporan kemajuan.

David Schwartz
sumber
Apakah ada cara untuk melakukan ini dengan jumlah data yang tidak terbatas? Sejauh yang bisa saya katakan, saya perlu menyediakan angka dengan -B dan jika produser mencapai konsumen di depan, produser akan melambat lagi. Jika Anda berada dalam situasi di mana terdapat banyak konsumen ( producer | tee >(pv -cB $SIZE | consumer1) | pv -cB $SIZE2 | consumer2), ini dapat menyebabkan perlambatan lagi.
Daniel H
Saya telah menggunakan pvratusan kali dan tidak pernah tahu ini. Sangat luar biasa, terima kasih!
Rucent88
pv -B 4096 -c -N in /dev/zero | pv -q -B 1000000000 | pv -B 4096 -c -N out -L 100k > /dev/null- Saya berharap kedua pvujungnya menjadi halus (meskipun yang 1GB di depan). Tidak bekerja seperti ini, tidak seperti denganmbuffer
Vi.
9

Anda bisa menggunakan dd:

producer | dd obs=64K | consumer

Ini tersedia di setiap unix.

Michał Šrajer
sumber
+1 untuk menggunakan utilitas standar, meskipun pvmungkin mungkin lebih baik untuk digunakan (menunjukkan kemajuan).
Totor
2
Apakah itu benar-benar memisahkan kecepatan membaca dan menulis? Sepertinya ddhanya menyimpan satu blok pada satu waktu, jadi itu hanya akan menunda semuanya dengan jumlah waktu yang diperlukan untuk menghasilkan ukuran blok; tolong perbaiki saya jika saya salah. Juga, dapatkah buffering ini diperluas ke ukuran tidak terbatas, atau hanya apa pun yang dimasukkan untuk ukuran blok?
Daniel H
@DanielH - ya sekarang.
mikeserv
7

Lihatlah mbuffer . Ini dapat buffer ke memori atau file yang dipetakan memori ( -t/ -T).

Stephen Paul Lesniewski
sumber
Ketika saya meminta yang lain, apakah ada cara untuk mengatakannya untuk buffer sebanyak yang diperlukan, atau apakah itu memiliki ukuran maksimum? Apakah ada alasan konseptual mengapa sebagian besar program ini memiliki ukuran maksimum dan tidak, misalnya, menggunakan daftar tautan buffer yang lebih kecil (atau implementasi antrian ukuran arbitrer lainnya)?
Daniel H
Mungkin untuk mencegah kesalahan kehabisan memori. Anda mungkin dapat menggunakan opsi untuk mengatur buffer yang sangat besar (4GB atau lebih) jika Anda mau (coba).
David Balažic
1

Ini pada dasarnya adalah jawaban negatif. Tampaknya tidak ada dd, atau mbufferbahkan tidak pvberfungsi adalah semua kasus, khususnya jika tingkat data yang dihasilkan oleh produsen dapat sangat bervariasi. Saya memberikan beberapa testcases di bawah ini. Setelah mengetik perintah, tunggu sekitar 10 detik, lalu ketik >(untuk pergi ke akhir data, yaitu menunggu akhir input).

zsh -c 'echo foo0; sleep 3; \
        printf "Line %060d\n" {1..123456}; \
        echo foo1; sleep 5; \
        echo foo2' | dd bs=64K | less

Di sini, setelah mengetik >, seseorang harus menunggu selama 5 detik, artinya produser (skrip zsh) telah memblokir sebelum sleep 5. Menambah bsukuran menjadi misalnya 32M tidak mengubah perilaku, meskipun buffer 32MB cukup besar. Saya menduga bahwa ini karena ddblok pada output bukannya melanjutkan input. Menggunakan oflag=nonblockbukanlah solusi karena ini membuang data.

zsh -c 'echo foo0; sleep 3; \
        printf "Line %060d\n" {1..123456}; \
        echo foo1; sleep 5; \
        echo foo2' | mbuffer -q | less

Dengan mbuffer, masalahnya adalah baris pertama (foo0) tidak segera muncul. Tampaknya tidak ada opsi untuk mengaktifkan buffer-line pada input.

zsh -c 'echo foo0; sleep 3; \
        printf "Line %060d\n" {1..123456}; \
        echo foo1; sleep 5; \
        echo foo2' | pv -q -B 32m | less

Dengan pv, perilaku tersebut mirip dengan dd. Lebih buruk lagi, saya curiga bahwa itu melakukan hal-hal yang salah ke terminal karena kadang less- kadang tidak dapat lagi menerima input dari terminal; misalnya, seseorang tidak dapat berhenti dengannya q.

vinc17
sumber
0

Langkah tidak standar: menggunakan buffer soket.

Contoh:

# echo 2000000000 > /proc/sys/net/core/wmem_max
$ socat -u system:'pv -c -N i /dev/zero',sndbuf=1000000000 - | pv -L 100k -c -N o > /dev/null
        i:  468MB 0:00:16 [ 129kB/s] [  <=>                        ]
        o: 1.56MB 0:00:16 [ 101kB/s] [       <=>                   ]

Menerapkan dua alat tambahan untuk ini: buffered_pipeline dan mapopentounixsocket

$ ./buffered_pipeline ! pv -i 10 -c -N 1 /dev/zero ! $((20*1000*1000)) ! pv -i 10 -L 100k -c -N 2 ! > /dev/zero
        1: 13.4MB 0:00:40 [ 103kB/s] [         <=>      ]
        2: 3.91MB 0:00:40 [ 100kB/s] [         <=>      ]
Vi.
sumber