写在前面

前文主要介绍了ObjectPool的一些理论基础,本文主要从源码角度理解Microsoft.Extensions.ObjectPool是如何实现的。下图为其三大核心组件图:

核心组件

ObjectPool

ObjectPool是一个泛型抽象类,里面只有两个抽象方法,Get和Return。它从底层定义了最一般的接口。

  • Get方法用于从对象池获取到可用对象,如果对象不可用则创建对象并返回出来

  • Return方法用户将对象返回到对象池

源码如下:

ObjectPoolProvider

ObjectPoolProvider也是抽象类,其内部内置了一个已经实现的Create泛型方法以及一个抽象Create方法,这代表两种ObjectPool的创建方式,一个是基于默认策略的,一个是基于用户自定义策略的。

IPooledObjectPolicy

这个接口是一个泛型接口,用于提供一种策略来管理对象池中的对象,同样也有两个方法,Create和Return。

  • Create方法用于创建相关类型实例

  • Return方法用于将已经使用好的对象放回到对象池的时候进行逻辑处理,包括对象的状态重置以及是否能够放回到对象池

该接口有一个实现PooledObjectPolicy,这是一个抽象类,内部有两个抽象方法:

实现机制

其内部实现逻辑较为简单,充分考虑到了一般实现、对象追踪、对象释放等场景的使用方式。

以下为其逻辑图:

DefaultObjectPool

DefaultObjectPool实现了ObjectPool,其内部维护了一个结构体类型的私有数组,用于存储相关对象。该数组的大小在构造函数中定义,其实际大小为输入值减去1(默认情况下,其值为逻辑处理器数量的两倍)主要是因为DefaultObjectPool单独将首项定义了出来。

以下为DefaultObjectPool中Get和Return的实现:

通过源码可以知道这两个方法大量使用了Interlocked.CompareExchange:

比较location1与comparand,如果不相等,什么都不做;如果location1与comparand相等,则用value替换location1的值。无论比较结果相等与否,返回值都是location1中原有的值。

Interlocked.CompareExchange的使用确保了线程安全性。

DefaultObjectPoolProvider

DefaultObjectPoolProvider实现了ObjectPoolProvider,该类重写了Create方法并返回ObjectPool对象。该类还定义了MaximumRetained属性,默认情况下,其值为逻辑处理器数量的两倍。

其源码如下,比较简单:

其中DisposableObjectPool是DefaultObjectPool类的派生类,这个类也实现了IDisposable,用于创建可手动释放的ObjectPool对象。

其相关代码如下:

DefaultPooledObjectPolicy

该类继承了PooledObjectPolicy,实现也非常简单。

不过值得注意的是,PooledObjectPolicy还有一个实现StringBuilderPooledObjectPolicy,这个类从命名上看就知道是基于StringBuilder的。其内部默认定义了StringBuilder的大小以及初始化容量。并确定了超出容量后,将不允许归还对象。

在我们自定义PooledObjectPolicy的时候,可以参考这段实现去扩展新的PooledObjectPolicy对象。

我们看一下源码:

对象追踪

该库内部定义了LeakTrackingObjectPool和LeakTrackingObjectPoolProvider用于追踪对象状态。

  • LeakTrackingObjectPoolProvider会根据构造函数传入的ObjectPoolProvider类型对象,创建LeakTrackingObjectPool实例。

  • LeakTrackingObjectPool内部定义了ConditionalWeakTable<T, Tracker>类型的数组,MSDN的解释是使编译器可以将对象字段动态附加到托管对象,这个对象会自动维护内部的键值对,而不会一直使其停留在内存中。

Tracker是LeakTrackingObjectPool的内部类,其目的是为了方便我们对对象本身进行维护跟踪,其定义如下:

