Diferença de desempenho entre stdin e argumento de linha de comando

11

Para alguns comandos, é possível especificar determinadas entradas como stdin ou como argumento da linha de comandos.

Especificamente, suponha que commandpode levar a entrada stdin e um nome de arquivo como argumento de linha de comando e command < myfile, cat myfile | command e command myfilepode produzir o mesmo resultado.

Por exemplo,

Quando o comando é sed:

sed s/day/night/ <myfile >new   
sed s/day/night/ myfile >new    
cat myfile | sed s/day/night/ >new

Quando o comando é cat:

cat < myfile
cat myfile
  1. Fiquei me perguntando se existem algumas regras gerais sobre suas performances, ou seja, qual delas é geralmente a mais eficiente e qual a menos?
  2. O redirecionamento é sempre melhor que o pipe?
Tim
fonte
1
Desejo que todos que fazem essas perguntas (duplicadas) escrevam seu próprio shell do zero como um exercício.
22411 alex
1
por favor não use "Obrigado!" nas suas perguntas. Vote nas respostas para expressar sua gratidão.
22411 alex
@ Alex: Se este é um engano, faça o link para o duplicado e trabalharemos para fechá-lo. Normalmente, você se abstém de responder a uma pergunta que sabe ser duplicada e a sinaliza para atenção do moderador.
Caleb
1
@alex: Onde posso aprender a escrever meu próprio shell?
Tim
@Caleb: Estou certo de que este foi perguntado como 2 ou 3 vezes no mês passado, simplesmente não têm o link útil :-P
alex

Respostas:

6

A cat file | commandsintaxe é considerada um uso inútil deCat . De todas as suas opções, é preciso um impacto no desempenho porque ele precisa gerar outro processo no kernel. Por mais insignificante que isso possa parecer, é uma sobrecarga que as outras formas não têm. Isso foi abordado em questões como: Devo me preocupar com gatos desnecessários?

Entre as outras duas formas, praticamente não há diferenças de desempenho. STDIN é um nó de arquivo especial que o processo precisa abrir e ler como qualquer outro. Passar um nome de arquivo em vez de STDIN apenas abre um arquivo diferente.

A diferença estaria em quais recursos / flexibilidade você está procurando.

  • Passar o nome do arquivo para o programa significa que o arquivo de entrada foi procurado. Isso pode ou não importar para o programa, mas algumas operações podem ser aceleradas se o fluxo for procurado.
  • Conhecer o arquivo de entrada real permite que seu programa grave nele. Por exemplo, sed -ipara edição no local. (Observação: como é necessário criar um novo arquivo nos bastidores, não é um ganho de desempenho em relação a outros redirecionamentos, mas é uma etapa de conveniência.)
  • O uso de redirecionamentos de shell permite concatenar vários arquivos ou até mesmo usar o redirecionamento de processos. sed [exp] < file1 file2ou mesmo sed [exp] < <(grep command). Detalhes deste caso de uso podem ser encontrados nesta pergunta: Substituição de processo e canalização
Caleb
fonte
A substituição do processo deve funcionar sem exigir que você canalize o resultado; sed [exp] < <(grep command)funcionará bem como sed [exp] <(grep command)(desde que <(grep command)cria um arquivo temporário nomeado para o tamanho do comando, que sedé perfeitamente capaz de abrir por si mesmo sem a ajuda do shell).
ShadowRanger
2
  1. Dado que command fileapenas abre o arquivo e, a partir de então, funciona como se fosse stdin, há pouca diferença. Com o redirecionamento do shell, basta abrir o arquivo com antecedência (o shell faz), em vez de comandar o próprio binário.

  2. Se estamos falando de cat file | commandvs. command <file, o último é o preferido. Você não notará diferença significativa de desempenho entre os dois, mas o primeiro é desnecessariamente complicado (processo extra e buffer de memória compartilhada para o pipe, com taxa de transferência limitada.) Além disso, você não pode seek(alterar a posição do ponteiro do arquivo arbitrariamente) em um pipe, enquanto você pode em um arquivo comum. Alguns comandos podem usar um algoritmo mais eficiente quando seek-ing no arquivo de entrada é possível.

alex
fonte
Eu diria que o arquivo de comando é preferido sobre o comando <file, porque o comando pode fazer algum tipo de acesso não sequencial.
user606723
E com o que impediria isso <file? Seu ponto é válido para o uso do nome do arquivo de entrada para derivar o nome do arquivo de saída resistente, por exemplo: gzip fileproduz file.gz.
alex
talvez eu não entenda como o redirecionamento funciona internamente. Digamos que redirecionamos um filme de 12 GB para o mplayer / vlc e pulamos para o final. O que exatamente aconteceria neste caso?
user606723
1
O Shell abre o arquivo e bifurca um subprocesso, que herda o descritor de arquivo. O processo bifurcada closes stdine chamadas dupsobre o descritor de arquivo aberto, por isso substituir o antigo stdin(que era algum tipo de tty na maioria dos casos.) Do ponto jogador de filme de vista não há nenhuma diferença entre isso e abrir o arquivo por ele é nome no próprio jogador. O descritor de arquivo pode ser procurado nos dois cenários; portanto, quando pulamos para o final, não há diferença detectável pelo usuário.
22411 alex