Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use .NET Core object Pool

2025-04-11 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces how to use the NET Core object pool, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.

In principle, all reference type objects can be provided through object pooling, but whether it is worth using in specific applications needs to be weighed. Although object pooling can avoid GC through object reuse, the objects it stores consume memory, and it is not worth using object pooling if the frequency of object reuse is very small. If a small object has a short life cycle and can ensure that GC can recycle it in generation 0, such an object is not suitable for being placed in the object pool, because the performance of generation 0 GC is actually very high. In addition, after the object is released into the object pool, it may be extracted by other threads, and if the release time is not right, it may cause multiple threads to operate on the same object at the same time. In short, we have to consider whether the current scene is suitable for object pooling before using it, and strictly follow the principles of "borrow and return" and "return only if you don't use it".

I. pooled collection

We know that an array is used inside a List object to hold list elements. The array is of fixed length, so List has a maximum capacity (reflected in its Capacity attribute). When the number of list elements exceeds the capacity of the array, the list object must be expanded, that is, a new array is created and existing elements are copied into it. The more elements you currently have, the more copy operations you need to perform, and the greater the impact on performance. If we create a List object and keep adding objects to it, it may lead to multiple expansion, so if we can predict the number of elements, we should specify an appropriate capacity when creating the List object. But in many cases, the number of list elements is dynamic, and we can use object pooling to solve this problem.

Next, we will use a simple example to demonstrate how to provide a List object using object pooling, with the element type Foobar shown below. In order to explicitly control the creation and return of list objects, we customized the following FoobarListPolicy that represents the pooled object policy. Through the introduction of the default implementation of object pooling in the Design article, we know that inheriting PooledObjectPolicy types directly has better performance advantages than implementing IPooledObjectPolicy interfaces.

Public class FoobarListPolicy: PooledObjectPolicy {private readonly int _ initCapacity; private readonly int _ maxCapacity; public FoobarListPolicy (int initCapacity, int maxCapacity) {_ initCapacity = initCapacity; _ maxCapacity = maxCapacity;} public override List Create () = > new List (_ initCapacity); public override bool Return (List obj) {if (obj.Capacity new Foobar (it, it)); json = JsonConvert.SerializeObject (list) } finally {objectPool.Return (list);} II. Pooled StringBuilder

We know that if operations for string concatenation are frequently involved, StringBuilder should be used for better performance. In fact, StringBuilder objects themselves have expansion problems similar to list objects, so the best way is to reuse them by object pooling. The object pooling framework provides native support for pooling StringBuilder objects, so let's demonstrate this with a simple example.

Class Program {static void Main () {var objectPool = new ServiceCollection () .AddSingleton () .BuildServiceProvider () .GetRequiredService () .CreateStringBuilderPool (1024, 1024,1024); var builder = objectPool.Get (); try {for (int index = 0; index)

< 100; index++) { builder.Append(index); } Console.WriteLine(builder); } finally { objectPool.Return(builder); } }} 如上面的代码片段所示,我们直接可以调用ObjectPoolProvider的CreateStringBuilderPool扩展方法就可以得到针对StringBuilder的对象池对象(类型为ObjectPool)。我们上面演示实例一样,我们指定的也是StringBuilder对象的初始和最大容量。池化StringBuilder对象的核心体现在对应的策略类型上,即如下这个StringBuilderPooledObjectPolicy类型。 public class StringBuilderPooledObjectPolicy : PooledObjectPolicy{ public int InitialCapacity { get; set; } = 100; public int MaximumRetainedCapacity { get; set; } = 4 * 1024; public override StringBuilder Create()=>

New StringBuilder (InitialCapacity); public override bool Return (StringBuilder obj) {if (obj.Capacity > MaximumRetainedCapacity) {return false;} obj.Clear (); return true;}}

You can see that its definition is the same as the FoobarListPolicy type we defined earlier. By default, the initialization and maximum capacity of pooled StringBuilder objects are 100 and 5096, respectively. The definitions of the two CreateStringBuilderPool extension methods that ObjectPoolProvider uses to create ObjectPool objects are shown below.

Public static class ObjectPoolProviderExtensions {public static ObjectPool CreateStringBuilderPool (this ObjectPoolProvider provider) = > provider.Create (new StringBuilderPooledObjectPolicy ()); public static ObjectPool CreateStringBuilderPool (this ObjectPoolProvider provider, int initialCapacity, int maximumRetainedCapacity) {var policy = new StringBuilderPooledObjectPolicy () {InitialCapacity = initialCapacity, MaximumRetainedCapacity = maximumRetainedCapacity,}; return provider.Create (policy);}} III, ArrayPool

