Pergunta

Eu estou escrevendo um aplicativo C financeira # que receber mensagens da rede, traduzi-las em objeto diferente de acordo com o tipo de mensagem e finalmente aplicar a lógica de negócios do aplicativo sobre eles.

O ponto é que, após a lógica de negócios é aplicada, estou muito certo de que nunca vai precisar neste caso novamente. Em vez de esperar para o coletor de lixo para libertá-los, eu gostaria de explicitamente "delete"-los.

Existe uma maneira melhor de fazê-lo em C #, eu deveria usar um pool de objeto de reutilizar sempre o mesmo conjunto de exemplo ou há uma estratégia melhor.

O objetivo é evitar a coleta de lixo para usar qualquer CPU durante um processo crítico tempo.

Foi útil?

Solução

Não exclua-los imediatamente. Chamando o coletor de lixo para cada objeto é uma má idéia. Normalmente você realmente não quer mexer com o coletor de lixo em tudo, e processos críticos mesmo tempo são condições de corrida apenas esperando para acontecer se eles são tão sensível.

Mas se você sabe que vai ter ocupado vs períodos de carga de luz para o seu aplicativo, você pode tentar um GC.Collect mais geral () quando você chegar a um período de luz para estimular a limpeza antes do próximo período ocupado.

Outras dicas

Olhe aqui: http://msdn.microsoft.com/en-us /library/bb384202.aspx

Você pode dizer o coletor de lixo que você está fazendo algo crítico, no momento, e ele vai tentar ser bom para você.

Você bateu em si mesmo - usar um pool de objetos e reutilizar esses objetos. A semântica das chamadas para os objetos que precisam ser escondidos atrás de uma fachada de fábrica. Você precisa crescer a piscina, de alguma forma pré-definida. Talvez dobrar a cada vez que tamanho ela atinge o limite - um algoritmo de alta água, ou uma percentagem fixa. Eu realmente recomendo fortemente que você não chamar GC.Collect ().

Quando a carga na sua piscina fica baixo o suficiente você poderia encolher a piscina e que, eventualmente, irá desencadear uma coleta de lixo -. Permitir que a preocupação CLR sobre isso

A tentativa de adivinhar o coletor de lixo é geralmente uma idéia muito ruim. No Windows, o coletor de lixo é um geracional um e lata ser invocado para ser bastante eficiente. Há algumas exceções notáveis ??a esta regra geral - sendo a mais comum a ocorrência de um evento de um tempo que você sabe para um fato terá causado um monte de objetos antigos para morrer - uma vez que objetos são promovidos a Gen2 (o mais longo viveu) eles tendem a pendurar ao redor.

No caso que você menciona, você soa como se você está gerando uma série de objetos de vida curta - estes irão resultar em coleções Gen0. Estes acontecem com relativa frequência de qualquer maneira, e são os mais eficientes. Você poderia evitá-los por ter uma piscina reutilizável de objetos, se você preferir, mas é melhor para determinar com certeza se GC é um problema de desempenho antes de tomar tal ação -. O Profiler CLR é a ferramenta para fazer isso

Deve-se notar que o coletor de lixo é diferente em diferentes quadros .NET - sobre o quadro compacto (que é executado no Xbox 360 e em plataformas móveis) é um GC não-geracional e, como tal, você deve ser muito mais cuidado com o lixo o programa gera.

Forçar uma GC.Collect () é geralmente uma má idéia, deixe o GC para fazer o que faz melhor. Parece que a melhor solução seria a utilização de um conjunto de objetos que você pode crescer, se necessário -. Eu usei esse padrão com sucesso

Desta forma você evita não apenas a coleta de lixo, mas o custo de alocação regular também.

Finalmente, você tem certeza de que a GC está causando um problema? Você provavelmente deve medir e provar isso antes de implementar qualquer solução de economia de perf - você pode estar causando a si mesmo trabalho desnecessário

"O objetivo é evitar a coleta de lixo para usar qualquer CPU durante um processo crítico tempo"

Q: Se por momento crítico, você quer dizer que você está ouvindo alguma parte esotérica de hardware, e você não pode dar ao luxo de perder a interrupção?

A:. Se sim, então C # não é a língua de uso, você quer que Assembler, C ou C ++ para esse

Q: Se pelo tempo crítica, quer dizer, enquanto há muitas mensagens no tubo, e você não quer deixar o coletor de lixo coisas lentas para baixo?

