Por que ler um FILE mais rápido que ler uma VARIABLE?

4

Não entendo os resultados de um teste de desempenho simples executado com dois scripts básicos (em execução em um servidor de ponta):

perfVar.zsh :

#!/bin/zsh -f

MYVAR='cat $1'
for i in {1..10}
do
  echo $MYVAR
done

perfCat.zsh

#!/bin/zsh -f

for i in {1..10}
do
cat $1
done

Resultado do teste de desempenho:

> time ./perfVar.zsh BigTextFile > /dev/null
./perfVar.zsh FE > /dev/null  6.86s user 0.32s system 100% cpu 7.177 total
> time ./perfCat.zsh BigTextFile > /dev/null
./perfCat.zsh FE > /dev/null  0.01s user 0.10s system 91% cpu 0.118 total

Eu teria pensado que acessar uma variável era muito mais rápido do que ler um arquivo no sistema de arquivos ... Por que esse resultado? Existe uma maneira de otimizar o script perfCat.zsh reduzindo o número de acessos ao sistema de arquivos?

    
por Sébastien 04.05.2011 / 19:41

3 respostas

1

Consegui reproduzir o mesmo comportamento no Bash. O principal problema aqui é que você está usando variáveis de shell de uma maneira que não foram projetadas; e, portanto, não otimizado para. Quando você faz 'echo $ HUGEVAR', o shell tem que construir uma linha de comando contendo todo o conteúdo de $ HUGEVAR (mesmo que 'echo' seja um comando interno, ainda existe uma linha de comando).

Assim, o shell expande o HUGEVAR para uma string grande, que é então analisada novamente para dividi-lo no espaço em branco em uma lista de argumentos individuais para o comando echo. (Observe que isso terá o efeito de reduzir os caracteres de espaços em branco consecutivos no arquivo de entrada para caracteres de espaço único). Claramente, este processo não é muito eficiente com grandes strings.

Você deve usar o método 'cat bigfile' várias vezes; e permitir que o cache do sistema de arquivos do SO faça seu trabalho e acelere o acesso repetido do arquivo grande; você evita a modificação sutil (possivelmente indesejada) na string que o shell faz quando você usa o echo (mais o método 'cat' funcionará com arquivos binários onde o método do shell pode quebrar dados binários).

    
por 05.05.2011 / 17:28
2

No bash e csh, a variável choice ...

#!/usr/bin/env bash
MYVAR='cat $1'

#!/usr/bin/env tcsh
set myvar='cat $1'

... fará com que execute o comando cat , bem como qualquer interpretação do texto que possa ocorrer. Por exemplo, se a variável de ambiente LANG estiver configurada como UTF8 ou se ela transformar linhas novas em espaços. Finalmente, ele precisa alocar espaço para armazenar o resultado do cat .

Por outro lado, o script # 2 apenas exibe o arquivo e é feito com ele. Na verdade, como está escrevendo para /dev/null , isso provavelmente melhorará o desempenho também.

Tente gravar em um arquivo em vez de /dev/null e re-time-lo. Com certeza, será ainda mais rápido, mas os horários podem estar mais de acordo uns com os outros.

Por último, tenha tempo apenas o loop em vez de cronometrar todo o script. Se o que você quer fazer é ler o tempo de uma variável -vs- lendo de um arquivo, então você não está cronometrando corretamente.

editar

Para o tempo, em vez de usar o comando time , recomendo fazer isso:

#!/usr/bin/env bash

# do some stuff
date --rfc-3339=ns
for (( i = 0; i < 10; i++ )); do
  # Some more stuff
done;
date --rfc-3339=ns

Isto irá mostrar a data atual & tempo preciso para o nanossegundo.

    
por 04.05.2011 / 20:02
0

Atribuição variável (em contraste com a maioria dos outros scripts incorporados) é uma operação cara. A razão pela qual você está vendo uma diferença de desempenho tão drástica é devido ao tamanho dos dados com os quais você está trabalhando. Na superfície, parece que você está atribuindo os dados apenas uma vez a uma única variável (MYVAR), mas, na realidade, zsh está atribuindo os dados a um local temporário (mapeando e desmapeando a memória) em todas as chamadas de eco. Normalmente, isso não é um problema, mas ao trabalhar com uma grande quantidade de dados, torna-se perceptível.

A razão pela qual a alça do gato é superior é dupla. Tamanho dos dados e armazenamento em cache do sistema de arquivos.

    
por 04.05.2011 / 20:37