Utilità per bufferizzare una quantità illimitata di dati in una pipeline?


13

Esiste un'utilità che posso inserire in una pipeline per disaccoppiare le velocità di lettura e scrittura?

$ producer | buf | consumer

Fondamentalmente, voglio un'utilità bufche legge il suo input il più velocemente possibile, memorizzandolo in modo che consumerpossa impiegare il suo dolce tempo mentre producerviene eseguito il più velocemente possibile.


Mi piacerebbe vedere anche questo
Antti Haapala,

Lo stdbufstrumento sembra essere un sizeparametro. Non sono sicuro che funzioni però.
CMCDragonkai,

Risposte:


13

L' pvutilità (pipe viewer) può fare questo (con l' -Bopzione) e molto altro, incluso fornire rapporti sullo stato di avanzamento.


C'è un modo per farlo con una quantità illimitata di dati? Per quanto posso dire, devo fornire un numero con -B e se il produttore è molto più avanti del consumatore, il produttore rallenterà di nuovo. Se ti trovi in ​​una situazione in cui ci sono più consumatori ( producer | tee >(pv -cB $SIZE | consumer1) | pv -cB $SIZE2 | consumer2), questo può causare nuovamente rallentamenti.
Daniel H,

L'ho usato pvcentinaia di volte e non l' ho mai saputo. Molto fantastico, grazie!
Rucent88,

pv -B 4096 -c -N in /dev/zero | pv -q -B 1000000000 | pv -B 4096 -c -N out -L 100k > /dev/null- Mi aspetto che entrambe le pvestremità siano lisce (sebbene una sia 1 GB avanti). Non funziona in questo modo, a differenza dimbuffer
Vi.

9

puoi usare dd:

producer | dd obs=64K | consumer

È disponibile su ogni Unix.


+1 per l'utilizzo dell'utilità standard, sebbene pvsia probabilmente più piacevole da usare (mostra progressi).
Totor

2
Ciò disaccoppia effettivamente la velocità di lettura e scrittura? Sembra che ddmemorizzi solo un blocco alla volta, quindi ritarderebbe tutto di quanto tempo ci vuole per produrre la dimensione del blocco; Per favore correggimi se sbaglio. Inoltre, questo buffering può essere esteso a dimensioni illimitate, o solo ciò che è stato inserito per le dimensioni del blocco?
Daniel H,

@DanielH - lo fa ora.
Mikeserv,

7

Dai un'occhiata a mbuffer . Può bufferizzare in memoria o file mappato in memoria ( -t/ -T).


Come ho chiesto agli altri, c'è un modo per dirlo per bufferizzare quanto è necessario o ha una dimensione massima? C'è un motivo concettuale per cui la maggior parte di questi programmi ha dimensioni massime e, ad esempio, non utilizza un elenco collegato di buffer più piccoli (o qualsiasi altra implementazione di coda di dimensioni arbitrarie)?
Daniel H,

Probabilmente per evitare errori di memoria insufficiente. Probabilmente puoi usare un'opzione per impostare un buffer molto grande (circa 4 GB) se lo desideri (provalo).
David Balažic,

1

Questa è sostanzialmente una risposta negativa. Sembra che né dd, né mbuffer, né pvfunziona, tutti i casi, in particolare se la velocità dei dati generati dal produttore può variare molto. Di seguito alcune prove. Dopo aver digitato il comando, attendere circa 10 secondi, quindi digitare >(per andare alla fine dei dati, ovvero attendere la fine dell'input).

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

Qui, dopo aver digitato >, bisogna aspettare 5 secondi, il che significa che il produttore (script zsh) si è bloccato prima del sleep 5. L'aumento della bsdimensione, ad esempio 32M, non modifica il comportamento, sebbene il buffer da 32 MB sia abbastanza grande. Sospetto che ciò sia dovuto al fatto che ddblocchi sull'output invece di continuare con l'input. L'uso oflag=nonblocknon è una soluzione perché questo scarta i dati.

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

Con mbuffer, il problema è che la prima riga (foo0) non appare immediatamente. Non sembra esserci alcuna opzione per abilitare il buffering di linea sull'input.

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

Con pv, il comportamento è simile a dd. Peggio ancora, sospetto che faccia cose sbagliate al terminale poiché a volte lessnon è più possibile ricevere input dal terminale; per esempio, non si può uscire con q.


0

Spostamento non standard: utilizzo di buffer socket.

Esempio:

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

Implementati due strumenti aggiuntivi per questo: buffered_pipeline e 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] [         <=>      ]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.