logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

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

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

Como eu já disse em um post anterior, estou fazendo um parser de arquivos IDL, usando somente C++ ISO (nada de Win32), STL e Boost. Apesar de estar realmente impressionado com o desempenho do meu parser do jeito que está, eu me propus a testar o nível de otimização de I/O que seria possível usando a API Win32 diretamente. Vou publicar uma sequência de posts contando minhas exeriências com isso, explicando os métodos e ferramentas que eu usei para chegar às conclusões.

Primeiro, deixe-me explicar algo sobre desempenho (ou performance). Ultimamente eu tenho trabalhado bastante com isso, minha atribuição na empresa onde trabalho é (entre outras) pegar programas, serviços e componentes que já funcionam e melhorá-los. As melhorias são feitas em vários aspectos, tanto melhorias na estabilidade dos serviços quanto melhorias de desempenho.

Existem vários fatores importantes para se fazer melhoria de desempenho em um software. Conhecimento da linguagem de programação usada (C++ no meu caso) é muito importante, assim como é importante o conhecimento do funcionamento das bibliotecas (como a grande maioria das bibliotecas C++ são pequenas e com o fonte disponível, essas tarefa exige muito estudo de código fonte e pouca adivinhação ou disassembly). Outro fator muito importante é o conhecimento do sistema operacional e quais interações seu programa tem com cada parte dele. Nesse caso específico, o conhecimento do funcionamento do I/O do sistema operacional é muito importante, até para podermos saber quais opções temos para fazer essa melhoria. Um melhoria pode envolver uma modificação - algumas vezes pequena - no método usado para se chegar a um resultado, ou uma mudança completa no enfoque ou no algoritmo.

Todos os fatores que eu citei são importantes, mas o fator mais importante não é um conhecimento técnico. Chama-se mensuração. Só é possível dizer que alguma coisa foi melhorada se você souber exatamente o estado dela no momento atual, e se você conseguir mensurar exatamente qual o nível de melhoria entre uma modificação e outra. O conceito de melhor é algo muito subjetivo, não resolve o problema. Não basta o software ser "melhor", deve-se saber o "quão melhor" esse software é. E, depois disso, saber se o esforço dedicado a essa melhoria realmente valeu a pena, ou se foi muito trabalho para uma melhoria pequena.

A estrutura do parser é simples, e da forma que está feito hoje (sem Win32), o código que faz o I/O é muito parecido com o abaixo:

void MidlParser::ParseMidlFile(const char* fileName)
{
   fstream f;
   string str;
   
   ...
   
   if(m_bParseAsImportFile)
   {
      if(!OpenIncludeFile(fileName, &f, &m_parsedFileName))
         throw ParseException(string("error opening import file "") + fileName + 
                              "\"", *this, m_parsedFileName);
	   ...
   }
   else
   {
      f.open(fileName, ios::in);

      if(f.fail())
         throw ParseException(string("error opening file "") + fileName + 
                              "\"", *this, m_parsedFileName);
	  ...
   }
   
   //
   // carrega o arquivo inteiro em uma string STL
   //
   getline(f, str, f.widen(EOF));
	
   //
   // Inicializa o tokeninzer
   //
   m_Tokenizer.assign(str,char_separator("\t\r " , "\n\"*,;:{}/[]()"));
   
   ...  
   
   //
   // Loop que interpreta o IDL
   //
   for(;;)
   {
	  // ...
   }

Quando um arquivo é interpretado, diversas estruturas - IdlInterface, IdlMethod, IdlParameter, etc - são preenchidas com as informações interpretadas. Isso faz com que o interpretador fique completamente independente do gerador de proxy/stub que consumirá essas estruturas, o que me permite, futuramente, usar outro formato que não o Microsoft IDL.

Para um arquivo IDL comum, aproximadamente 400kb de texto deve ser lidos, em aproximadamente 10 arquivos. A maioria dos arquivos interpretados fazem parte do Windows Platform SDK, que definem os tipos de dados padrão do COM. A saída do parser é essa:

Parsing import file oaidl.idl
Parsing import file objidl.idl
Parsing import file unknwn.idl
Parsing import file wtypes.idl
Parsing import file ocidl.idl
Parsing import file oleidl.idl
Parsing import file servprov.idl
Parsing import file urlmon.idl
Parsing import file msxml.idl
Finish (234ms)

No próximo post da série veremos algumas estatísticas sobre o programa da forma que está e começaremos a fazer algumas otimizações.


Em 08/08/2005 02:58, 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
  ::::