Forçar o diretório a sempre estar em cache


35

Eu tenho testado métodos diferentes para melhorar o tempo necessário para compilar todo o meu projeto c ++. Atualmente, leva ~ 5 minutos. Eu experimentei distcc, ccache e outros. Recentemente, descobri que se eu copiar todo o meu projeto em uma unidade de RAM e compilar a partir daí, o tempo de compilação será reduzido para 30% do original - apenas 1,5 minutos.

Obviamente, trabalhar a partir da unidade de RAM não é prático. Então, alguém sabe como eu posso forçar o sistema operacional a manter sempre um determinado diretório em cache ? Ainda quero que o diretório seja sincronizado de volta ao disco normalmente, mas também quero sempre uma cópia dos dados na memória. Isso é possível?

EDIT: Como uma solução possível, pensamos apenas em lançar um daemon que é executado a rsynccada 10 segundos ou mais para sincronizar a unidade de disco com uma unidade de RAM. Depois, executamos a compilação a partir da unidade de RAM. O rsyncé super rápido, mas isso realmente funciona? Certamente o sistema operacional poderia fazer melhor ....


O cache não é a única diferença entre tmpfs e ext3 / 4; eles têm registro no diário, por exemplo, que será gravado independentemente do armazenamento em cache.
André Paramés 28/01

11
Você poderia timecompilar e compartilhar o resultado conosco? Isso dissiparia algumas controvérsias. make clean && /usr/bin/time -v make(não use a festa construído no timecomando)
shellholic

11
@she Por que não o comando interno do bash?
2241111

3
@Tshepang o timeconstruída em bash ( help time) tem muito menos detalhes (sem detalhado opção) do que o tempo GNU ( man time) sobre o I / O, trocas de contexto, ...
shellholic

Respostas:


18

A maneira óbvia de manter um monte de arquivos no cache é acessá-los com frequência. O Linux é muito bom em arbitrar entre troca e armazenamento em cache, então suspeito que a diferença de velocidade observada não se deva ao fato de o sistema operacional não manter as coisas no cache, mas a alguma outra diferença entre o uso de tmpfs e outras tentativas.

Tente observar o que está fazendo IO em cada caso. A ferramenta básica para isso é iotop. Outras ferramentas podem ser úteis; veja detalhamento da carga de E / S de disco do Linux, por caminho e / ou processo do sistema de arquivos? , Que programa no Linux pode medir E / S ao longo do tempo? e outros threads na falha do servidor.

Aqui estão algumas hipóteses sobre o que poderia estar acontecendo. Se você fizer medições, mostre-as para que possamos confirmar ou refutar essas hipóteses.

  • Se você tiver os tempos de acesso a arquivos ativados, o sistema operacional poderá perder bastante tempo gravando esses tempos de acesso. Os tempos de acesso são inúteis para uma árvore de compilação; portanto, verifique se eles estão desativados com a noatimeopção de montagem. Sua solução tmpfs + rsync nunca no disco rígido, portanto, nunca precisa gastar tempo extra escrevendo vezes.
  • Se as gravações estiverem sincronizando , seja porque o compilador chama sync()ou porque o kernel libera seus buffers de saída com frequência, as gravações levarão mais tempo para um disco rígido do que para tmpfs.

Eu também tenho esse sentimento. A compilação consome muita CPU, em vez de E / S.
phunehehe

Hmmm, eu gostaria de ver um comentário de @JaredC aqui confirmando ou negando a hipótese de Gilles. 1,5 vs. 5 minues é uma grande diferença ...
Daniel Alder

8

Por padrão, o Linux usa a RAM como cache de disco. Como demonstração, tente executar time find /some/dir/containing/a/lot/of/files > /dev/nullduas vezes, a segunda vez é muito mais rápida, pois todos os inodes de disco são armazenados em cache. O ponto aqui é como fazer uso desse recurso do kernel e parar sua tentativa de substituí-lo.

O ponto é mudar o swappiness. Vamos considerar três tipos principais de uso de memória: programas ativos, programas inativos e cache de disco. Obviamente, a memória usada pelos programas ativos não deve ser trocada e a escolha entre duas outras é bastante arbitrária. Deseja uma troca rápida de programa ou acesso rápido a arquivos? Uma baixa troca prefere manter os programas na memória (mesmo que não sejam usados ​​por muito tempo) e uma alta troca prefere manter mais cache de disco (trocando programas não utilizados). (a escala de swappiness é de 0 a 100 e o valor padrão é 60)

Minha solução para o seu problema é alterar o swappiness para muito alto (90-95 para não dizer 100) e carregar o cache:

echo 95 | sudo tee /proc/sys/vm/swappiness > /dev/null # once after reboot
find /your/source/directory -type f -exec cat {} \; > /dev/null

Como você imagina, você deve ter memória livre suficiente para armazenar em cache todos os seus arquivos de origem e objetos, bem como o compilador, arquivos de cabeçalhos incluídos, bibliotecas vinculadas, seu IDE e outros programas usados.


