Udostępnij przez


Zarządzanie pamięcią w programie Kestrel

Autor: Tom Dykstra

Ten artykuł zawiera wskazówki dotyczące zarządzania pamięcią w Kestrel, w tym automatycznej eksmisji z pul pamięci i używania metryk pul pamięci.

Automatyczna eksmisja z puli pamięci

Pule pamięci używane przez Kestrel, IIS i HTTP.sys automatycznie usuwają bloki pamięci, gdy aplikacja jest bezczynna lub pod niskim obciążeniem. Funkcja jest uruchamiana automatycznie i nie musi być włączona ani skonfigurowana ręcznie.

Ta funkcja automatycznego usuwania zmniejsza ogólne użycie pamięci i pomaga aplikacjom pozostać responsywnymi przy różnych obciążeniach. W wersjach platformy .NET wcześniejszych niż 10 pamięć przydzielona przez pulę pozostawała zarezerwowana nawet wtedy, gdy nie była używana.

Korzystanie z metryk puli pamięci

Domyślna pula pamięci używana przez implementacje serwera ASP.NET Core obejmuje metryki, których można użyć do monitorowania i analizowania wzorców użycia pamięci. Metryki są pod nazwą "Microsoft.AspNetCore.MemoryPool".

Aby uzyskać informacje o metrykach i sposobie ich używania, zobacz ASP.NET Metryki podstawowe.

Zarządzanie pulami pamięci

Oprócz wydajnego używania pul pamięci przez eksmitowanie niepotrzebnych bloków pamięci, ASP.NET Core udostępnia wbudowany interfejs IMemoryPoolFactory i jego domyślną implementację, która jest dostępna za pośrednictwem wstrzykiwania zależności.

Poniższy przykład kodu przedstawia prostą usługę działającą w tle, która używa wbudowanej implementacji fabryki puli pamięci do tworzenia pul pamięci. Te pule korzystają z funkcji automatycznego eksmitowania:

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;
            }
        }
    }
}

Aby użyć niestandardowej fabryki puli pamięci, utwórz klasę, która implementuje IMemoryPoolFactory i zarejestruj ją za pomocą iniekcji zależności, jak w poniższym przykładzie. Pule pamięci utworzone w ten sposób korzystają również z funkcji automatycznego wysiedlenia.

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;
    }
}

Jeśli używasz puli pamięci, należy pamiętać o puli MaxBufferSize.