Arquivo para março \26\UTC 2009

XmlSerializer e sGen.exe – Melhorando Performance

Utilizamos há algum tempo aqui na empresa uma camada caseira de acesso à dados que salva as configurações dos diferentes servidores e bancos de dados a serem acessados em um arquivo XML. Este arquivo XML, por sua vez, é lido pela biblioteca através da classe XmlSerializer (System.Xml.Serialization), que o transforma numa coleção de objetos com apenas duas linhas de código.. simples e configurável, sempre nos pareceu uma excelente opção!

Tudo corria bem até que um de nossos produtos começou a ganhar uma escala até então inédita para nós num único servidor, e a criação das classes de acesso a dados começou a ficar bastante lenta. Fuça daqui, revira de lá, chegou-se à conclusão que a serialização do bendito arquivo XML estava consumindo processamento demais. Como não suspeitamos do .NET Framework 1.1 (sim, ainda estávamos nele no ano passado), acabamos criando uma Factory que centralizava numa coleção estática todas coleções desserializadas pela aplicação, realizando o controle da modificação do arquivo através da classe FileSystemWatcher (System.IO). A performance melhorou e tudo parecia estar mais uma vez sob controle..

Como nada dura para sempre, entretanto, aconteceu desta mesma camada de acesso a dados ter problemas com concorrência. Coincidentemente, no meio dessa análise de concorrência, ocorreu também de eu receber um link para o recurso de profiling de código do VSTS (assunto para um próximo post) e, adivinhem, não é que a leitura do XML continuava consumindo tempo demais?

Tudo bem que a performance dificilmente estaria ligada aos problemas de concorrência, mas era preciso entender o porquê daquilo. Procedimento padrão: Google -> XmlSerializer performance e… batata! Caí num artigo sobre um problema de performance com o XmSerializer e seus workarounds para os frameworks 1.1 e 2.0+. O que acontece, em resumo, é o seguinte:

  • Ao criar uma instância da classe XmlSerializer com os construtores XmlSerializer(type) ou XmlSerializer(type, string), o .NET Framework cria automaticamente o serializador e desserializador daquele tipo, criando um assembly para armazená-lo (sim, isso mesmo, um assembly é criado em tempo de execução)..
  • No .NET Framework 1.1, isto era feito à cada chamada do construtor, independente se aquele tipo já foi criado ou não! Incrível, não? Alguém se habilita pra chutar por que tínhamos problemas de performance? Existe um workaround no artigo que linkei acima para este caso, mas não testei por não ser o foco;
  • Já no .NET Framework 2.0+, isto é feito assim que a classe é criada e o assembly é reutilizado no caso de reincidência de construção daquele tipo. Bem melhor, mas longe do ideal para sistemas em que a performance é crítica..

A grande melhoria de performance vem com o fato de que é possível, através de um utilitário de linha de comando chamado sGen.exe (acessível pelo VS promt) criar uma pré-compilação de todos esses tipos que vão ser serializados. É possível compilar todos os tipos de uma DLL ou somente alguns (sgen MeuAssembly.dll, para todos, por exemplo). Também é possível, nas opções de Build do projeto no próprio VS habilitar uma opção chamada Generate Serialization Assembly, que vai fazer exatamente o mesmo trabalho. Em ambos os casos, é gerado na pasta de build um arquivo com o nome MeuAssembly.XmlSerializers.dll, que quando jogado na sua pasta \bin reduz, e muito, o tempo de criação da classe XmlSerializer.

ATENÇÃO: O arquivo não será gerado caso seu Assembly possua classes ou tipos cujo nome coincida com tipos do .NET Framework ou mesmo existam duas classes com o mesmo nome em namespaces diferentes. Nesse caso, os tipos em questão devem ser decorados com os attributes de System.Xml.Serialization (XmlType em específico) para adquirir um nome ou namespace único! No caso de problemas, rode diretamente pelo sGen para ganhar mensagens mais detalhadas.

É isso! Esta pode não ser uma situação das mais corriqueiras mas que pode destruir a performance de sua aplicação, então é sembre bom ficar atento!

Abraços!

Zé Filipe

Anúncios

Comeeeeça o jogo!

Começo a me preocupar comigo mesmo ao escrever um post mesmo sabendo que ninguém está lendo o blog.. 🙂

O objetivo desse espaço é servir como um diário de bordo das andanças, tombos e lições aprendidas no dia-a-dia de tecnologia, principalmente .NET. Melhor assim, já que mesmo que ninguém visite o blog sei que vou poder salvar algum tempo de Google nas tão comuns situações de “eu já vi isso. como se fazia mesmo?“.

O nome do blog, certamente familiar pra alguns (aquelas aulas de criatividade não serviram pra nada mesmo), refere-se à funcionalidade de debug existente em IDEs pra acompanhar o valor de uma variável ao longo da execução. Mais uma tentativa pra ver se alguém assina o RSS Feed esperando encontrar coisas interessantes.. 🙂

Agora que o gelo está quebrado, vem o primeiro post “as vera”! E, é claro, pra não fugir das frases prontas: sugestões, críticas e elogios são sempre muito bem-vindos..

Abraços!

Zé Filipe


Perfil

Olá! Meu nome é José Filipe e sou o autor deste blog. Trabalho como Gerente de Desenvolvimento da todo! BPO, onde sou responsável pela manutenção e evolução de pessoas, processos e sistemas desenvolvidos em diferentes tecnologias. Atualmente curso uma especialização em Engenharia de Software pela PUCPR, em Curitiba, mas moro em Florianópolis, onde me graduei em Sistemas de Informação pela UFSC. Possuo o título de MCP e com base nas experiências do dia-a-dia espero trazer ao blog assuntos interessantes sobre arquitetura e desenvolvimento .NET..

Arquivos

Páginas

março 2009
S T Q Q S S D
    abr »
 1
2345678
9101112131415
16171819202122
23242526272829
3031