.NET Core 3.0之深入源码理解ObjectPool(二)相关推荐

  1. .NET Core 3.0之深入源码理解ObjectPool(一)

    写在前面 对象池是一种比较常用的提高系统性能的软件设计模式,它维护了一系列相关对象列表的容器对象,这些对象可以随时重复使用,对象池节省了频繁创建对象的开销. 它使用取用/归还的操作模式,并重复执行这些 ...

  2. .NET Core 3.0之深入源码理解Host(二)

    写在前面 停了近一个月的技术博客,随着正式脱离996的魔窟,接下来也正式恢复了.本文从源码角度进一步讨论.NET Core 3.0 中关于Host扩展的一些技术点,主要内容是关于创建Long Run ...

  3. .NET Core 3.0之深入源码理解HttpClientFactory(二)

    写在前面 上一篇文章讨论了通过在ConfigureServices中调用services.AddHttpClient()方法,并基于此进一步探讨了DefaultHttpClientFactory是如何 ...

  4. .NET Core 3.0之深入源码理解Startup的注册及运行

    开发.NET Core应用,直接映入眼帘的就是Startup类和Program类,它们是.NET Core应用程序的起点.通过使用Startup,可以配置化处理所有向应用程序所做的请求的管道,同时也可 ...

  5. .NET Core 3.0之深入源码理解HealthCheck(一)

    写在前面 我们的系统可能因为正在部署.服务异常终止或者其他问题导致系统处于非健康状态,这个时候我们需要知道系统的健康状况,而健康检查可以帮助我们快速确定系统是否处于正常状态.一般情况下,我们会提供公开 ...

  6. .NET Core 3.0之深入源码理解Kestrel的集成与应用(二)

    前言 前一篇文章主要介绍了.NET Core继承Kestrel的目的.运行方式以及相关的使用,接下来将进一步从源码角度探讨.NET Core 3.0中关于Kestrel的其他内容,该部分内容,我们无需 ...

  7. .NET Core 3.0之深入源码理解Kestrel的集成与应用(一)

    写在前面 ASP.NET Core 的 Web 服务器默认采用Kestrel,这是一个基于libuv(一个跨平台的基于Node.js的异步I/O库)的跨平台.轻量级的Web服务器. 在开始之前,先回顾 ...

  8. .NET Core 3.0之深入源码理解Configuration(一)

    微软在.NET Core里设计出了全新的配置体系,并以非常灵活.可扩展的方式实现.从其源码来看,其运行机制大致是,根据其Source,创建一个Builder实例,并会向其添加Provider,在我们使 ...

  9. .NET Core 3.0之深入源码理解HttpClientFactory(一)

    写在前面 创建HttpClient实例的时候,在内部会创建HttpMessageHandler链,我们知道HttpMessageHandler是负责建立连接的抽象处理程序,所以HttpClient的维 ...

最新文章

  1. C#WinForm的线程及Invoke应用(转)
  2. linux 压缩文件夹格式,Linux下常见文件格式的压缩、解压小结
  3. Android Binder总结
  4. php yii 插入,YII框架批量插入数据的方法
  5. Android 应用 之路 百度地图API使用(3)
  6. IOS中的swift和oc关于对象模型的description方法重写
  7. 设计模式 原型模式_原型设计模式:创建另一个小车
  8. linux怎么抓sip包,Ubuntu下使用Wireshark进行抓包分析(含SIP和RTP包)
  9. cookie购物车php简单,cookie的优化与购物车实例
  10. javascript自制函数图像生成器
  11. Mac下mysql登陆问题
  12. 不搞数字货币的科技巨头们,在区块链的布局上有这三个方向
  13. php 写入txt换行_PHP fwrite 函数:将字符串写入文件(追加与换行)
  14. 关于84坐标系与54坐标系转换问题
  15. 最受Java程序员欢迎的大数据工具排名
  16. NOI 1966 玛雅历
  17. C++ 实现贪吃蛇游戏(免费附源码)
  18. 两个单位方向矢量夹角的余弦值推导过程【遥感散射角余弦】
  19. Windows通过虚拟机的Ubuntu系统安装、配置、管理、远程访问ClickHouse
  20. 申请圣文森特牌照申请流程

热门文章

  1. objective-c中的static
  2. 算法的力量(李开复)
  3. 学习kaneboy的 sps区域列表的管理入口程序
  4. 怎样制作滴滴截图_滴滴老了吗?
  5. 10.31T4 HAOI2010最长公共子序列 计数+容斥原理
  6. Oracle数据库-主键(primary key)、外键(foreign key)、候选键(candidate key)、超键(super key)和references总结...
  7. 如何获得一个集合的所有子集合?
  8. 添加CSS的四种方式
  9. 如何解决U盘无法停止通用卷设备
  10. javascript常用技巧