Melhore o uso inicial do tempo de desempenho de 'encontrar'

2

Estou trabalhando em um projeto para encontrar todos os arquivos de instalação .tar em meu sistema usando o comando:

time find / -type f \( -name "*.tar" -o -name "*.tar.*" \) 2>/dev/null | wc

Na primeira vez que eu executo, recebo:

real    1m10.767s

Na segunda vez que eu obtenho:

real    0m9.847s

Eu gostaria de sempre obter o desempenho de segunda vez de < 10 segundos e abandonar o desempenho inicial de 1 minuto 10 segundos . Qual é a melhor maneira de evitar a penalidade de um minuto na primeira vez em que find é usado?

Notas

  • Seu find inicial pode ser mais rápido porque eu tenho uma instalação do Ubuntu 16.04 mais duas instalações do Windows 10 para um total de 2 milhões de arquivos.
  • OTOH seu find inicial pode ser mais lento porque eu tenho o Ubuntu 16.04 e uma das instalações do Windows 10 em um Samsung Pro 960 NVMe SSD avaliado em 3.000 MBps enquanto os discos rígidos são avaliados em 140 MBps e bons SSDs são classificados em 400 MBps.
  • Se você quiser replicar os testes, mas não tiver arquivos .tar em seu sistema, substitua tar por bashrc na seção: -name "*.tar" -o -name "*.tar.*" .

TL; DR

Drop caches de RAM que aceleram find de acesso ao disco

Você pode repetir os testes de desempenho de primeiro / segundo chamando este pequeno script antes do primeiro find :

#!/bin/bash
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
sync; echo 1 > /proc/sys/vm/drop_caches
sync; echo 2 > /proc/sys/vm/drop_caches
sync; echo 3 > /proc/sys/vm/drop_caches

GIF mostrando quanto de cache de disco RAM consome

O comando find executado em / consome cerca de 500 MB de buffers de cache, conforme mostra o .gif abaixo quando eles são descartados:

^^^ --- Observe que a linha de memória imediatamente abaixo da janela do terminal mostra uma queda de 4,74 GiB para 4,24 GiB. Na verdade, ele cai para 4,11 GiB depois que o gravador de tela peek salva o arquivo e fecha. No meu sistema find cache de disco está usando cerca de 5% de RAM.

    
por WinEunuuchs2Unix 22.04.2018 / 14:37

1 resposta

2

Projeto desafiador

Nas seções a seguir, há coisas que devem funcionar, mas não funcionam. No final, a única maneira certa de fazer esse trabalho foi com este script:

#!/bin/bash
# NAME: find-cache
# DESC: cache find command search files to RAM
# NOTE: Written for: https://sobrelinux.info/questions/274063/improve-initial-use-of-find-performance-time"========================" >> /tmp/find-cache.log
    printf "find-cache.log # $i: "  >> /tmp/find-cache.log
    date                            >> /tmp/find-cache.log
    echo "Free RAM at start:"       >> /tmp/find-cache.log
    free -h | head -n2              >> /tmp/find-cache.log
    printf "Count of all files: "   >> /tmp/find-cache.log
    SECONDS=0                       # Environment variable
    time find /* 2>/dev/null|wc -l  >> /tmp/find-cache.log
    duration=$SECONDS               # Set elapsed seconds
    echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds for find." \
                                    >> /tmp/find-cache.log
    echo "Free RAM after find:"     >> /tmp/find-cache.log
    free -h | head -n2              >> /tmp/find-cache.log
    echo "Sleeping 15 seconds..."   >> /tmp/find-cache.log
    sleep 15
done

Copie o texto acima para um arquivo de script chamado: find-cache . Coloque o nome do script em Aplicativos de inicialização . Use as instruções na próxima seção, mas substitua o nome do comando /usr/bin/find... por /<path-to-script>/find-cache .

Não se esqueça de marcar o script como executável usando:

chmod a+x /<path-to-script>/find-cache

<path-to-script> deve estar em seu ambiente $ PATH, como /usr/local/bin ou preferencialmente /home/<your-user-name>/bin . Para verificar novamente, use echo $PATH para revelar a variável de ambiente.

Sempre que faço login, geralmente inicio conky e firefox . Você provavelmente faz outras coisas. Para ajustar as configurações do seu sistema, verifique o arquivo de registro:

$ cat /tmp/find-cache.log
========================
find-cache.log # 1: Sun Apr 22 09:48:40 MDT 2018
Free RAM at start:
              total        used        free      shared  buff/cache   available
Mem:           7.4G        431M        5.9G        628M        1.1G        6.1G
Count of all files: 1906881
0 minutes and 59 seconds for find.
Free RAM after find:
              total        used        free      shared  buff/cache   available
Mem:           7.4G        1.1G        3.0G        599M        3.3G        5.3G
Sleeping 15 seconds...
========================
find-cache.log # 2: Sun Apr 22 09:49:54 MDT 2018
Free RAM at start:
              total        used        free      shared  buff/cache   available
Mem:           7.4G        1.2G        2.9G        599M        3.3G        5.3G
Count of all files: 1903097
0 minutes and 9 seconds for find.
Free RAM after find:
              total        used        free      shared  buff/cache   available
Mem:           7.4G        1.1G        3.0G        599M        3.3G        5.3G
Sleeping 15 seconds...

    (... SNIP ...)

Observação: entre a 1ª e a 2ª RAM sem iteração, a taxa cai 3 GB, mas firefox está restaurando 12 guias ao mesmo tempo.

O que está acontecendo? Por alguma razão, quando find é executado apenas uma vez em um trabalho bash de inicialização, ou um trabalho bash cron reboot, o Linux Kernel pensa: "Eles provavelmente não quer manter o cache da página, então eu vou esvaziá-lo para salvar a memória RAM ". No entanto, quando o comando find é executado 10 vezes, como neste script, o Kernel do Linux pensa: "Whoaa eles realmente gostam desse material no cache da página, é melhor não limpá-lo" .

Pelo menos esse é o meu melhor palpite. Independentemente do motivo, essa abordagem funciona como testada várias vezes.

O que deve funcionar, mas não funciona

Abaixo estão duas tentativas de fazer este projeto funcionar. Eu os deixei aqui para que os outros não perdessem tempo repetindo-os. Se você acha que pode consertá-los por todos os meios, refine-os, poste uma resposta e eu vou alegremente votar.

Usar aplicativos de inicialização

Toque e solte a tecla Windows / Super (tem o ícone: ou ou ) para trazer dash .

No campo de pesquisa, digite startup e você verá o ícone Startup Applications . Clique no ícone. Quando a janela abrir, clique em Add à direita. Preencha os novos campos do Programa de inicialização da seguinte forma:

  • Preencha o nome como Cache Find to RAM .
  • Preencha o comando como sleep 30 && find /* 2>/dev/null | wc .
  • Adicione um comentário como "Execução inicial do comando Localizar para armazenar em cache o disco para ram".
  • Clique no botão Add na parte inferior.

Agora reinicie e verifique o desempenho do comando find .

Créditos: Ícones da chave do Windows copiados do Super Usuário post .

Cron na reinicialização

Você pode usar cron para chamar o comando find no momento da inicialização para armazenar em cache o disco lento para RAM rápida. Execute o comando crontab -e e adicione a seguinte linha na parte inferior:

@reboot /usr/sleep 30 && /usr/bin/find /* 2>/dev/null | wc -l
  • @reboot informa cron para executar este comando a cada inicialização / reinicialização.
  • /usr/sleep 30 tem o comando find aguardando 30 segundos antes de executar, para que a inicialização seja executada o mais rápido possível. Aumente isso para 45 ou 60, dependendo da velocidade de inicialização, do tempo de login e dos aplicativos de inicialização a serem executados.
  • /usr/bin/find /* 2>/dev/null | wc-l chama o comando find pesquisando todos os arquivos ( /* ). Quaisquer mensagens de erro estão ocultas por 2>/dev/null . O número de arquivos é contado usando | wc -l . No meu sistema, são cerca de 2 milhões devido a uma instalação do Ubuntu e duas instalações do Windows 10.
  • Depois de adicionar a linha use Ctrl + O seguido por Enter para salvar o arquivo.
  • Depois de salvar o arquivo, use Ctrl + X para sair do editor nano usado por cron . Se você escolheu um editor diferente de nano , use os comandos apropriados para salvar e sair.

Como sempre, o acrônimo YMMV (Sua milhagem pode variar) se aplica.

Após a reinicialização, fiz esses testes para provar que não funciona :

rick@alien:~$ time find / -type f \( -name "*.tar" -o -name "*.tar.*" \) 2>/dev/null | wc
     26      26    1278

real    1m10.022s
user    0m7.246s
sys     0m12.840s
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~$ time find / -type f \( -name "*.tar" -o -name "*.tar.*" \) 2>/dev/null | wc
     26      26    1278

real    0m8.954s
user    0m2.476s
sys     0m3.709s
    
por WinEunuuchs2Unix 22.04.2018 / 14:37