对资源的可复用是提升应用程序性能的一个非常重要的手段,比如本篇要分享的 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. python博客大全

    python技术博客 egon博客 计算机基础系列一:计算机硬件 - linhaifeng - 博客园 https://www.zhihu.com/people/xiaoyuanqujing #ego ...

  2. Operating System:信号量

    pv原语操作(1)操作系统PV意思:PV操作与信号量的处理相关,P表示通过的意度思,V表示释放的意思.(2)p操作和v操作是不可中断问的程序段,称为原语.如果将信号量看作共享变量,则pv操作为其临界区 ...

  3. codeforces 1019B The hat 【交互题+二分搜索】

    题目链接:戳这里 学习题解:戳这里

  4. dp的小理解

    这段时间刷dp,总结出了一个不算套路的套路. 1.根据题意确定是否有重叠子问题,也就是前面的状态对后面的有影响,基本满足这个条件的就可以考虑用dp了. 2.确定是dp后,就是最难的部分--如何根据题意 ...

  5. 牛客网-Beauty of Trees 【加权并查集】

    锟斤拷锟接o拷https://www.nowcoder.com/acm/contest/119/A锟斤拷源锟斤拷牛锟斤拷锟斤拷 锟斤拷目锟斤拷锟斤拷 It锟斤拷s universally acknow ...

  6. GitHub new features 2020 All In One

    GitHub new features 2020 All In One Discussions Discussions is the space for your community to have ...

  7. JavaScript string repeat methods All In One

    JavaScript string repeat methods All In One There are many ways in the ES-Next ways repeat ES2015 / ...

  8. CVS、SVN、Git、GitHub :版本控制系统

    1 1 1 Git常用命令 1 1 1 1 1 1 https://www.codecademy.com/learn/learn-git Learn Git You have now been int ...

  9. tslint 忽略对某行代码的检测

    tslint rules class Ajanuw { constructor() { console.log("hello ajanuw"); } } // @ts-ignore ...

  10. dart2native 使用Dart 在macOS,Windows或Linux上创建命令行工具

    下载dart2.6以上 >dart2native --help 编写源文件 // bin\main.dart main(List<String> args) { print('hel ...