Compartilhar via


Gerenciamento de memória em Kestrel

Por Tom Dykstra

Este artigo fornece diretrizes para gerenciar a memória em Kestrel, incluindo a expulsão automática de pools de memória e o uso de métricas de pool de memória.

Descarte automático do pool de memória

Os pools de memória usados por Kestrel, IIS e HTTP.sys removem automaticamente blocos de memória quando o aplicativo está ocioso ou sob pouca carga. O recurso é executado automaticamente e não precisa ser habilitado ou configurado manualmente.

Esse recurso de remoção automática reduz o uso geral de memória e ajuda os aplicativos a permanecerem responsivos em cargas de trabalho variadas. Em versões do .NET anteriores a 10, a memória alocada pelo pool permaneceu reservada mesmo quando não estava em uso.

Usar métricas do pool de memória

O pool de memória padrão usado pelas implementações do servidor ASP.NET Core inclui métricas, que podem ser usadas para monitorar e analisar padrões de uso de memória. As métricas estão sob o nome "Microsoft.AspNetCore.MemoryPool".

Para obter informações sobre métricas e como usá-las, consulte as métricas do ASP.NET Core.

Gerenciar reservatórios de memória

Além de usar pools de memória com eficiência removendo blocos de memória desnecessários, o ASP.NET Core fornece uma interface IMemoryPoolFactory interna e sua implementação padrão, que estão disponíveis por meio da injeção de dependência.

O exemplo de código a seguir mostra um serviço em segundo plano simples que usa a implementação integrada de fábrica de pools de memória para criar pools de memória. Esses pools se beneficiam do recurso de remoção automática:

public class MyBackgroundService : BackgroundService
{
    private readonly MemoryPool<byte> _memoryPool;

    public MyBackgroundService(IMemoryPoolFactory<byte> factory)
    {
        _memoryPool = factory.Create();
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                await Task.Delay(20, stoppingToken);
                // do work that needs memory
                // consider checking _memoryPool.MaxBufferSize
                var rented = _memoryPool.Rent(100);
                rented.Dispose();
            }
            catch (OperationCanceledException)
            {
                return;
            }
        }
    }
}

Para usar uma fábrica de pool de memória personalizada, crie uma classe que implemente IMemoryPoolFactory e registre com injeção de dependência, como faz o exemplo a seguir. Os pools de memória criados dessa forma também se beneficiam do recurso de remoção automática:

services.AddSingleton<IMemoryPoolFactory<byte>,
CustomMemoryPoolFactory>();

public class CustomMemoryPoolFactory : IMemoryPoolFactory<byte>
{
    public MemoryPool<byte> Create()
    {
        // Return a custom MemoryPool implementation
        // or the default, as is shown here.
        return MemoryPool<byte>.Shared;
    }
}

Quando você estiver usando um pool de memória, fique atento às características do pool MaxBufferSize.