对象池方案总结

  最近项目涉及到大量数据并发的问题,短时间内会产生和销毁大量对象,因此担心会不会影响系统的性能,考虑使用对象池的方案。

  但是在对对象池的学习中,对于是否使用对象池产生的疑问。

  MSDN中 How to: Create an Object Pool by Using a ConcurrentBag”https://msdn.microsoft.com/en-us/library/ff458671.aspx)一文中提到

  “Object pools can improve application performance in situations where you require multiple instances of a class and the class is expensive

  to create or destroy. ”,这里考虑是否必须当类实例的创建和销毁开销比较大的时候才能够使用对象池?如果对象创建的太频繁会不会也会造成很大

  的开销,影响系统的性能,同时对象的销毁也是个问题。因为对GC了解不够深入,不敢妄下判断。

  在一种轻量级对象池的设计与实现文中提到什么时候不要池化:

  采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,从而提高整体的性能。然而池化处理本身也要付出代价,因此,并非任何情况下都适合

  采用对象池化。Dr. CliffClick在JavaOne 2003上发表的《Performance Myths Exposed》中,给出了一组其它条件都相同时,使用与不使用对象池化技术的实际性能的比较结果。

  他的实测结果表明:对于类似Point这样的轻量级对象,进行池化处理后,性能反而下降,因此不宜池化;对于类似Hashtable这样的中量级对象,进行池化处理后,性能基本不变,

  一般不必池化(池化会使代码变复杂,增大维护的难度);对于类似JPanel这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。根据使用方法的不同,实际的

  情况可能与这一测量结果略有出入。在配置较高的机器和技术较强的虚拟机上,不宜池化的对象的范围可能会更大。不过,对于像网络和数据库连接这类重量级的对象来说,

  目前还是有池化的必要。基本上,只在重复生成某种对象的操作成为影响性能的关键因素的时候,才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话,

  还是不采用对象池化技术,以保持代码的简明,而使用更好的硬件和更棒的虚拟机来提高性能为佳。

  随后,在一篇讲解GC知识的文章:垃圾回收机制GC知识再总结兼谈如何用好GC中提到“不要频繁的new生命周期很短object,这样频繁垃圾回收频繁压缩

  有可能会导致很多内存碎片,可以使用设计良好稳定运行的对象池(ObjectPool)技术来规避这种问题”,看来对于自己项目的情况是否可以使用对象池

  还有待项目测试后再做判断。

  这里先总结可能使用对象池的两种情况(可能不完全正确):

  1. 需要多个类的实例,当类实例的创建和销毁开销比较大;
  2. 对象生命周期很短,频繁的进行创建和销毁。 对象最好是无状态的,否则重复使用前回复原始状态;

  了解了以上知识后,在网上找到了几个实现方案,大体思路是一致的:

  1. 编写高效的C++程序方法之使用对象池: C++的实现方法,思路简单明晰,值的借鉴,但方法在多线程中使用感觉会有问题。

  2. 在C#中实现简单的对象池 :此方案利用ConcurrentBag<T>类,实现了对象池的功能。因为本人开发环境为C#,因此考虑使用此方法。

   这里面ConcurrentBag<T>类是头一次使用,MSDN中的解释是:

ConcurrentBag<T> is used to store the objects because it supports fast insertion and removal, especially when the same thread is both

    adding and removing items.

Bags are useful for storing objects when ordering doesn‘t matter, and unlike sets, bags support duplicates.

    ConcurrentBag<T> is a thread-safe bag implementation, optimized for

scenarios where the same thread will be both producing and consuming data stored in the bag.

