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

6 Responses to “XmlSerializer e sGen.exe – Melhorando Performance”


  1. 1 ribeirofloripa 27/03/2009 às 00:26

    “XmlSerializer performance e… batata!”…impagável…Paulo Coelho dos blogs…=)

    Legal a idéia, vou acompanhar.

  2. 2 Emanuel 27/03/2009 às 09:38

    Cara, muito interessante. Vou ficar mais atento a esse tipo de situãção.

  3. 3 xaxim 30/03/2009 às 09:54

    Como fica com webservices? Pelo que sei, internamente o asp.net utiliza essa mesma classe para serializar e desserializar os tipos transportados.

  4. 5 Galeto 31/03/2009 às 10:03

    Muito bom artigo,
    boa sorte com seu blog,
    já adicionei um addwatch aqui….
    Esperando mais artigos…
    []s


  1. 1 NHibernate – Mapeando valores default como null: IUserType, IParameterizedType « Add Watch! Trackback em 21/05/2009 às 15:06

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s




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  

%d blogueiros gostam disto: