Narzędzie do buforowania nieograniczonej ilości danych w potoku?

14

Czy istnieje narzędzie, które mogę włożyć do potoku, aby oddzielić prędkości odczytu i zapisu?

$ producer | buf | consumer

Zasadniczo chcę narzędzie, bufktóre odczytuje dane wejściowe tak szybko, jak to możliwe, przechowując je w pamięci, aby consumermogło zająć słodki czas, gdy producerdziała tak szybko, jak to możliwe.

Doktor J
źródło
Też chciałbym zobaczyć
Antti Haapala
stdbufNarzędziem wydaje się być sizeparametr. Nie jestem jednak pewien, czy to działa.
CMCDragonkai

Odpowiedzi:

14

Narzędzie pv(przeglądarka potoków) może to zrobić (z -Bopcją) i wiele więcej, w tym przekazywanie raportów postępu.

David Schwartz
źródło
Czy można to zrobić z nieograniczoną ilością danych? Najlepiej, jak mogę powiedzieć, muszę podać liczbę z -B, a jeśli producent dostanie się tak daleko przed konsumentem, producent ponownie zwolni. Jeśli znajdujesz się w sytuacji, gdy jest wielu klientów ( producer | tee >(pv -cB $SIZE | consumer1) | pv -cB $SIZE2 | consumer2), może to spowodować spowolnienie.
Daniel H
Użyłem pvsetki razy i nigdy o tym nie wiedziałem. Bardzo fajnie, dziękuję!
Rucent88
pv -B 4096 -c -N in /dev/zero | pv -q -B 1000000000 | pv -B 4096 -c -N out -L 100k > /dev/null- Spodziewam się, że oba pvkońce będą gładkie (chociaż jeden z nich ma 1 GB przewagi). To nie działa w ten sposób, w przeciwieństwie dombuffer
Vi.
9

możesz użyć dd:

producer | dd obs=64K | consumer

Jest dostępny na każdym uniksie.

Michał Šrajer
źródło
+1 za używanie standardowego narzędzia, chociaż pvprawdopodobnie jest prawdopodobnie łatwiejszy w użyciu (pokazuje postęp).
Totor
2
Czy to faktycznie oddziela szybkość czytania i pisania? Wygląda na to, że ddzapisuje tylko jeden blok na raz, więc opóźniałoby wszystko o czas potrzebny do wytworzenia rozmiaru bloku; Proszę popraw mnie jeżeli się mylę. Czy to buforowanie można rozszerzyć do nieograniczonego rozmiaru, czy tylko cokolwiek wprowadzonego dla rozmiaru bloku?
Daniel H
@DanielH - robi to teraz.
mikeserv
7

Spójrz na mbuffer . Może buforować do pamięci lub pliku odwzorowanego w pamięci ( -t/ -T).

Stephen Paul Lesniewski
źródło
Jak poprosiłem o inne, czy istnieje sposób, aby kazać buforować tyle, ile jest konieczne, czy ma maksymalny rozmiar? Czy istnieje konceptualny powód, dla którego większość z tych programów ma maksymalne rozmiary i nie używa na przykład połączonej listy mniejszych buforów (ani żadnej innej implementacji kolejki o dowolnym rozmiarze)?
Daniel H
Prawdopodobnie w celu uniknięcia błędów braku pamięci. Prawdopodobnie możesz użyć opcji, aby ustawić bardzo duży bufor (około 4 GB), jeśli chcesz (wypróbuj).
David Balažic
1

Jest to w zasadzie odpowiedź negatywna. Wygląda na to dd, że ani wszystkie mbuffer, ani nawet nie pvdziałają we wszystkich przypadkach, w szczególności jeśli szybkość danych generowanych przez producenta może się bardzo różnić. Poniżej podaję kilka przypadków testowych. Po wpisaniu polecenia poczekaj około 10 sekund, a następnie wpisz >(aby przejść do końca danych, tj. Poczekać na koniec danych wejściowych).

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

Tutaj po wpisaniu >trzeba poczekać 5 sekund, co oznacza, że ​​producent (skrypt zsh) zablokował się przed sleep 5. Zwiększenie bsrozmiaru do np. 32M nie zmienia zachowania, chociaż bufor 32 MB jest wystarczająco duży. Podejrzewam, że dddzieje się tak, ponieważ blokuje wyjście, a nie kontynuuje wprowadzanie danych. Używanie oflag=nonblocknie jest rozwiązaniem, ponieważ powoduje to odrzucenie danych.

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

Dzięki mbuffer, problem jest, że pierwsza linia (foo0) nie pojawia się natychmiast. Wydaje się, że nie ma opcji włączenia buforowania linii na wejściu.

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

Z pvzachowanie jest podobne do dd. Co gorsza, podejrzewam, że źle robi to terminalowi, ponieważ czasami lessnie może już odbierać danych wejściowych z terminalu; na przykład nie można go rzucić q.

vinc17
źródło
0

Niestandardowy ruch: użycie buforów gniazd.

Przykład:

# 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] [       <=>                   ]

Zaimplementowano w tym celu dwa dodatkowe narzędzia: buffered_pipeline i 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.
źródło