Reduzindo drasticamente o uso de memória com o Log
Tags: dotnet, aspdotnet, csharp, dotnetcore
Published: 2023-07-10 15:58:34

O registro de logs desempenha um papel fundamental no monitoramento e depuração de aplicações dotnet. No entanto, o uso inadequado do log pode impactar negativamente o desempenho das aplicações.

É comum espalhar chamadas para a escrita de logs em todo o código, frequentemente utilizando interpolação de strings para facilitar a sua criação. No entanto, raramente avaliamos se essa abordagem é a mais eficiente.

## Analisando o benchmark do método LogInformation
Para ilustrar o impacto da alocação de memória, examinaremos o benchmark do método LogInformation, existente no Logger comum que é aquele que utiliza os métodos de extensão da interface ILogger. O código de teste é simples e comumente encontrado em aplicações em produção.

```csharp
[Benchmark(Baseline = true)]
public void LogInformationComStringInterpolation()
{
    _logger.LogInformation($"Pedido {_pedido} gerado com sucesso!");
}
```
## Benchmark com interpolação de strings
Ao executar o benchmark com interpolação de strings, observamos uma alocação de 80 bytes. Parece ser uma quantidade insignificante, mas quando repetimos essa chamada em um loop de 100.000 iterações, como em uma importação de arquivos, a alocação totaliza 7,63MB. É uma quantidade considerável de memória utilizada apenas para escrever logs.

![benchLogInformation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukre6k5xgdv8qtmaa35c.png)

![benchLogInformation100k](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gltv83qvvtbq5158cez9.png)

## Alocação de memória mesmo com LogLevel definido como Warning
Surpreendentemente, mesmo definindo o LogLevel como Warning, a alocação de memória continua a mesma (7,63MB). Isso pode ser alarmante, especialmente considerando a presença de outras chamadas de log, como LogDebug, LogTrace e LogInformation, espalhadas pelo código.

![benchLogInformation100kWarning](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dhi32wfbbiop3ujqxo0.png)

## Reduzindo a alocação de memória com "String Template"
Uma abordagem para reduzir a alocação de memória é utilizar o formato de "String Template" em vez de interpolação de strings. Ao aplicar essa alteração, a alocação de memória é reduzida para 56 bytes em um único teste. Realizando o mesmo teste com 100.000 iterações, a alocação de memória continua menor em comparação à interpolação de strings.

![benchLogInformationStringTemplate](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cir1w8bi6ih0j4c3488g.png)

![benchLogInformationStringTemplate100K](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0qkcyk6srm8ci7a2zv64.png)

## Evitando alocação de memória com verificação do LogLevel
Podemos evitar a alocação de memória ao verificar se o LogLevel está habilitado antes de realizar a chamada para o log. Essa abordagem resolve o problema quando desejamos aumentar o LogLevel em produção. No entanto, ainda ocorre alocação de memória quando precisamos executar o LogInformation em produção. Embora o uso de "String Template" possa reduzir o consumo, não é possível eliminá-lo completamente.

![benchLogInformationComIf100K](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pu7khsayqxq9569424cd.png)

```csharp
[Benchmark(Baseline = true)]
public void LogInformationComStringInterpolation()
{
    for (int i = 0; i < 100_000; i++)
    {
        if (_logger.IsEnabled(LogLevel.Information))
        {
            _logger.LogInformation($"Pedido {_pedido} gerado com sucesso!");
        }
    }
}

[Benchmark]
public void LogInformationComStringTemplate()
{
    for (int i = 0; i < 100_000; i++)
    {
        if (_logger.IsEnabled(LogLevel.Information))
        {
            _logger.LogInformation("Pedido {Pedido} gerado com sucesso!", _pedido);
        }
    }
}
```
## Conclusão e próximos passos
É essencial compreender o motivo das alocações de memória no Logger e explorar abordagens para evitá-las. No próximo artigo, explicaremos os motivos das alocações e o método para diminuir as alocações de memória ao utilizar logs.

O teste a seguir apresenta uma otimização, na qual nenhuma alocação de memória é necessária durante a escrita dos logs.

![benchLogInformationCom100KOtimizado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukbugj57369czqr6yw92.png)

Mantenha-se atualizado e não perca a continuação deste conteúdo!