Apagar grande número de arquivos no linux consome CPU

6

Eu gero mais de 50GB de arquivos de cache no meu servidor RHEL (e o tamanho de arquivo típico é de 200kb, então nenhum arquivo é grande). Quando tento excluir esses arquivos, demoram de 8 a 10 horas.

No entanto, o maior problema é que a carga do sistema é crítica para essas 8 a 10 horas. Existe alguma maneira onde eu possa manter o carregamento do sistema sob controle durante a exclusão.

Eu tentei usar

nice -n19 rm -rf *

mas isso não ajuda no carregamento do sistema.

P.S. Eu fiz a mesma pergunta em superuser.com mas não recebi uma resposta boa o suficiente para tentar aqui.

    
por Sanjay 29.03.2010 / 11:19

9 respostas

8

Aqui estão alguns pontos de referência para várias operações e sistemas de arquivos para sua referência. (Em um sistema ocupado, é claro, você teria resultados diferentes, mas esperamos que isso lhe dê uma idéia do que esperar).

Se eu estivesse na sua cadeira, tentaria obter uma referência básica do cenário:

  • estabeleça por quanto tempo a operação levará em hardware nu isolado de todo o resto (e sim, deve demorar muito, muito menos de 7 a 8 horas, mesmo em hardware bem antigo).
  • tente adicionar outras operações que normalmente ocorrem de maneira controlada e veja o que realmente faz com que ele seja executado por tanto tempo

Alguns números.

Em um notebook de 5 anos ext3 montado rw, noatime, em execução no topo e nada muito mais crie diretórios 10k com script shell create10kdirs.sh

#!/bin/bash
for i in $(seq 10000)
do
    mkdir $i
done

tempo de sudo ./create10kdirs.sh
24.59usuário
20.70system
0: 47.04desenvolvido
96% da CPU (0avgtext + 0avgdata 0maxresident) k80inputs + 8outputs (1major + 2735150minor) pagefaults 0swaps

delete 10k diretórios com sudo time rm -rf
0.10user
19.75system
0: 20.71 encapsulado
95% da CPU (0avgtext + 0avgdata 0maxresident) k0inputs + 8outputs (0major + 222minor) pagefaults 0swaps

mesmo hardware, ext4 montado rw, noatime criar diretórios 10k com script de shell sudo time create10kdirs.sh
23.96user
22.31sistema
0: 49,26 encapuçado
93% da CPU (0avgtext + 0avgdata0maxresident) k1896inputs + 8outputs (20major + 2715174minor) pagefaults 0swaps

delete 10k diretórios com sudo time rm -rf
0.13user
16.96system
0: 28.21 encapsulado
60% da CPU (0avgtext + 0avgdata0maxresident) k10160inputs + 0outputs (1major + 219minor) pagefaults0swaps

Notebook de 4 anos, xfs montado em rw, relatime, nobarrier em USB sudo time create10kdirs.sh
14.19user
13.86sistema
0: 29.75 encapsulado
94% da CPU (0avgtext + 0avgdata0maxresident) k432inputs + 0outputs (1major + 2735243minor) pagefaults 0swaps

delete 10k diretórios com o
sudo time rm -rf
0.13user
2.65system
0: 08.20elapsed
33% CPU (0avgtext + 0avgdata 0maxresident) k120inputs + 0outputs (1major + 222minor) pagefaults 0swaps

Conclusão: Este hardware antigo apagaria 400k arquivos pequenos + pastas no ext3 em aproximadamente 21s * 40 = 12m40s. No xfs (sem barreiras) ele faria isso em aproximadamente 5m20s. Concedida em ambos os casos de teste, a máquina de teste não estava sob carga pesada, mas para mim parece que seus problemas não estão estritamente relacionados à sua escolha do sistema de arquivos.

EDIT2 Além disso, depois de correr acima de benchmarks fui tentar o delete com encontrar . -mindepth 1 -maxdepth 1 -delete

e os resultados!:

ext3 excluir diretórios de 10k com sudo tempo encontrar. -mindepth 1 -maxdepth 1 -delete
0.04user
0.44system
0: 00.88elapsed
55% da CPU (0avgtext + 0avgdata 0maxresident) k516inputs + 8outputs (1major + 688minor) pagefaults0swaps

ext4 excluir diretórios 10k com o
sudo tempo encontrar. -mindepth 1 -maxdepth 1 -delete
0.05user
0.66system
0: 01.02elapsed
70% da CPU (0avgtext + 0avgdata 0maxresident) k568inputs + 0outputs (1major + 689minor) swaps de pagefaults

xfs excluir diretórios 10k com o
sudo tempo encontrar. -mindepth 1 -maxdepth 1 -delete
0.06user
Sistema 0.84system 0: 04.55 encapsulado
19% CPU (0avgtext + 0avgdata 0maxresident) k416inputs + 0outputs (3major + 685minor) pagefaults 0swaps

A conclusão real é que rm -rf não é muito inteligente e que vai ter baixo desempenho para árvores grandes. (desde que meu caso de teste seja realmente representativo).

