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.
É 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

“XmlSerializer performance e… batata!”…impagável…Paulo Coelho dos blogs…=)
Legal a idéia, vou acompanhar.
Cara, muito interessante. Vou ficar mais atento a esse tipo de situãção.
Como fica com webservices? Pelo que sei, internamente o asp.net utiliza essa mesma classe para serializar e desserializar os tipos transportados.
Pedro,
Neste caso pode ser utilizada a opção /p do sgen.exe, que gera os serializadores das classes de proxy do web service.
Para o caso de classes de proxy mapeadas para outros assemblies através de SchemaImporterExtensions (e não geradas automaticamente pelo VS) vale um teste.
Fonte: MSDN – XML Serializer Generator Tool (Sgen.exe)
Abraços.
Muito bom artigo,
boa sorte com seu blog,
já adicionei um addwatch aqui….
Esperando mais artigos…
[]s