Pergunta

Eu tenho um aplicativo que lê a partir de grande quantidade de filas MSMQ(cerca de 10000 no momento).Eu uso queue.BeginPeek com UInt32.MaxValue tempo de espera para receber a mensagem da fila.Quando aparecer a mensagem na fila, eu processo-o e chamada de queue.BeginPeek novamente.Então, eu ouvi todas as filas, mas a mensagem de processamento é realizado no Pool de threads.

Eu notei que o uso de memória cresce lentamente(de duas semanas de trabalho provocam o crescimento de 200 a 800 MB).Depois de investigar o arquivo de despejo de eu ver típica fragmentação de imagem com vários objetos (alguns deles têm tamanho sobre vários megabytes).E há objetos fixados entre os furos.

Esta parece ser a situação comum quando se trabalha com as chamadas de código não gerenciado, que criam objetos fixados.Mas eu não encontrar alguma solução na internet.

Assim é o gerenciamento de memória no .NET tão puro, que não permita a completa mesmo em cenários simples, ou eu perdi alguma coisa?

Editar : Eu fiz algumas investigações em aplicações de exemplo.Os furos(gratuito zonas de memória, livre chamado objetos) entre objetos fixados são reutilizados por GC quando a alocação de memória para novos objetos.Mas no meu aplicativo de produção de objetos fixados são de longa vida, e eles finalmente aparecer na 2ª geração com os buracos entre elas(porque o GC apenas desloca a fronteira que separa as gerações).Como eu tenho muito pouco tempo normal-objectos vivos, eu vejo isso buracos na 2ª geração, em arquivo de despejo.

Assim, o consumo de memória do aplicativo pode crescer para 10000*(tamanho médio do furo).(10000 é o número de filas que podem também aumentar no futuro).Eu não tenho idéia de como corrigir isso no momento.O único jeito é reiniciar o aplicativo de tempo em tempo.

Mais uma vez só posso perguntar, o porquê .NET não tem heap separado para objetos fixados?(talvez isso é o novato pergunta).No momento em que eu vejo que a chamada assíncrona as operações que trabalham com código não gerenciado pode causar problemas de memória.

Foi útil?

Solução

Depois de olhar o código-fonte para o wrapper gerenciado para o MSMQ parece que você tropeçou em um verdadeiro problema usando a API.Chamar BeginPeek vai criar uma coleção de propriedades que são, em seguida, preso antes de passado para a API não gerenciada.Somente quando uma mensagem é recebida são essas propriedades não-fixado, mas para continuar a receber mensagens você tem que chamar BeginPeek neste ponto, levando à fragmentação da memória ao longo do tempo.

Se esta fragmentação é uma preocupação real com o único hack que eu possa vir até a cada hora ou assim que você deve cancelar todas as chamadas para BeginPeek, força de coleta de lixo e, em seguida, retomar a audição normal de operações.Isso deve permitir que o coletor de lixo para lidar com a fragmentação.

Outras dicas

Bem, se é um problema com os objetos fixados a ser de longa duração do que uma simples alternativa seria a utilização de um limite de tempo no BeginPeek com uma duração menor para mantê-los de mover-se para a próxima geração.Após cada tempo de espera e EndPeek você pode reemitir BeginPeek.Dependendo de quando as propriedades que Martin se refere ao " são criados e eliminados, poderá ter de recriar o objecto de fila (não a fila em si, obviamente, apenas a amanged wrapper).Embora com alguma sorte, você não precisa levá-lo tão longe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top