3. 一种轻量级对象池的设计与实现: java的实现方式,值的借鉴;

  4. 一个通用并发对象池的实现:http://ifeve.com/generic-concurrent-object-pool/,同样是java;

  5. Lock Free ObjectPool的C#实现 (对象池):http://www.360doc.com/content/14/1015/09/5054188_417089038.shtml

  6. C#对象池详细解析

  学习了以上的方案,确定了自己要使用的方案。声明:本方案不是原创。

 1  /// <summary>
 2     /// 对象池
 3     /// </summary>
 4     /// <typeparam name="T"></typeparam>
 5     public class ObjectPool<T>
 6     {
 7         private readonly ConcurrentBag<T> _buffer;
 8
 9         private readonly Func<T> _createFunc;
10         private readonly Action<T> _resetFunc;
11
12         public int Capacity { get; private set; }
13
14         private readonly int _chunkSize;
15         public int Count { get { return _buffer.Count; } }
16
17         public ObjectPool(Func<T> createFunc, Action<T> resetFunc, int capacity = 50, int chunkSize = 10)
18         {
19             if (createFunc == null)
20             {
21                 throw new ArgumentNullException("createFunc");
22             }
23             if (capacity <= 0)
24             {
25                 throw new ArgumentOutOfRangeException("capacity");
26             }
27             if (chunkSize <= 0)
28             {
29                 throw new ArgumentOutOfRangeException("chunkSize");
30             }
31
32             this._buffer = new ConcurrentBag<T>();
33             this._createFunc = createFunc;
34             this._resetFunc = resetFunc;
35
36             this.Capacity = capacity;
37             this._chunkSize = chunkSize;
38
39             AllocateChunk();
40         }
41
42         public T GetObject()
43         {
44             T obj;
45             if (!_buffer.TryTake(out obj))
46             {
47                 //创建一些数据
48                 AllocateChunk();
49                 return _buffer.FirstOrDefault();
50             }
51             return obj;
52         }
53
54         public void ReleaseObject(T obj)
55         {
56             Contract.Assume(obj != null);
57
58             //超过容量了,不再需要
59             if (Count >= Capacity) return;
60
61             if (_resetFunc != null)
62             {
63                 _resetFunc(obj);
64             }
65
66             _buffer.Add(obj);
67         }
68
69         private void AllocateChunk()
70         {
71             for (int i = 0; i < _chunkSize; i++)
72             {
73                 _buffer.Add(_createFunc());
74             }
75         }
76     }

  下面贴出MSDN中对象池的使用方法:

 1  class Program
 2     {
 3        staticvoid Main(string[] args)
 4         {
 5             CancellationTokenSource cts = new CancellationTokenSource();
 6
 7             // Create an opportunity for the user to cancel.
 8             Task.Run(() =>
 9                 {
10                     if (Console.ReadKey().KeyChar == ‘c‘ || Console.ReadKey().KeyChar == ‘C‘)
11                         cts.Cancel();
12                 });
13
14             ObjectPool<MyClass> pool = new ObjectPool<MyClass> (() => new MyClass());
15
16             // Create a high demand for MyClass objects.
17             Parallel.For(0, 1000000, (i, loopState) =>
18                 {
19                     MyClass mc = pool.GetObject();
20                     Console.CursorLeft = 0;
21                     // This is the bottleneck in our application. All threads in this loop// must serialize their access to the static Console class.
22                     Console.WriteLine("{0:####.####}", mc.GetValue(i));
23
24                     pool.PutObject(mc);
25                     if (cts.Token.IsCancellationRequested)
26                         loopState.Stop();
27
28                 });
29             Console.WriteLine("Press the Enter key to exit.");
30             Console.ReadLine();
31             cts.Dispose();
32         }
33     }
时间: 2024-10-10 21:11:20

对象池方案总结的相关文章

[译]Unity3D内存管理——对象池(Object Pool)

