the_almeida
(usa Sabayon)
Enviado em 04/05/2011 - 11:19h
Olá pessoal!
Estou desenvolvendo um programa em C (em ambiente Linux) que, na sua inicialização, executa um restore de um backup de informações.
Para validação das informações lidas, acesso um arquivo muito grande, onde estão os meus dados, e verifico se cada um deles possui o padrao esperado.
Esse acesso ao disco (ao arquivo grande) acontece em milhões de leituras de 32 bytes em posições aleatórias, não lineares.
Dentro do arquivo que estou lendo, tenho dados que me interessam, que variam o seu tamanho de poucos KB até alguns GB. Cada dado possui cabeçalho e calda, como um pacote. Esses cabeçalhos e caldas, de 32 bytes cada, que estou lendo nesse trecho de código.
Acontece que essa leitura está extremamente lenta, de maneira a impossibilitar o uso dessa estratégia no programa.
Acredito que as posições aleatórias dos dados no disco devem ter grande influência nesse baixo desempenho.
Usando um programa simples que mede a taxa de IO no disco, pude perceber que o programa acessa o disco a apenas 1,5MB/s, em média. No final da execução do loop de leitura, ele parece aumentar a taxa para até 10MB/s, o que ainda não compreendi o porquê.
Estou usando um HD sATA, mas as taxas estão baixas mesmo para um IDE.
Para executar as leituras, já tentei estratégias do tipo (simplificando):
// Posicionamento no offset desejado com lseek, leitura com read, comparação com os dados esperados com memcmp
for(;;){
lseek(offset);
read(buffer);
!memcmp(buffer, esperado);
}
// Mapeamento do arquivo inteiro em memória, comparacao diretamente do offset do arquivo, com os dados esperados
arq_ptr = mmap(arquivo)
for(;;){
!memcmp(arq_ptr + offset, esperado);
}
munmap(arquivo)
// Mapeamento de cada porcao do arquivo desejado em cada iteracao, e comparacao com os dados esperados.
for(;;){
arq_ptr = mmap(arquivo, offset);
!memcmp(arq_ptr, esperado);
munmap(arquivo);
}
Todas as estratégias demonstraram o mesmo desempenho, a mesma taxa de acesso ao disco. Mesmo a estratégia de mapeamento do arquivo em memória que, pelo que entendo, deveria ser mais rápida.
Ou seja, meu gargalo está realmente no acesso ao disco, e não nas funções ou chamadas de sistema utilizadas.
Nos meus testes tomei o cuidado de reiniciar o computador antes de cada execução, para esvaziar as caches e RAM, pois após a primeira execução do programa, o mesmo executa mais de 600 vezes mais rápido, devidos às caches e etc.
Também tentei usar a função madvise para indicar ao kernel a natureza aleatória dos dados nessa região de memória (no caso do arquivo mapeado), para que o read ahead não se tornasse um problema. Porém, isso também não surtiu efeito.
Não sei se preciso mudar alguma coisa na minha implementação, ou se realmente não há modo de acessar tantas posições randômicas de forma mais rápida.
Algum de vocês já teve um problema parecido? Conhece alguma alternativa para a situação?
Obrigado!