logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

Usando Win32 API para otimizar o I/O, parte 4

Parte Zero     Parte 1     Parte 2     Parte 3     Parte 4     Parte 5     Parte 6     Fontes do parser

Conhecer a arquitetura do sistema operacional e de todas as dependências do seu software é essencial na hora de fazer otimização. Muitas vezes, mudanças muito pequenas no código podem melhorar substancialmente um software. Até porque, uma mudança pequena pode causar grandes mudanças no funcionamento de um módulo do sistema operacional ou de alguma biblioteca.

Além do conhecimento, é importante saber bem o que se está fazendo (e prestar atenção na documentação :-)). Na documentação do CreateFile na MSDN, estão listados diversos flags que você pode passar quando abre um arquivo. No nosso caso específico, o que mais chama atenção é o FILE_FLAG_SEQUENTIAL_SCAN:

FILE_FLAG_SEQUENTIAL_SCAN A file is accessed sequentially from beginning to end. The system can use this as a hint to optimize file caching. If an application moves the file pointer for random access, optimum caching may not occur. However, correct operation is still guaranteed.
Specifying this flag can increase performance for applications that read large files using sequential access. Performance gains can be even more noticeable for applications that read large files mostly sequentially, but occasionally skip over small ranges of bytes.

Usando essa flag, estamos dizendo ao Windows que acessaremos o arquivo do início ao fim, sequencialmente. A função interpreta isso como uma dica, que pode ser usada para otimizar o cache do arquivo. Sabendo como acessaremos o arquivo, o Windows pode "prever" nosso comportamento e ficar preparado para isso.

Modificando o trecho de código que abre o arquivo, ele ficará assim:

//
// chama atual para abrir um arquivo
//
hFile = CreateFile(str.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, 
                   OPEN_EXISTING, NULL, NULL);

//
// nova chamada para abrir um arquivo
//
hFile = CreateFile(str.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, 
                   OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

Refeitos os testes de desempenho, temos os seguintes resultados:

Média de tempo (50 chamadas):

228,01 ms - versão usando a runtime do C++
214,68 ms - versão usando CreateFile
204,17 ms - versão usando CreateFile com FILE_FLAG_SEQUENTIAL_SCAN

5,15% - melhoria em relação a versão Win32 sem FILE_FLAG_SEQUENTIAL_SCAN
11,68% - melhoria em relação a versão inicial (runtime C++)

Ganhamos mais ~5% de desempenho somente trocando UM flag em UMA chamada. Isso foi quase a mesma melhoria que ganhamos trocando todos os acessos feitos usando a runtime do C++ por chamadas Win32. Conhecimento é poder.

Em 29/08/2005 16:15, por Rodrigo Strauss


  
 
 
Comentários
Algo a dizer?
Nome:


Site:


E-mail:


Escreva o número vinte e seis:


 Não mostre meu e-mail no site, não serve pra nada mesmo...

Comentário





Os comentários devem ser sobre assuntos relativos ao post, eu provavelmente apagarei comentários totalmente offtopic. Se quiser me enviar uma mensagem, use o formulário de contato. E não esqueça: isso é um site pessoal e eu me reservo o direito de apagar qualquer comentário ofensivo ou inapropriado.
rebarba rebarba
  ::::