Isso é útil em geral, mas o que realmente quero é que meu código-fonte tenha baixa permuta, mas todo o resto tenha uma permuta normal. Basicamente, tenho muitas coisas em segundo plano, mas quero limitá-las a 6 de 8 GB, mantendo sempre os outros 2 GB para o código-fonte. Não quero arriscar que seja trocado ... sempre ... porque isso é chato.
JaredC

Swappiness é amplo no sistema. De fato, se você estiver fazendo outra coisa e seus arquivos forem descarregados da memória, basta recarregá-lo com a segunda linha. Se a memória tiver que ser liberada para outra coisa, você realmente "não quer arriscar" que seja feita a partir da troca. Aliás, tmpfsno mesmo caso, também seriam trocados.
shellholic

2
Pessoalmente, senti uma alta permuta é absolutamente horrível nas estações de trabalho. Embora algumas funções possam ser aceleradas pelo cache maior (isto é, mais arquivos em cache), isso tem um preço: você paga por isso em termos de capacidade de resposta ao alternar entre programas, que é o que os usuários percebem primeiro ao trabalhar em um sistema. Ao mudar do navegador para o escritório, para outro navegador, para o e-mail, não posso esperar mais que um ou dois segundos para que cada programa volte a funcionar. Em todas as minhas máquinas Linux, geralmente defino a troca para um valor baixo de 10.
fgysin restabelece Monica

6

Forçar o cache não é o caminho certo para fazer isso. Melhor manter as fontes no disco rígido e compilá-las no tmpfs. Muitos sistemas de construção, como qmake e CMake, suportam construções fora da fonte.


6

O inosyncdaemon parece que faz exatamente o que você deseja se for sincronizar novamente com um ramdisk. Em vez de sincronizar novamente a cada 10 segundos, ele usa o recurso de inotificação do Linux para sincronizar novamente quando um arquivo é alterado. Eu o encontrei no repositório Debian como o inosyncpacote ou sua fonte está disponível em http://bb.xnull.de/projects/inosync/ .


Isso parece bastante útil. Vou investigar e relatar. Obrigado!
JaredC

5

Parece que isso funciona para mim se eu quiser manter certos arquivos ou todos os arquivos em um determinado diretório no cache.

O vmtouch parece fazer exatamente isso. Exemplo 5, pode haver o que você precisa.

vmtouch -dl /whatever/directory/

Eu precisava executá-lo como root com sudo


11
Não vê arquivos novos / removidos.
Vi.

3

Dada a memória suficiente, sua compilação a partir do ramdisk não faz E / S. Isso pode acelerar qualquer coisa que leia ou grave arquivos. A E / S é uma das operações mais lentas. Mesmo se você obtiver tudo em cache antes da compilação, ainda terá as E / Ss para gravação, embora elas tenham um impacto mínimo.

Você pode obter alguma aceleração pré-carregando todos os arquivos no cache, mas o tempo necessário para isso deve ser incluído no tempo total de compilação. Isso pode não lhe dar muita vantagem.

Construindo o objeto e os arquivos intermediários na RAM, e não no disco. Fazer construções incrementais pode obter ganhos significativos em construções frequentes. Na maioria dos projetos, faço uma compilação diária limpa e compilações incrementais no meio. Compilações de integração são sempre compiladas, mas tento limitá-las a menos de uma por dia.

Você pode obter algum desempenho usando uma partição ext2 com o atime desativado. Sua fonte deve estar no controle de versão em um sistema de arquivos com diário, como ext3 / 4.


2

Como afirmado anteriormente, a maneira óbvia é ler toda a estrutura de diretórios e o conteúdo do arquivo que você deseja que seja armazenado em cache.

Você pode automatizar isso escrevendo um script para monitorar a saída de vmstat 1(use qualquer ferramenta equivalente para o seu sistema operacional) e mantenha uma soma do número de blocos gravados e lidos. Depois que a soma ultrapassar o limite de sua escolha, leia todos os arquivos que você deseja armazenar em cache, redefina a soma e continue monitorando a saída vmstat. Para ler rapidamente arquivos: se sua árvore contiver muitos arquivos, evite find ... -exec cat; tente find ... -print0 | xargs -0 catum programa personalizado que não execute cat para cada arquivo.

O monitoramento de E / S de disco é preferível ao uso de um intervalo fixo, porque ele sinaliza para reler seus dados com mais ou menos frequência, dependendo da carga de E / S de disco.

Eu usei esse método automatizado com êxito em sistemas onde eu precisava que algumas leituras de arquivos de índice fossem sempre rápidas, evitando a E / S do disco rígido. Também usei o strace para fazer uma lista de todos os arquivos que são acessados ​​quando eu faço o logon, para manter tudo quente no cache para logins rápidos.

Esta pode não ser a melhor solução possível, mas me serviu bem.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.