Nota: Eu também testei a variante xargs e é rápido, mas não tão rápido quanto o acima.

    
por 29.03.2010 / 13:10
5

Como você mencionou em um comentário, você está usando ext3 .

É bem conhecido que rm de desempenho para arquivos grandes no ext3 é ruim; é uma das coisas que foram corrigidas em ext4 . Veja por exemplo este post , ou kernelnewbies (que menciona extensões melhoram as velocidades de exclusão e truncagem para arquivos grandes).

Eu não sei o quanto isso se aplica aos tamanhos de arquivo comuns. Eu esperaria aplicar pelo menos um pouco, já que com cerca de 200kB você já estaria usando blocos indiretos em ext3 , possivelmente em uma única extensão em ext4 .

Como solução alternativa (já que você provavelmente não fará upgrade para ext4 apenas para isso), exclua apenas alguns arquivos de cada vez e adicione um sleep entre as exclusões. Não é bonito, mas deve ajudar a reduzir a carga.

Além disso, se perder os arquivos em perda de energia não for um problema (já que é um cache de algum tipo), você pode colocá-los em uma partição separada que você mkfs novamente na inicialização e usar ext3 sem um diário ou até ext2 . A causa da alta carga é provavelmente o diário sendo liberado para o disco em conflito com as leituras (você mencionou em outro post que você tem muitas leituras simultâneas).

    
por 29.03.2010 / 13:05
3

Talvez o shell seja a causa do problema. Você deve usar diretamente encontrar: find /dir -mindepth 1 -maxdepth 1 -delete

    
por 29.03.2010 / 12:04
2

Isso pode ou não estar relacionado: mas tive ocasiões em que rm não conseguiu lidar com o número de arquivos que forneci na linha de comando (por meio do operador star). Em vez disso, eu usaria o seguinte comando do shell:

for i in *; do rm -rf $i; done

Nesse caso, você pode estar excluindo árvores. Nesse caso, o item acima pode não fazer o que você precisa. Você pode ter que dividir a operação de exclusão em partes, por exemplo,

for i in [a-mA-M]*; do rm -rf $i; done
for i in [n-zN-Z]*; do rm -rf $i; done
    
por 29.03.2010 / 11:58
1

Isso é apenas 250.000 arquivos ou mais, não deve ser um problema realmente - o sistema de arquivos que você está usando e este volume é usado para mais alguma coisa?

    
por 29.03.2010 / 11:29
1

Quando você tem muitos arquivos como descrito, você está invocando o comando a cada vez. Além disso, você deve ter em mente que no FS com registro no diário você está lidando com ocorrências de buffer e metadados que podem impactar muito os tempos do processo.

Sua melhor aposta é usar o comando find como mencionado acima apenas com um recurso menos que óbvio.

find / -name filename.* -exec /bin/rm -f '{}' \+

Basicamente, o "+" é seu amigo. O que isto faz é criar os nomes dos arquivos em conjuntos e invocar o comando rm uma vez por conjunto. Isso é praticamente o mesmo que o que 'xargs' faz, mas você não precisa se preocupar com os sinalizadores corretos se estiver no BSD / Linux.

Muito curioso quanto isso acelera para você. Então responda de volta se você ainda estiver por perto. Boa sorte!

    
por 24.08.2012 / 23:07
0
Depois de estudar os benchmarks do sistema de arquivos, escolhi o JFS como repositório de arquivos para os meus arquivos de vídeo mythtv, porque as exclusões de arquivos são rápidas (e o mythtv aguarda a exclusão terminar, tornando o IO lento).

Você também pode invocar 'rm' através de 'find' e 'xargs' em vez de rm -rf. Isso pode ser mais rápido:

find <dir> | xargs rm
    
por 29.03.2010 / 14:25
0

Que tal colocar uma lista desses arquivos no Perl e usar sua função unlink?

find <dir> | perl -nle 'unlink;'
    
por 30.03.2010 / 16:23
0

Concordo que não deve demorar tanto, mas, dependendo do armazenamento subjacente usado, pode ser esperado com as leituras intensivas. Acho que, no final das contas, sua melhor solução é adicionar discos adicionais e dividir suas atividades entre eles. O RAID pode ajudar em alguns cenários se você seguir esse caminho. O que o iostat lhe diz durante estes tempos? Você também pode usar um loop for e agrupar os comandos 'rm' em 'time' para obter algumas informações adicionais.

Outra possibilidade, dependendo da sua configuração e da aplicação do curso, mas talvez você possa fazer esses arquivos em cache em uma partição diferente e apenas formatar a unidade periodicamente, em vez de remover os arquivos? Acho que rodar o mkfs reduziria consideravelmente o tempo, mas o aplicativo não estará disponível enquanto isso não for o ideal.

Também gosto da ideia de limpá-los com mais frequência. Digamos que no cron você agende algo assim a cada hora:

encontre ./ -maxdepth 1 -tipo f -name "algum padrão" -ctime +1 -exec rm -f {} \;

Isso excluiria todos os arquivos com mais de 24 horas, em vez de tentar fazer todos de uma vez.

    
por 30.03.2010 / 16:28

Tags