从一个简单的对象池类开始说起 对象池背后的理念其实是非常简单的.我们将对象存储在一个池子中,当需要时在再次使用,而不是每次都实例化一个新的对象.池的最重要的特性,也就是对象池设计模式的本质是允许我们获取一个“新的”对象而不管它真的是一个新的对象还是循环使用的对象.该模式可以用以下简单的几行代码实现: public class ObjectPool<T> where T : class, new() { private Stack<T> m_objectStack = new Sta

【Todo】Apache-Commons-Pool及对象池学习

有这篇文章: http://www.cnblogs.com/tommyli/p/3510095.html 方案提供了三种类型的pool,分别是GenericKeyedObjectPool,SoftReferenceObjectPool和GenericObjectPool.其中GenericObjectPool是一般意义上的对象池:SoftReferenceObjectPool是弱引用的对象池:GenericKeyedObjectPool是具备分组的对象池.

JAVA模式 对象池 简要代码示例

package org.rui.util; import java.util.ArrayList; /** * 对象复用模式 * * @author PC * */ public class PoolManager { //连接池对象 public static class PoolItem { boolean inUse = false; Object item;//池数据 PoolItem(Object item) { this.item = item; } } //连接池集合 privat

对象池学习

概念 为了避免大量创建(构造)对象.销毁(析构)对象带的性能开销 设计 对象队列 初始化时,指定队列长度 出队.入队操作需要加锁保护 对象的构造 在初始化对象池时构造好 对象并不是一开始全部构造好,而是在获取对象的过程中构造(构造之后便保存在队列中供使用) 获取对象 提供接口 归还对象 提供接口,显示归还 利用c++ RAII特性(即智能指针析构时,调用归还操作),隐式归还 对象管理器 负责构造对象与销毁对象 管理每个对象的状态 获取状态接口 提供接口,用户可以获取对象池的各种状态信息 注意事项

游戏编程模式-对象池

“使用固定的对象池重用对象,取代单独的分配和释放对象,以此来达到提升性能和优化内存使用的目的.” 动机 假设我们正在致力于游戏的视觉效果优化.当英雄释放魔法时,我们想让一个火花在屏幕上炸裂.这通常需要一个粒子系统(一个用来生成大量小的图形并在它们生存周期产生动画的引擎)来实现.而这个粒子系统实现这个火花的时候会产生大量的粒子,我们需要非常快速的创建这些粒子同时在这些粒子“死亡”的时候释放这些粒子对象.在这里,我们会碰到一个严重的问题——内存碎片化. 碎片化地害处 为游戏和移动设备编程在很多方面都

整数对象池

Python 的内建对象存放在源代码的Objects目录下.intobject.c用于整数对象 在 Python 中,整数分为小整数对象和大整数对象 小整数对象 由于数值较小的整数对象在内存中会很频繁地使用,如果每次都向内存申请空间.请求释放,会严重影响 Python 的性能.好在 整数对象 属于不可变对象,可以被共享而不会被修改导致问题,所以为 小整数对象 划定一个范围,即小整数对象池,在Python运行时初始化并创建范围内的所有整数,这个范围内的 整数对象是被共享的,即一次创建,多次共享引用

对象池实现分析

对象池实现分析 什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的概念.对象池缓存了一些已经创建好的对象,避免需要时才创建对象,同时限制了实例的个数.池化技术最终要的就是重复的使用池内已经创建的对象.从上面的内容就可以看出对象池适用于以下几个场景: 创建对象的开销大 会创建大量的实例 限制一些资源的使用 如果创建一个对象的开销特别大,那么提前创建一些可以使用的并且缓存起来(池化技术就是重复使用对象,提前创建并缓存起来重复使用就是池化

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

游戏中可能经常会遇到需要某个物体跟着鼠标移动,然后又需要把物体放在某个鼠标指定的位置 实现方式 Camera.main.WorldToScreenPoint Camera.main.ScreenToWorldPoint 3D打地鼠实例 我这里用到的素材都比较简陋,几乎全是用Unity做的 首先是锤子 就是两个Cylinder,在把手的位置放一个空物体用于模拟锤子的动作,命名为Hammer,把锤子作为Hammer的子物体,给Hammer添加Animation动画: 在三个关键帧位置设置Hammer

c++实现游戏开发中常用的对象池(含源码)

c++实现游戏开发中常用的对象池(含源码) little_stupid_child2017-01-06上传 对象池的五要素: 1.对象集合 2.未使用对象索引集合 3.已使用对象索引集合 4.当前使用量 5.最大使用量 http://download.csdn.net/download/little_stupid_child/9730912