Em muitos dos serviços em que trabalho, muitos registros estão sendo feitos. Os serviços são serviços WCF (principalmente) que usam a classe .NET EventLogger.
Estou no processo de melhorar o desempenho desses serviços e acho que o log de maneira assíncrona beneficiaria o desempenho.
Não sei o que acontece quando vários threads pedem para registrar, e se isso cria um gargalo, mas mesmo que não ache, ainda acho que não deve interferir no processo real que está sendo executado.
Penso que devo invocar o mesmo método de log que chamo agora, mas usando um novo encadeamento, continuando com o processo real.
Algumas perguntas sobre isso:
Tudo bem?
Existem desvantagens?
Deve ser feito de uma maneira diferente?
Talvez seja tão rápido que nem vale o esforço?
Respostas:
Segmento separado para operação de E / S parece razoável.
Por exemplo, não seria bom registrar quais botões o usuário pressionou no mesmo thread da interface do usuário. Essa interface do usuário será interrompida aleatoriamente e terá um desempenho percebido lento .
A solução é desacoplar o evento de seu processamento.
Aqui estão muitas informações sobre o problema produtor-consumidor e fila de eventos do mundo do desenvolvimento de jogos
Muitas vezes, existe um código como
Essa abordagem levará à contenção de threads. Todos os threads de processamento estarão lutando para obter bloqueio e gravação no mesmo arquivo de uma só vez.
Alguns podem tentar remover bloqueios.
Não é possível prever o resultado se 2 threads entrarem no método ao mesmo tempo.
Então, eventualmente, os desenvolvedores desabilitarão o log ...
É possível consertar?
Sim.
Vamos dizer que temos interface:
Em vez de esperar pelo bloqueio e executar a operação do arquivo de bloqueio sempre que
ILogger
for chamado, adicionaremos o LogMessage à fila de mensagens Penging e voltaremos para coisas mais importantes:Fizemos com este simples registrador assíncrono .
O próximo passo é processar as mensagens recebidas.
Para simplificar, vamos iniciar um novo thread e aguardar eternamente até o aplicativo sair ou o Asynchronous Logger adicionará uma nova mensagem à fila pendente .
Estou passando por uma cadeia de ouvintes personalizados. Você pode querer enviar apenas a estrutura de registro de chamadas (
log4net
, etc ...)Aqui está o restante do código:
Ponto de entrada:
fonte
Os principais fatores a serem considerados são sua necessidade de confiabilidade nos arquivos de log e a necessidade de desempenho. Consulte desvantagens. Eu acho que essa é uma ótima estratégia para situações de alto desempenho.
Tudo bem - sim
Existem desvantagens - sim - dependendo da criticidade do seu log e da sua implementação, qualquer um dos seguintes itens pode ocorrer - logs gravados fora de sequência, ações do encadeamento de logs não concluídas antes da conclusão das ações do evento. (Imagine um cenário em que você registra "começando a se conectar ao banco de dados" e depois trava o servidor, o evento de log nunca pode ser gravado, mesmo que o evento tenha ocorrido (!))
Deve ser feito de uma maneira diferente - você pode querer olhar para o modelo Disruptor, pois é quase ideal para este cenário
Talvez seja tão rápido que nem sequer valha o esforço - discordo. Se a sua é uma lógica de "aplicativo", e a única coisa que você faz é gravar logs da atividade - então você terá ordens de magnitude mais baixa latência descarregando o log. Se, no entanto, você confiar em uma chamada SQL de 5 segundos para retornar antes de registrar 1-2 instruções, os benefícios serão variados.
fonte
Eu acho que o log é geralmente uma operação síncrona por natureza. Você deseja registrar as coisas se elas acontecerem ou não, dependendo da sua lógica. Portanto, para registrar alguma coisa, essa coisa precisa ser avaliada primeiro.
Dito isto, você pode melhorar o desempenho do seu aplicativo armazenando em cache os logs e, em seguida, criando um encadeamento e salvando-os em arquivos quando tiver uma operação vinculada à CPU.
Você precisa identificar seus pontos de verificação de maneira inteligente, para não perder suas informações importantes de registro durante esse período de cache.
Se você deseja obter um aumento de desempenho em seus encadeamentos, precisa equilibrar as operações de E / S e as operações da CPU.
Se você criar 10 threads que executam IO, não receberá um aumento de desempenho.
fonte
O log de forma assíncrona é o único caminho a percorrer se você precisar de baixa latência nos threads de log. A maneira como isso é feito para obter o desempenho máximo é através do padrão de disruptor para comunicação de encadeamento sem bloqueios e sem lixo. Agora, se você deseja permitir que vários encadeamentos registrem simultaneamente no mesmo arquivo, você deve sincronizar as chamadas de log e pagar o preço em contenção de bloqueio OU usar um multiplexador sem bloqueio. Por exemplo, o CoralQueue fornece uma fila simples de multiplexação, conforme descrito abaixo:
Você pode dar uma olhada no CoralLog, que usa essas estratégias para o log assíncrono.
Disclaimer: Eu sou um dos desenvolvedores do CoralQueue e CoralLog.
fonte