对资源的可复用是提升应用程序性能的一个非常重要的手段,比如本篇要分享的 ArrayPool 和 MemoryPool,它们就有效的减少了内存使用和对GC的压力,从而提升应用程序性能。

什么是 ArrayPool

System.Buffers 命名空间下提供了一个可对 array 进行复用的高性能池化类 ArrayPool<T>,在经常使用 array 的场景下可使用 ArrayPool<T> 来减少内存占用,它是一个抽象类,如下代码所示:


public abstract class ArrayPool<T>
{
}

可以想象一下你的业务场景中需要多次实例化 array,这么做有什么后果呢? 很显然每一次 new array 都会在托管堆上分配,同时当 array 不再使用时还需要 GC 去释放,而 ArrayPool<T> 就是为了解决此事而生的,它在池中动态维护若干个 array 对象,当你需要 new array 的时候只需从池中获取即可。

使用 ArrayPool<T>

可以通过下面三种方式来使用 ArrayPool<T>

  • 通过 ArrayPool<T>.Shared 属性来获取 ArrayPool<T> 实例。

  • 通过 ArrayPool<T>.Create() 来生成 ArrayPool<T> 实例。

  • 通过继承 ArrayPool<T> 来生成一个自定义子类。

下面的代码展示了如何从 ArrayPool 中获取一个 size >= 10 的 array 数组。


var shared = ArrayPool<int>.Shared;
var rentedArray = shared.Rent(10);

上面的代码一定要注意,虽然只租用了 10 个 size,但底层会返回 2的倍数 的size , 也就是图中的 2* 8 = 16。

当什么时候不需要 rentedArray 了,记得再将它归还到 ArrayPool 中,如下代码所示。


shared.Return(rentedArray);

下面是仅供参考的完整代码。


static void Main(string[] args)
{
var shared = ArrayPool<int>.Shared; var rentedArray = shared.Rent(10); for (int i = 0; i < 10; i++)
{
rentedArray[i] = i + 1;
} for (int j = 0; j < 10; j++)
{
Console.WriteLine(rentedArray[j]);
} shared.Return(rentedArray); Console.ReadKey();
}

创建自定义的 ArrayPool

你也可以通过重写 ArrayPool 来实现自定义的池化对象,如下代码所示:


public class CustomArrayPool<T> : ArrayPool<T>
{
public override T[] Rent(int minimumLength)
{
throw new NotImplementedException();
}
public override void Return(T[] array, bool clearArray = false)
{
throw new NotImplementedException();
}
}

使用 MemoryPool<T>

System.Memory 命名空间下提供了一个内存池对象 MemoryPool<T>,在这之前你需要每次都 new 一个内存块出来,同时也增加了 GC 的负担,有了 MemoryPool<T> 之后,你需要的内存块直接从池中拿就可以了。


static void Main(string[] args)
{ var memoryPool = MemoryPool<int>.Shared; var rentedArray = memoryPool.Rent(10); for (int i = 0; i < 10; i++)
{
rentedArray.Memory.Span[i] = i + 1;
} for (int j = 0; j < 10; j++)
{
Console.WriteLine(rentedArray.Memory.Span[j]);
} Console.ReadKey();
}

ArrayPool<T> vs MemoryPool<T>

从上面的演示可以看出, ArrayPool<T> 是以 array 的形式向外租借,而 MemoryPool<T> 则是以 内存块 的方式向外租借,所以在重复使用 array 的场景下可以优选 ArrayPool<T> 来提高性能,如果你的代码是以 Memory<T> 这种内存块的形式多次使用则优先使用 MemoryPool<T>

更多精彩,欢迎订阅

译文链接:https://www.infoworld.com/article/3596289/how-to-use-arraypool-and-memorypool-in-c.html

如何在 C# 中使用 ArrayPool 和 MemoryPool的更多相关文章

  1. 我是如何在SQLServer中处理每天四亿三千万记录的

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  2. 如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧

    做WEB项目,一定都用过JSP这个大牌.Spring MVC里面也可以很方便的将JSP与一个View关联起来,使用还是非常方便的.当你从一个传统的Spring MVC项目转入一个Spring Boot ...

  3. 如何在latex 中插入EPS格式图片

    如何在latex 中插入EPS格式图片 第一步:生成.eps格式的图片 1.利用visio画图,另存为pdf格式的图片 利用Adobe Acrobat裁边,使图片大小合适 另存为.eps格式,如下图所 ...

  4. 如何正确的使用json?如何在.Net中使用json?

    什么是json json是一种轻量级的数据交换格式,由N组键值对组成的字符串,完全独立于语言的文本格式. 为什么要使用json 在很久很久以前,调用第三方API时,我们通常是采用xml进行数据交互,但 ...

  5. [原创]如何在Parcelable中使用泛型

    [原创]如何在Parcelable中使用泛型 实体类在实现Parcelable接口时,除了要实现它的几个方法之外,还另外要定义一个静态常量CREATOR,如下例所示: public static cl ...

  6. 如何在springMVC 中对REST服务使用mockmvc 做测试

    如何在springMVC 中对REST服务使用mockmvc 做测试 博客分类: java 基础 springMVCmockMVC单元测试  spring 集成测试中对mock 的集成实在是太棒了!但 ...

  7. 如何在tomcat中如何部署java EE项目

    如何在tomcat中如何部署java EE项目 1.直接把项目复制到Tomcat安装目录的webapps目录中,这是最简单的一种Tomcat项目部署的方法,也是初学者最常用的方法.2.在tomcat安 ...

  8. 【转】我是如何在SQLServer中处理每天四亿三千万记录的

    原文转自:http://blog.jobbole.com/80395/ 首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文 ...

  9. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

随机推荐

  1. CF1471-B. Strange List

    CF1471-B. Strange List 题意: 给定一个由\(n\)个数字组成的数组以及一个\(x\).现在从前往后遍历数组,若当前遍历的数字\(a[i]\)可以被\(x\)整除,那么就在数组的 ...

  2. Zabbix 监控网站

    官网教学步骤 配置 Web 监控 创建 Web 场景 配置 Web 场景 配置 Web 监控步骤 一共划分为 5 个步骤: 监测访问登录页面 模拟登录功能 # sid 变量的值 regex:name= ...

  3. 缓冲区溢出实验 5 Snprintf

    实验环境.代码.及准备 https://www.cnblogs.com/lqerio/p/12870834.html vul5 Snprintf函数,百度百科: 将可变个参数(...)按照format ...

  4. sizeof和strlen在string类中的使用

    字符串的sizeof和strlen 考虑下面的问题: char a[] = "abcdef"; char b[20] = "abcdef"; string s ...

  5. C# 数据类型(3)

    动态类型 dynamic types 动态类型是后来引进的,他其实是一个static type,但是不像其他的静态类型,编译器不会检查你到底是啥类型(也不会检查你能不能去call某个'method') ...

  6. how to share UI components

    how to share UI components The shared component cloud · Bit https://bit.dev/ A better way to build w ...

  7. Dart & import show & import hide & import as & part & part of

    Dart & import show & import hide & import as & part & part of // 部分导入,即仅仅导入 dart ...

  8. Apple & iOS & Device Screen Sizes and Orientations & React Native

    Apple & iOS & Device Screen Sizes and Orientations & React Native iOS devices https://de ...

  9. React Native & Android & Text Input

    React Native & Android & Text Input react native clear input value https://stackoverflow.com ...

  10. macOS & Nginx

    macOS & Nginx ngnix # 使用 brew 安装(如果没有 brew 命令,需要自行安装 brew) $ brew install nginx $ nginx -h # 查看 ...