The next introduction has nothing to do with the previous content, but it also belongs to our common object pool usage scenario. We use a lot of collections when programming, and many collection types (such as linked list-based collections) use an array as internal storage, so there will be the expansion problem mentioned earlier. If the array is large, it will also put pressure on GC. We have previously used the pooled collection solution to solve this problem, but there is another solution to this problem.

In many cases, when we need to create an object, we actually need a sequence of contiguous objects of definite length. Suppose we pool array objects, and when we need a fixed-length sequence of objects, extract an available array from the pool that is longer than the desired length, and intercept the available contiguous fragments (usually from scratch). After using it, we can just return the array objects to the object pool without performing any release operations. This array-based object pool usage can be implemented using ArrayPool.

Public abstract class ArrayPool {public abstract T [] Rent (int minimumLength); public abstract void Return (T [] array, bool clearArray); public static ArrayPool Create (); public static ArrayPool Create (int maxArrayLength, int maxArraysPerBucket); public static ArrayPool Shared {get;}}

As shown in the code snippet above, the abstract type ArrayPool also provides a way to complete the two basic operations of the object pool, where the Rent method "lends" an array of no less than (or equal to) the specified length from the object pool, and the array is eventually released to the object pool through the Return method. The clearArray parameter of the Return method indicates whether to empty the array before returning it, depending on how we use the array. If we need to overwrite the original content every time, there is no need to do this extra operation.

We can create an ArrayPool object through the static method Create. Pooled arrays are not directly stored in the object pool, and multiple arrays of similar length are encapsulated into a Bucket. The advantage is that when executing the Rent method, you can quickly find the best matching array according to the specified length (larger than and close to the specified length). The object pool stores a set of Bucket objects, and the longer the array is allowed, the more buckets there are. The Create method can specify not only the maximum allowed length of the array, but also the capacity of each bucket. In addition to calling the static Create method to create an exclusive ArrayPool object, we can use the static property Shared to return an application-wide shared ArrayPool object. ArrayPool is very convenient to use, and the following code snippet shows an example of reading a file.

Class Program {static async Task Main () {using var fs = new FileStream ("test.txt", FileMode.Open); var length = (int) fs.Length; var bytes = ArrayPool.Shared.Rent (length); try {await fs.ReadAsync (bytes, 0, length); Console.WriteLine (Encoding.Default.GetString (bytes, 0, length)) } finally {ArrayPool.Shared.Return (bytes);} IV. MemoryPool

An array is an expression of a piece of contiguous memory used to store similar objects in a managed heap, while another type, Memory, is more widely used because it can represent not only a continuous Managed memory, but also a contiguous Native memory, or even thread stack memory. MemoryPool with the following definition represents a pool of objects of type Memory.

Public abstract class MemoryPool: IDisposable {public abstract int MaxBufferSize {get;} public static MemoryPool Shared {get;} public void Dispose (); protected abstract void Dispose (bool disposing); public abstract IMemoryOwner Rent (int minBufferSize =-1);} public interface IMemoryOwner: IDisposable {Memory Memory {get;}}

MemoryPool and ArrayPool have similar definitions, such as getting the MemoryPool object currently shared globally through the static property Shared, and lending a Memory object of no less than the specified size from the object pool through the Rent method. The difference is that the Rent method of MemoryPool does not return a Memory object directly, but an IMemoryOwner object that encapsulates it. MemoryPool also does not define a Reurn method to release the Memory object, which is done through the Dispose method of the IMemoryOwner object. If you use MemoryPool, the previous demonstration for ArrayPool can be rewritten as follows.

Class Program {static async Task Main () {using var fs = new FileStream ("test.txt", FileMode.Open); var length = (int) fs.Length; using (var memoryOwner = MemoryPool.Shared.Rent (length)) {await fs.ReadAsync (memoryOwner.Memory); Console.WriteLine (Encoding.Default.GetString (memoryOwner.Memory.Span.Slice (0) } Thank you for reading this article carefully. I hope the article "how to use the .NET Core object Pool" shared by the editor will be helpful to you. At the same time, I also hope that you will support and follow the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report