BufferManager


O WCF faz uso internamente de uma classe chamada BufferManager. Como o próprio nome sugere, ela faz o gerenciamento de memória durante as requisições, e ao invés de ficar criando array de bytes para ler ou escrever uma mensagem, o BufferManager gerencia um pool de buffers para fazer uma melhor reutilização quando o recurso não é mais necessário.

Quando a requisição é lida e a memória reservada para isso não é mais necessária, este gestor recicla a mesma ao invés de descartar, evitando assim ter todo o custo de criação e alocação quando uma nova requisição chegar. A não utilização de um gestor de memória pode degradar a performance do serviço, do host e, consequentemente, da máquina onde tudo isso é executado.

Os bindings já fornecem propriedades para criar e gerenciar o BufferManager, a saber: MaxBufferPoolSize e MaxBufferSize. A primeira indica a quantidade máxima de memória (em bytes) que ele terá, enquanto a segunda, indicará o máximo de memória que cada item dentro do pool poderá ter, também em bytes. É importante dizer que a propriedade MaxBufferSize deve ter o mesmo valor da propriedade MaxReceivedMessageSize.

Engana-se quem acha que esta classe só traz benefícios. Se ela for mal configurada, a memória pode não ser devolvida/reciclada, e em pouco tempo, esgotará os recursos disponíveis na máquina. O algoritmo utilizado por esta classe, cria os pools de acordo com o tamanho das mensagens que precisam ser manipuladas, e se não havendo nenhum pool que atenda a mesma ou a mensagem é maior que o valor estipulado na configuração, o WCF aloca memória diretamente na HEAP, ou seja, não gerenciada pelo BufferManager.

Se isso ocorrer com frequência, ao longo do tempo os recursos estarão esgotados e as mensagens não serão mais processadas. É comum ver cenários onde todos as configurações são definidas com seus valores máximos (int.MaxValue), e isso poderá impactar consideravelmente o serviço. É importante dimensionar as configurações de acordo com a necessidade de cada serviço, baseando-se, principalmente, na demanda e tamanho das mensagens que chegam até ele.

Há uma forma de informar ao runtime do WCF para não utilizer o pool de buffers. Para isso basta configurar a propriedade MaxBufferPoolSize com o valor 0 (zero). Isso fará com que o WCF crie um buffer para cada requisição diretamente na memória HEAP, e fica a cargo do Garbage Collector gerenciar o seu tempo de vida. Para confirmar isso, no interior da classe BufferManager, se o valor informado for zero, a classe GCBufferManager é criada, e caso contrário, a classe PooledBufferManager é utilizada.

Se criarmos um pequeno exemplo de um serviço que retorna uma coleção de objetos (5000), podemos perceber no resumo do profiler que foi aplicado à execução, uma diferença significativa da quantidade de bytes que foram alocados quando utilizamos a propriedade MaxBufferPoolSize com valor diferente de zero e com valor igual a zero.

O buffer é útil quando falamos de mensagens pequenas. Quando se tratam de mensagens que ultrapassam 64KB, opte por não utilizar este recurso.

Anúncios

2 comentários sobre “BufferManager

  1. Como ficaria o Web.config do cliente e do servidor? Pois eu alterei o MaxBufferPoolSize para 0, pois passo um array com muitos itens e continua dando mensagem de erro (413) Too Large

Deixe uma resposta

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