O Tee desacelera os oleodutos?

10

Eu estou querendo saber se o tee diminui os encanamentos. A gravação de dados no disco é mais lenta do que a distribuição, afinal.

O tee espera com o envio de dados para o próximo canal até que sejam gravados no disco? (Caso contrário, acho que o tee precisa enfileirar dados que foram enviados, mas não gravados em disco, o que me parece improvável.)

$ program1 input.txt | tee intermediate-file.txt | program2 ...
The Unfun Cat
fonte
Não, esse "próximo canal" é a primeira coisa em que ele escreve (também mencionado aqui ).
ManRow 04/04/19

Respostas:

12

Sim, isso atrasa as coisas. E basicamente tem uma fila de dados não escritos, embora isso seja realmente mantido pelo kernel - todos os programas têm isso, a menos que solicitem explicitamente o contrário.

Por exemplo, aqui está um canal trivial usando pv, o que é bom porque exibe a taxa de transferência:

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

Agora, vamos adicionar um tee, nem mesmo escrever uma cópia extra - apenas encaminhá-la:

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

Então, isso é um pouco mais lento, e nem estava fazendo nada! Essa é a sobrecarga de copiar internamente STDIN para STDOUT. (Curiosamente, a adição de um segundo pvlá permanece em 5,19GiB / s, portanto pvé substancialmente mais rápida que o tee. pvUsa splice(2), teeprovavelmente não.)

De qualquer forma, vamos ver o que acontece se eu pedir teepara gravar em um arquivo no disco. Ele começa com bastante rapidez (~ 800MiB / s), mas, à medida que continua, diminui a velocidade - chegando a ~ 100MiB / s, que é basicamente 100% da largura de banda de gravação em disco. (O início rápido se deve ao armazenamento em cache do kernel na gravação do disco, e a diminuição da velocidade de gravação do disco é o kernel que se recusa a deixar o cache crescer infinitamente.)

Isso importa?

O exposto acima é o pior dos casos. O exemplo acima usa um tubo para transmitir dados o mais rápido possível. O único uso no mundo real em que posso pensar dessa maneira é canalizar dados brutos de YUV de / para ffmpeg.

Quando você está enviando dados a taxas mais lentas (porque está processando-os etc.), será um efeito muito menos significativo.

derobert
fonte
Explicação agradável
shubham
5

Nada de surpreendente aqui, afinal

> POSIX diz ,

DESCRIÇÃO

O utilitário tee deve copiar a entrada padrão para a saída padrão, fazendo uma cópia em zero ou mais arquivos. O utilitário tee não deve armazenar em buffer a saída.

E também que

JUSTIFICATIVA

O requisito de armazenamento em buffer significa que tee não tem permissão para usar gravações totalmente em buffer ou em linha padrão ISO C. Isso não significa que o tee precisa fazer leituras de 1 byte seguidas de gravações de 1 byte.

Portanto, sem explicar o "raciocínio", teeprovavelmente só lerá e gravará até quantos bytes caberem no buffer de seu canal por vez, liberando a saída em cada gravação.

E sim, dependendo do aplicativo, isso pode ser bastante ineficiente - portanto, fique à vontade para simplesmente remover / comentar qualquer um desses itens:
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L208
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L224

ManRow
fonte
+1 nos links para o código-fonte responsável. Essas partes são realmente responsáveis ​​por esse comportamento, para que a remoção / comentário das mesmas fosse teeexecutada mais rapidamente?
Hashim
1
Parece que seria esse o caso! Tee substitui o esquema de buffer escolhido pelo SO
ManRow