Condividi tramite


Gestione della memoria in Kestrel

Di Tom Dykstra

Questo articolo fornisce indicazioni per la gestione della memoria in Kestrel, inclusa la rimozione automatica dai pool di memoria e l'uso delle metriche del pool di memoria.

Rimozione automatica dal pool di memoria

I pool di memoria usati da Kestrel, IIS e HTTP.sys rimuove automaticamente blocchi di memoria quando l'applicazione è inattiva o sotto carico ridotto. La funzionalità viene eseguita automaticamente e non deve essere abilitata o configurata manualmente.

Questa funzionalità di rimozione automatica riduce l'utilizzo complessivo della memoria e consente alle applicazioni di rimanere reattive in carichi di lavoro diversi. Nelle versioni di .NET precedenti a 10, la memoria allocata dal pool è rimasta riservata anche quando non è in uso.

Utilizzare le metriche del pool di memoria

Il pool di memoria predefinito usato dalle implementazioni del server core ASP.NET include metriche, che possono essere usate per monitorare e analizzare i modelli di utilizzo della memoria. Le metriche sono sotto il nome "Microsoft.AspNetCore.MemoryPool".

Per informazioni sulle metriche e su come usarle, vedere ASP.NET Metriche principali.

Gestire i pool di memoria

Oltre a usare i pool di memoria in modo efficiente rimuovendo blocchi di memoria non necessarie, ASP.NET Core fornisce un'interfaccia IMemoryPoolFactory predefinita e la relativa implementazione predefinita, disponibili tramite l'inserimento delle dipendenze.

L'esempio di codice seguente illustra un semplice servizio in background che usa l'implementazione predefinita della factory del pool di memoria per creare pool di memoria. Questi pool traggono vantaggio dalla funzionalità di rimozione automatica:

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

Per usare una factory del pool di memoria personalizzata, creare una classe che implementa IMemoryPoolFactory e registrarla con l'iniezione delle dipendenze, come illustrato nell'esempio seguente. I pool di memoria creati in questo modo traggono vantaggio anche dalla funzionalità di rimozione automatica:

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 si usa un pool di memoria, tenere presente il parametro del pool MaxBufferSize.