A: Se assim você está se preocupando desnecessariamente. Pelos sons de coisas que seus objetos são muito curta, isso significa que o coletor de lixo irá reciclá-los de forma muito eficiente, sem qualquer aparente atraso no desempenho.

No entanto, a única maneira de saber com certeza é testá-lo, configurá-lo para ser executado durante a noite processamento de um fluxo constante de mensagens de teste, eu estarei atordoado se você suas estatísticas de desempenho podem detectar quando os GC entra em ação (e até mesmo se você pode manchá-lo, eu vou ser ainda mais surpreso se ele realmente importa).

Obter um bom entendimento e sentir-se sobre a forma como o lixo se comporta Collector, e você vai entender por que você está pensando aqui não é recomendado. a menos que você realmente como o CLR para passar o tempo reorganizando objetos na memória um monte .

Como intensivo é o aplicativo? Eu escrevi um aplicativo que captura 3 placas de som (Managed DirectX, 44,1 kHz, estéreo, 16 bits), em 8KB blocos, e envia 2 dos 3 fluxos para outro computador via TCP / IP. A interface do usuário torna um medidor de nível de áudio e (liso) rolagem título / artista para cada um dos 3 canais. Isto funciona em PCs com XP, 1.8GHz, 512MB, etc. O aplicativo usa cerca de 5% da CPU.

Eu fiquei clara de chamar manualmente métodos GC. Mas eu tive que ajustar algumas coisas que foram um desperdício. I utilizado perfilador da formiga do RedGate para aprimorar em porções de desperdício. Uma ferramenta incrível!

Eu queria usar um pool de matrizes de bytes pré-alocado, mas o conseguiu Assembleia DX aloca buffers de bytes internamente, em seguida, retorna que a App. Descobriu-se que eu não preciso.

Se for absolutamente momento crítico, então você deve usar uma plataforma determinista como C / C ++. Mesmo chamando GC.Collect () irá gerar ciclos de CPU.

A sua questão começa com a sugestão de que você deseja salvar memória, mas se livrar de objetos. Este é um espaço otimização crítica. Você precisa decidir o que você realmente quer, porque o GC é melhor para otimizar essa situação do que um ser humano.

A partir do som dele, parece que você está falando sobre finalização determinística (destruidores em C ++), que não existe em C #. A coisa mais próxima que você vai encontrar em C # é o padrão descartável. Basicamente você implementar o IDisposable interface.

O padrão básico é o seguinte:

public class MyClass: IDisposable
{
    private bool _disposed;

    public void Dispose()
    {
        Dispose( true );
        GC.SuppressFinalize( this );
    }

    protected virtual void Dispose( bool disposing )
    {
        if( _disposed )    
            return;

        if( disposing )
        {
            // Dispose managed resources here
        }

        _disposed = true;
    }
}

Você poderia ter uma quantidade limitada de instâncias de cada tipo em uma piscina, e reutilizar o que já feito com instâncias. O tamanho da piscina vai depender da quantidade de mensagens que você estará processando.

Em vez de criar uma nova instância de um objeto cada vez que você receber uma mensagem, por que você não reutilizar objetos que já foram usados? Desta forma, você não estará lutando contra o coletor de lixo e sua memória heap não vai ter fragmentado. **

Para cada tipo de mensagem, você pode criar um pool para manter as instâncias que não estão em uso. Sempre que você receber uma mensagem de rede, você olha para o tipo de mensagem, puxe uma instância de espera fora da piscina apropriada e aplicar a lógica de negócios. Depois disso, você colocar essa instância da mensagem objeto de volta para a sua piscina.

Você provavelmente irá querer "carga lenta" sua piscina com instâncias para que seus escalas de código facilmente. Portanto, sua classe piscina terá de detectar quando uma instância nula foi puxado e preenchê-lo antes de entregá-lo para fora. Então, quando o chamado puts código-lo de volta na piscina é um exemplo real.

** "pool de objetos é um padrão de uso que permite que objetos para ser reutilizado em vez de alocada e desalocada, que ajuda a prevenir a fragmentação da heap, bem como compactações GC caros."

http://geekswithblogs.net/robp/archive/2008/08/07/speedy-c-part-2-optimizing-memory-allocations---pooling-and.aspx

Em teoria, o GC não deve ser executado se o seu CPU está sob carga pesada ou a menos que ele realmente precisa. Mas se você tem que, você pode querer apenas manter todos os seus objetos na memória, talvez uma instância singleton, e nunca limpá-los, a menos que você está pronto. Isso é provavelmente a única maneira de garantir que os GC é executado.

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