Como é que o sed é tão rápido?

6

Pensei se esta pergunta é adequada para SE ou não, espero que você concorde.

Algum tempo atrás eu perguntei no SE como encontrar texto em arquivos e deixar o arquivo apenas com as linhas correspondentes que contêm o texto que eu estava procurando. A pergunta é aqui: Como encontrar texto em arquivos e manter apenas as respectivas linhas correspondentes usando o terminal no OS X?

Enquanto a resposta funcionou perfeitamente agora eu me pergunto, como é que sed é tão rápido? No meu caso de uso, eu tinha muitos arquivos que, no total, tinham cerca de 30 Gb de tamanho. O comando sed foi executado em cerca de 12 segundos, o que eu nunca teria acreditado (trabalhando com um disco rígido normal). Em 12 segundos, o comando leu 30 GB de texto, truncando cada arquivo para manter apenas as respectivas linhas pelas quais eu estava filtrando. Como isso funciona? (ou: o que é essa feitiçaria?)

O comando atual era:

find . -type f -exec sed -i'' '/\B\/foobar\b/!d' {} \;
    
por Alex 12.09.2014 / 09:44

2 respostas

1

A resposta provável é que:

  1. O arquivo de 30Gb não foi fragmentado (ou teve muito pouca fragmentação): todos os discos rígidos funcionam muito melhor com acesso sequencial (SSDs incluídos) porque eles podem armazenar em cache grandes partes do arquivo. Isso permite que eles se aproximem de seu desempenho máximo. O acesso sequencial ajudará com todos os níveis de caches.
  2. sed é um editor de fluxo; ele processa apenas uma linha por vez. Isso significa que sua pegada de memória é minúscula. Ao contrário de um editor de texto, como emacs ou vim , não é necessário manter toda a cópia do arquivo na memória.
  3. Você está editando o arquivo no local (com -i ) que (como demonstrado por @Ramesh e também indicado em página da Wikipédia ) cria um arquivo temporário que, em seguida, torna-se o arquivo antigo.

Tudo isso significa que sed é capaz de executar quase o mínimo de operações de arquivo: cada linha do arquivo original é lida uma vez e apenas as linhas que são correspondidas são gravadas.

Sua escolha de expressões regulares também afeta o desempenho, às vezes de maneiras muito ruins .: codificando o blog de terror .

    
por 12.09.2014 / 16:00
2

Um exemplo maravilhoso é que sed usa um arquivo temporário para salvar o conteúdo e, em seguida, substitui o arquivo original. Por exemplo, você pode fazer um teste simples para encontrar isso.

cat test
This is a test file. 

Agora, execute ls -li para verificar o número do inode.

ls -li test
2368770 -rw-r--r-- 1 root root 22 Sep 12 08:46 test

Agora, emita o comando sed abaixo para adicionar uma linha em branco.

sed -i 's/2/B/' test

Após alterar o arquivo, emita o comando ls novamente e verifique o número do inode.

ls -li test
2368753 -rw-r--r-- 1 root root 22 Sep 12 08:48 test

Podemos ver que o número do inode mudou na verdade. Então, em vez de copiar para o mesmo arquivo sed cria um novo arquivo temporário e copia o conteúdo para o novo arquivo temporário e, em seguida, exclui o arquivo original e renomeia o arquivo tmp em sincronia com o arquivo original, que é uma das razões pelas quais as operações do arquivo são realmente mais rápidos.

Citações de página da wikipedia ,

sed is a line-oriented text processing utility: it reads text, line by line, from an input stream or file, into an internal buffer called the pattern space. Each line read starts a cycle. To the pattern space, sed applies one or more operations which have been specified via a sed script. sed implements a programming language with about 25 commands that specify the operations on the text. For each line, after running the script sed ordinarily outputs the pattern space (the input line as modified by the script) and begins the cycle again with the next line.

Para entender mais sobre o espaço padrão e manter conceitos de espaço de sed , leia a resposta aqui .

When sed reads a file line by line, the line that has been currently read is inserted into the pattern buffer (pattern space). Pattern buffer is like the temporary buffer, the scratchpad where the current information is stored. When you tell sed to print, it prints the pattern buffer.

Hold buffer / hold space is like a long-term storage, such that you can catch something, store it and reuse it later when sed is processing another line. You do not directly process the hold space, instead, you need to copy it or append to the pattern space if you want to do something with it.

    
por 12.09.2014 / 15:53