前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Core 3.0之深入源码理解ObjectPool(一)

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

作者头像
Edison.Ma
发布2019-10-15 23:08:44
4840
发布2019-10-15 23:08:44
举报
文章被收录于专栏:DotNet Core圈圈

写在前面

对象池是一种比较常用的提高系统性能的软件设计模式,它维护了一系列相关对象列表的容器对象,这些对象可以随时重复使用,对象池节省了频繁创建对象的开销。

它使用取用/归还的操作模式,并重复执行这些操作。如下图所示:

本文将主要介绍对象池的基本概念、对象池的优势及其工作机制,下一篇文档将从源码角度介绍.NET Core 3.0是如何实现对象池的。

另外本公众号引入了一位来自中国台湾技术社区的程序员作为运营者,在不涉及到政治的情况下,欢迎大家积极来撩。

对象池基础

对象池的基本概念

对象池的核心概念是容器,其表示形式可以认为是列表。每当有新的对象创建请求进入时,都会通过从池中分配一个对象来满足该请求。当我们需要获取某个对象时,可以从池中获取。既然有了对象池,那么也就很方便我们就很容易建立起对象的管理与追踪了了。

对象池的优势

我们知道一旦应用程序启动并运行,内存使用就会受到系统所需对象的数量和大小的影响。

我们知道创建一个对象的实例,是需要消耗一定的系统资源,尤其是该对象的构造十分复杂的时候,再加上需要频繁创建的时候,其实例化所消耗的资源更加昂贵。如果我们能有一种办法减少这种昂贵的系统开销,这对系统性能的提升是十分有帮助的。

对象池理念的出现,有助于我们解决复杂对象的重复创建所引发的资源开销问题。对象存储在某种类型的列表或者说数组中,我们可以和获取数组中的子项一样获取已经存在在对象池中的对象。

对象池的最大优点是,它可以自主管理内部已经创建的对象,包括回收和重复使用对象。程序在使用完某个对象后,会将其发还至对象池,而不是在内存中销毁他们。

对象池通过资源的分配,因而也就减少了应用程序所需的垃圾回收数量。这对于需要频繁创建同一对象的功能来说,对象池最大程度地减少了系统资源的消耗。

简单来说,对象池的设计目标就是要使对象可以得到重复使用,而不是被垃圾回收器回收。

对象池的工作机制

通常情况下,当客户端程序需要某个对象时,对象池首先尝试提供一个已经创建的对象。如果没有可用的对象,则会创建一个新对象。这类似于一个GetOrAdd的操作。同时对象池中对象的数量就会减少,直到该对象已经使用完,那么它就会被放回到对象池池中以等待使用。这就是为什么对象池有助于重用性、并减少了在获取对象时创建对象所涉及的开销的原因。

另外,需要注意的是,只要池中至少有一个对象,该池就会一直保留在内存中。只要对象池还在,里面的对象也会一直存在。

当对象池用于并发操作时,需要确保对象池是线程安全的,而且其本身还要有很高的性能。

ConcurrentBag对象池解决方案

这个解决方案来自于MSDN,ConcurrentBag <T>用于存储对象,因为它支持快速插入和删除,尤其是在同一线程同时添加和删除项目时。该示例可以进一步扩展为围绕IProducerConsumerCollection <T>构建,该数据由bag数据结构实现,ConcurrentQueue <T>和ConcurrentStack <T>也是如此。

代码语言:javascript
复制
using System;using System.Collections.Concurrent;using System.Threading;using System.Threading.Tasks;

namespace ObjectPoolExample{   public class ObjectPool<T>  {      private ConcurrentBag<T> _objects;      private Func<T> _objectGenerator;
      public ObjectPool(Func<T> objectGenerator)      {          if (objectGenerator == null) throw new ArgumentNullException("objectGenerator");          _objects = new ConcurrentBag<T>();          _objectGenerator = objectGenerator;      }
      public T GetObject()      {          T item;          if (_objects.TryTake(out item)) return item;          return _objectGenerator();      }
      public void PutObject(T item)      {          _objects.Add(item);      }  }
  class Program  {     static void Main(string[] args)      {          CancellationTokenSource cts = new CancellationTokenSource();
          // Create an opportunity for the user to cancel.          Task.Run(() =>              {                  if (Console.ReadKey().KeyChar == 'c' || Console.ReadKey().KeyChar == 'C')                      cts.Cancel();              });
          ObjectPool<MyClass> pool = new ObjectPool<MyClass> (() => new MyClass());
          // Create a high demand for MyClass objects.          Parallel.For(0, 1000000, (i, loopState) =>              {                  MyClass mc = pool.GetObject();                  Console.CursorLeft = 0;                  // This is the bottleneck in our application. All threads in this loop                  // must serialize their access to the static Console class.####.####}", mc.GetValue(i));                                                     pool.PutObject(mc);                  if (cts.Token.IsCancellationRequested)                      loopState.Stop();
              });          Console.WriteLine("Press the Enter key to exit.");          Console.ReadLine();          cts.Dispose();      }
  }
  // A toy class that requires some resources to create.  // You can experiment here to measure the performance of the  // object pool vs. ordinary instantiation.  class MyClass  {      public int[] Nums {get; set;}      public double GetValue(long i)      {          return Math.Sqrt(Nums[i]);      }      public MyClass()      {          Nums = new int[1000000];          Random rand = new Random();          for (int i = 0; i < Nums.Length; i++)              Nums[i] = rand.Next();      }  }   }

参考链接:https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/how-to-create-an-object-pool

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet技术平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 对象池基础
    • 对象池的基本概念
      • 对象池的优势
        • 对象池的工作机制
        • ConcurrentBag对象池解决方案
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档