ASP.NET Core中的对象池化技术详解

写在前面

Microsoft.Extensions.ObjectPool 是 ASP.NET Core 基础结构的一部分,当对象的初始化成本较高,并且可能被频繁使用时,才适合采用对象池技术;被ObjectPool管理的对象不会进入垃圾回收,使用时通过由实例对象实现的Get()方法,从对象池中借出对象,用完之后调用Return(T obj)方法,将对象还回去。也可以在Return(T obj)方法中设置判断条件,仅允许特定的对象进入对象池。

通过NuGet 获取 Microsoft.Extensions.ObjectPool 类库

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using System.Security.Cryptography;
using System.Text;
  
var builder = WebApplication.CreateBuilder(args);
  
// DefaultPooledObjectPolicy: 默认的策略,继承抽象类PooledObjectPolicy
builder.Services.TryAddSingleton();
  
builder.Services.TryAddSingleton>(serviceProvider =>
{
    var provider = serviceProvider.GetRequiredService();
    var policy = new DefaultPooledObjectPolicy();
    return provider.Create(policy);
});
  
builder.Services.TryAddSingleton>(serviceProvider => {
    var provider = serviceProvider.GetRequiredService();
    var policy = new PersonPoolPolicy();
    return provider.Create(policy);
});
  
builder.Services.TryAddSingleton>(serviceProvider =>
{
    var provider = serviceProvider.GetRequiredService();
    var policy = new StringBuilderPooledObjectPolicy();
    return provider.Create(policy);
});
  
var app = builder.Build();
  
// config middleware
app.UseMiddleware();
  
app.MapGet("/", () => "Hello rjcql!");
  
// return the SHA256 hash of a word
http://localhost:5128/hash/xxxx
app.MapGet("/hash/{word}", (string word, ObjectPool bufferPool) =>
{
  
    var buffer = bufferPool.Get();
    try
    {
        // Set the buffer data to the ASCII values of a word
        for (var i = 0; i  hash = stackalloc byte[32];
        SHA256.HashData(buffer.Data.AsSpan(0, word.Length), hash);
        return "Hash: " + Convert.ToHexString(hash);
    }
    finally
    {
        // Data is automatically reset because this type implemented IResettable
        bufferPool.Return(buffer);
    }
});
  
app.MapGet("/create/{name}", (string name, ObjectPool personPool) =>
{
    var person = personPool.Get();
    try
    {
        person.Id = Guid.NewGuid().ToString("N");
        var lastName = person.Name; // 这个是上一个对象的值
        person.Name = name;
        return $"{person.Id}:{person.Name}, {lastName}";
    }
    finally
    {
        // 根据条件回收
        personPool.Return(person);
    }
});
  
app.Run();
  
public class ReusableBuffer : IResettable
{
    public byte[] Data { get; } = new byte[1024 * 1024]; // 1 MB
  
    public bool TryReset()
    {
        Array.Clear(Data);
        return true;
    }
}
  
public class Person
{
    public string Id { get; set; }
  
    public string Name { get; set; }
}
  
public class PersonPoolPolicy : PooledObjectPolicy
{
    public override Person Create()
    {
        return new Person { Id = "", Name = "rjcql" };
    }
  
    public override bool Return(Person p)
    {
        if (p.Name != "rjcql")
        {
            // 不允许其他名称的对象放入对象池
            return false;
        }
        return true;
    }
}
  
/// <summary>
/// 创建中间件
/// </summary>
public class BirthdayMiddleware
{
    private readonly RequestDelegate _next;
  
    public BirthdayMiddleware(RequestDelegate next)
    {
        _next = next;
    }
  
    public async Task InvokeAsync(HttpContext context, ObjectPool builderPool)
    {
        var stringBuilder = builderPool.Get();
        try
        {
            stringBuilder.Append("Hi");
            // 在中间干点啥别的
            // await context.Response.WriteAsync(stringBuilder.ToString());
            await _next.Invoke(context);
        }
        finally // 即使出错也要保证归还对象
        {
            builderPool.Return(stringBuilder);
        }
    }
}

调用示例

因为设置了回收条件,所以只有名字为rjcql的对象才会被回收,所以每次调用都先把rjcql对象取出。

到此这篇关于ASP.NET Core中的对象池化技术详解的文章就介绍到这了,更多相关.NET Core对象池内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/code/asp-net/9407.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部