Quản lý bộ nhớ trong Kestrel
Nguồn: Memory management in Kestrel
Bởi Tom Dykstra
Bài viết này cung cấp hướng dẫn quản lý bộ nhớ (memory management) trong Kestrel, bao gồm tính năng tự động loại bỏ (automatic eviction) khỏi memory pool và cách sử dụng memory pool metrics.
Tự động loại bỏ khỏi memory pool
Các memory pool (vùng nhớ dùng chung) được sử dụng bởi Kestrel, IIS, và HTTP.sys sẽ tự động loại bỏ các khối bộ nhớ khi ứng dụng ở trạng thái nhàn rỗi (idle) hoặc tải thấp (low load). Tính năng này chạy tự động và không cần bật hoặc cấu hình thủ công.
Tính năng tự động loại bỏ này giảm thiểu tổng mức sử dụng bộ nhớ và giúp ứng dụng duy trì hiệu suất tốt dưới các mức tải khác nhau. Trong các phiên bản .NET trước phiên bản 10, bộ nhớ được cấp phát bởi pool vẫn được giữ lại dù không còn được sử dụng.
Sử dụng memory pool metrics
Memory pool mặc định được dùng bởi các server implementation của ASP.NET Core có bao gồm metrics (số liệu đo lường), có thể dùng để theo dõi và phân tích các mẫu sử dụng bộ nhớ. Các metrics này được đặt dưới tên "Microsoft.AspNetCore.MemoryPool".
Để biết thêm thông tin về metrics và cách sử dụng chúng, xem ASP.NET Core metrics.
Quản lý memory pool
Bên cạnh việc sử dụng memory pool hiệu quả thông qua loại bỏ các khối bộ nhớ không cần thiết, ASP.NET Core cung cấp interface (giao diện) IMemoryPoolFactory được tích hợp sẵn và triển khai mặc định của nó, có sẵn thông qua dependency injection (tiêm phụ thuộc).
Ví dụ mã sau đây minh họa một background service (dịch vụ nền) đơn giản sử dụng triển khai memory pool factory tích hợp sẵn để tạo các memory pool. Các pool này được hưởng lợi từ tính năng tự động loại bỏ:
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;
}
}
}
}Để sử dụng custom memory pool factory (bộ tạo memory pool tùy chỉnh), tạo một class (lớp) triển khai IMemoryPoolFactory và đăng ký nó với dependency injection, như ví dụ dưới đây. Các memory pool được tạo theo cách này sẽ không được hưởng lợi từ tính năng tự động loại bỏ trừ khi bạn triển khai logic loại bỏ tương tự trong factory tùy chỉnh của mình:
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;
}
}Khi sử dụng memory pool, hãy lưu ý đến giá trị MaxBufferSize của pool.