Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Od Günther Foidl, Steve Gordon a Samson Amaugo
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.
Varování
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi tohoto článku najdete v verzi .NET 9.
Microsoft.Extensions.ObjectPool je součástí ASP.NET Core infrastruktury, která podporuje zachování skupiny objektů v paměti pro opětovné využití místo uvolnění objektů z paměti. Všechny statické a instanční metody v Microsoft.Extensions.ObjectPool jsou bezpečné pro přístup z více vláken.
Aplikace můžou chtít fond objektů používat, pokud jsou spravované objekty:
- Je nákladné přidělit nebo inicializovat.
- Představuje omezený prostředek.
- Používá se předvídatelně a často.
Například architektura ASP.NET Core používá fond objektů na některých místech k opakovanému použití StringBuilder instancí.
StringBuilder přiděluje a spravuje vlastní vyrovnávací paměť pro ukládání charakterových dat. ASP.NET Core pravidelně používá StringBuilder k implementaci funkcí a jejich opakované použití poskytuje výhodu výkonu.
Poolování objektů ne vždy zlepší výkon.
- Pokud nejsou náklady na inicializaci objektu vysoké, obvykle trvá déle získat objekt ze zásobníku.
- Objekty spravované fondem nejsou uvolněny, dokud není fond uvolněn.
Sdružování objektů používejte pouze po shromáždění dat o výkonu pomocí realistických scénářů pro vaši aplikaci nebo knihovnu.
POZNÁMKA: ObjectPool neumisťuje limit počtu objektů, které přiděluje, umístí limit počtu objektů, které si zachová.
Koncepty fondu objektů
Když se použije DefaultObjectPoolProvider a T implementuje IDisposable:
- Položky, které se nevrátí do rezervního zásobníku, budou odstraněny.
- Když se fond odstraní pomocí DI, všechny položky ve fondu se vyřadí.
POZNÁMKA: Po likvidaci fondu:
- Volání
Getvyvolá chybuObjectDisposedException. - Volání
Returnzlikviduje danou položku.
Důležité ObjectPool typy a rozhraní:
- ObjectPool<T> : Základní abstrakce fondu objektů. Slouží k získání a vrácení objektů.
- PooledObjectPolicy<T> : Implementujte to k přizpůsobení způsobu vytvoření objektu a jeho resetování při vrácení do fondu. Ten lze předat přímo do přímo vytvořeného fondu objektů.
- IResettable : Automaticky resetuje objekt při vrácení do fondu objektů.
Fond objektů lze v aplikaci použít několika způsoby:
- Vytvoření instance fondu
- Registrace fondu jako instance v Dependency Injection (DI)
- Registrace
ObjectPoolProvider<>v DI a jeho používání jako továrny.
Jak používat ObjectPool
Zavolejte Get pro získání objektu a Return k vrácení objektu. Není nutné vracet všechny objekty. Pokud se objekt nevrátí, bude odstraněn z paměti.
Ukázka objektového poolu
Následující kód:
- Přidá
ObjectPoolProviderdo kontejneru injekce závislostí (DI). - Implementuje rozhraní
IResettablek automatickému vymazání obsahu vyrovnávací paměti při vrácení do fondu objektů.
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using System.Security.Cryptography;
var builder = WebApplication.CreateBuilder(args);
builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
builder.Services.TryAddSingleton<ObjectPool<ReusableBuffer>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new DefaultPooledObjectPolicy<ReusableBuffer>();
return provider.Create(policy);
});
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
// return the SHA256 hash of a word
// https://localhost:7214/hash/SamsonAmaugo
app.MapGet("/hash/{name}", (string name, ObjectPool<ReusableBuffer> bufferPool) =>
{
var buffer = bufferPool.Get();
try
{
// Set the buffer data to the ASCII values of a word
for (var i = 0; i < name.Length; i++)
{
buffer.Data[i] = (byte)name[i];
}
Span<byte> hash = stackalloc byte[32];
SHA256.HashData(buffer.Data.AsSpan(0, name.Length), hash);
return "Hash: " + Convert.ToHexString(hash);
}
finally
{
// Data is automatically reset because this type implemented IResettable
bufferPool.Return(buffer);
}
});
app.Run();
public class ReusableBuffer : IResettable
{
public byte[] Data { get; } = new byte[1024 * 1024]; // 1 MB
public bool TryReset()
{
Array.Clear(Data);
return true;
}
}
POZNÁMKA: Pokud typ T fondu neimplementuje IResettable, lze vlastní PooledObjectPolicy<T> použít pro resetování stavu objektů před jejich vrácením do fondu.
Microsoft.Extensions.ObjectPool je součástí ASP.NET Core infrastruktury, která podporuje zachování skupiny objektů v paměti pro opětovné využití místo uvolnění objektů z paměti. Všechny statické a instanční metody v Microsoft.Extensions.ObjectPool jsou bezpečné pro přístup z více vláken.
Aplikace můžou chtít fond objektů používat, pokud jsou spravované objekty:
- Je nákladné přidělit nebo inicializovat.
- Představuje omezený prostředek.
- Používá se předvídatelně a často.
Například architektura ASP.NET Core používá fond objektů na některých místech k opakovanému použití StringBuilder instancí.
StringBuilder přiděluje a spravuje vlastní vyrovnávací paměť pro ukládání charakterových dat. ASP.NET Core pravidelně používá StringBuilder k implementaci funkcí a jejich opakované použití poskytuje výhodu výkonu.
Poolování objektů ne vždy zlepší výkon.
- Pokud nejsou náklady na inicializaci objektu vysoké, obvykle trvá déle získat objekt ze zásobníku.
- Objekty spravované fondem nejsou uvolněny, dokud není fond uvolněn.
Sdružování objektů používejte pouze po shromáždění dat o výkonu pomocí realistických scénářů pro vaši aplikaci nebo knihovnu.
POZNÁMKA: ObjectPool neumisťuje limit počtu objektů, které přiděluje, umístí limit počtu objektů, které si zachová.
Koncepty
Když se použije DefaultObjectPoolProvider a T implementuje IDisposable:
- Položky, které se nevrátí do rezervního zásobníku, budou odstraněny.
- Když se fond odstraní pomocí DI, všechny položky ve fondu se vyřadí.
POZNÁMKA: Po likvidaci fondu:
- Volání
Getvyvolá chybuObjectDisposedException. - Volání
Returnzlikviduje danou položku.
Důležité ObjectPool typy a rozhraní:
- ObjectPool<T> : Základní abstrakce fondu objektů. Slouží k získání a vrácení objektů.
- PooledObjectPolicy<T> : Implementujte to pro přizpůsobení způsobu vytvoření objektu a jeho resetování při jeho vrácení do fondu. To lze předat do fondu objektů, který je přímo konstruovaný, nebo
- Create : Funguje jako továrna pro vytváření fondů objektů.
- IResettable: Automaticky obnoví objekt při vrácení do fondu objektů.
Fond objektů lze v aplikaci použít několika způsoby:
- Vytvoření instance fondu
- Registrace fondu jako instance v Dependency Injection (DI)
- Registrace
ObjectPoolProvider<>v DI a jeho používání jako továrny.
Jak používat ObjectPool
Zavolejte Get pro získání objektu a Return k vrácení objektu. Není nutné, abyste vraceli všechny objekty. Pokud objekt nevrátíte, bude zpracován jako neplatný.
Ukázka objektového poolu
Následující kód:
- Přidá
ObjectPoolProviderdo kontejneru injekce závislostí (DI). - Přidá a nakonfiguruje
ObjectPool<StringBuilder>do kontejneru DI. - Přidá
BirthdayMiddleware.
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using ObjectPoolSample;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
builder.Services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new Microsoft.Extensions.ObjectPool.StringBuilderPooledObjectPolicy();
return provider.Create(policy);
});
builder.Services.AddWebEncoders();
var app = builder.Build();
// Test using /?firstname=Steve&lastName=Gordon&day=28&month=9
app.UseMiddleware<BirthdayMiddleware>();
app.MapGet("/", () => "Hello World!");
app.Run();
Následující kód implementuje: BirthdayMiddleware
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.Extensions.ObjectPool;
namespace ObjectPoolSample;
public class BirthdayMiddleware
{
private readonly RequestDelegate _next;
public BirthdayMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context,
ObjectPool<StringBuilder> builderPool)
{
if (context.Request.Query.TryGetValue("firstName", out var firstName) &&
context.Request.Query.TryGetValue("lastName", out var lastName) &&
context.Request.Query.TryGetValue("month", out var month) &&
context.Request.Query.TryGetValue("day", out var day) &&
int.TryParse(month, out var monthOfYear) &&
int.TryParse(day, out var dayOfMonth))
{
var now = DateTime.UtcNow; // Ignoring timezones.
// Request a StringBuilder from the pool.
var stringBuilder = builderPool.Get();
try
{
stringBuilder.Append("Hi ")
.Append(firstName).Append(" ").Append(lastName).Append(". ");
var encoder = context.RequestServices.GetRequiredService<HtmlEncoder>();
if (now.Day == dayOfMonth && now.Month == monthOfYear)
{
stringBuilder.Append("Happy birthday!!!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
else
{
var thisYearsBirthday = new DateTime(now.Year, monthOfYear,
dayOfMonth);
int daysUntilBirthday = thisYearsBirthday > now
? (thisYearsBirthday - now).Days
: (thisYearsBirthday.AddYears(1) - now).Days;
stringBuilder.Append("There are ")
.Append(daysUntilBirthday).Append(" days until your birthday!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
}
finally // Ensure this runs even if the main code throws.
{
// Return the StringBuilder to the pool.
builderPool.Return(stringBuilder);
}
return;
}
await _next(context);
}
}
Microsoft.Extensions.ObjectPool je součástí ASP.NET Core infrastruktury, která podporuje zachování skupiny objektů v paměti pro opětovné využití místo uvolnění objektů z paměti.
Fond objektů můžete chtít použít, pokud jsou spravované objekty:
- Je nákladné přidělit nebo inicializovat.
- Představuje nějaký omezený zdroj.
- Používá se předvídatelně a často.
Například architektura ASP.NET Core používá fond objektů na některých místech k opakovanému použití StringBuilder instancí.
StringBuilder přiděluje a spravuje vlastní vyrovnávací paměť pro ukládání charakterových dat. ASP.NET Core pravidelně používá StringBuilder k implementaci funkcí a jejich opakované použití poskytuje výhodu výkonu.
Poolování objektů ne vždy zlepší výkon.
- Pokud nejsou náklady na inicializaci objektu vysoké, obvykle trvá déle získat objekt ze zásobníku.
- Objekty spravované fondem nejsou uvolněny, dokud není fond uvolněn.
Sdružování objektů používejte pouze po shromáždění dat o výkonu pomocí realistických scénářů pro vaši aplikaci nebo knihovnu.
UPOZORNĚNÍ: ObjectPool neimplementuje IDisposable. Nedoporučujeme jej používat s typy, které potřebují likvidaci.
ObjectPool v systému ASP.NET Core 3.0 nebo novějším podporuje IDisposable.
POZNÁMKA: ObjectPool neumisťuje limit počtu objektů, které přidělí, umístí limit počtu objektů, které si zachová.
Koncepty
ObjectPool<T> - abstrakce základního fondu objektů. Slouží k získání a vrácení objektů.
PooledObjectPolicy<T> – Implementujte tuto možnost, abyste přizpůsobili způsob vytvoření objektu a jeho resetování při navrácení do poolu. Lze jej předat do fondu objektů, který jste vytvořili přímo.... NEBO
Create funguje jako továrna pro vytváření fondů objektů.
Fond objektů lze v aplikaci použít několika způsoby:
- Vytvoření instance fondu
- Registrace fondu jako instance v Dependency Injection (DI)
- Registrace
ObjectPoolProvider<>v DI a jeho používání jako továrny.
Jak používat ObjectPool
Zavolejte Get pro získání objektu a Return k vrácení objektu. Není nutné, abyste vraceli všechny objekty. Pokud objekt nevrátíte, bude zpracován jako neplatný.
Ukázka objektového poolu
Následující kód:
- Přidá
ObjectPoolProviderdo kontejneru injekce závislostí (DI). - Přidá a nakonfiguruje
ObjectPool<StringBuilder>do kontejneru DI. - Přidá
BirthdayMiddleware.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
{
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
var policy = new StringBuilderPooledObjectPolicy();
return provider.Create(policy);
});
services.AddWebEncoders();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Test using /?firstname=Steve&lastName=Gordon&day=28&month=9
app.UseMiddleware<BirthdayMiddleware>();
}
}
Následující kód implementuje: BirthdayMiddleware
public class BirthdayMiddleware
{
private readonly RequestDelegate _next;
public BirthdayMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context,
ObjectPool<StringBuilder> builderPool)
{
if (context.Request.Query.TryGetValue("firstName", out var firstName) &&
context.Request.Query.TryGetValue("lastName", out var lastName) &&
context.Request.Query.TryGetValue("month", out var month) &&
context.Request.Query.TryGetValue("day", out var day) &&
int.TryParse(month, out var monthOfYear) &&
int.TryParse(day, out var dayOfMonth))
{
var now = DateTime.UtcNow; // Ignoring timezones.
// Request a StringBuilder from the pool.
var stringBuilder = builderPool.Get();
try
{
stringBuilder.Append("Hi ")
.Append(firstName).Append(" ").Append(lastName).Append(". ");
var encoder = context.RequestServices.GetRequiredService<HtmlEncoder>();
if (now.Day == dayOfMonth && now.Month == monthOfYear)
{
stringBuilder.Append("Happy birthday!!!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
else
{
var thisYearsBirthday = new DateTime(now.Year, monthOfYear,
dayOfMonth);
int daysUntilBirthday = thisYearsBirthday > now
? (thisYearsBirthday - now).Days
: (thisYearsBirthday.AddYears(1) - now).Days;
stringBuilder.Append("There are ")
.Append(daysUntilBirthday).Append(" days until your birthday!");
var html = encoder.Encode(stringBuilder.ToString());
await context.Response.WriteAsync(html);
}
}
finally // Ensure this runs even if the main code throws.
{
// Return the StringBuilder to the pool.
builderPool.Return(stringBuilder);
}
return;
}
await _next(context);
}
}