Unity对象池技术
https://blog.csdn.net/LemonXQ/article/details/77148886

顾名思义,对象池是存放对象的缓冲区。用户可以从缓冲区中放入/取出对象。一类对象池存放一类特定的对象。那么对象池有什么用呢?在游戏中,经常会有产生/销毁大量同类游戏对象的需求,比如游戏中源源不断的敌人、频繁刷新的宝箱、乃至一些游戏特效(风、雨等)。如果没有一种比较好的机制来管理这些对象的产生和销毁,而是一昧的Instantiate和Destroy,将使你的游戏性能大大下降,甚至出现卡死、崩溃……

简而言之,就是当需要使用一个对象的时候,直接从该类对象的对象池中取出(SetActive(true)),如果对象池中无可用对象,再进行Instantitate。而当不再需要该对象时,不直接进行Destroy,而是SetActive(false)并将其回收到对象池中。

深入理解对象池技术

https://blog.csdn.net/jxw167/article/details/72377411

游戏中通过重新使用固定池中的对象来提高性能和内存使用,而不是单独分配和释放对象。

粒子播放时,可能导致数百颗粒子产生,系统需要能够很快地创建它们, 更重要的是,我们需要确保创建和销毁这些粒子不会导致内存碎片。

移动设备的编程在许多方面比传统的PC编程更接近嵌入式编程, 内存稀缺,用户期望游戏稳定,高效的压缩内存管理器很少可用。 在这种环境中,内存碎片是致命的。

碎片意味着我们堆中的可用空间被分解成较小的内存块,而不是一个大的开放块。 可用的总内存可能很大,但最大的连续区域可能会很小。 假设我们已经有十四个字节可用,但是它们被分成两个七字节的片段,它们之间带有大量的使用内存。 如果我们尝试分配一个十二字节的对象,我们将失败。 如下所示:

由于碎片,因为分配可能很慢,游戏对于管理内存的时间和方式非常谨慎。 一个简单的解决方案通常是最好的 - 在游戏开始时抓住大块内存,并且不要释放它直到游戏结束。 但是,对于在游戏运行期间需要创建和销毁东西的系统来说,这是一个痛苦。

对象池给了我们两个世界最好的, 对于内存管理员,我们只是在前面分配一大块内存,而不是在游戏中释放它。 对于池的用户,我们可以自由地分配和释放对象到我们心脏的内容。

定义一个维护一个可重用对象集合的池类。 每个对象都支持一个“在使用中”查询来判断当前是否“活着”。 当池初始化时,它将在前面创建整个对象集合(通常在单个连续分配中),并将它们全部初始化为“未使用”状态。    当你想要一个新对象时,查询一个池, 它找到一个可用对象,将其初始化为“正在使用”,并返回。 当对象不再需要时,它被设置回到“不使用”状态。 这样,可以自由地创建和销毁对象,而不需要分配内存或其他资源。
这种模式在游戏中广泛应用于诸如游戏实体和视觉效果之类的明显的东西,但它也用于不太可见的数据结构,例如当前播放的声音。 使用对象池时:

一、您需要频繁地创建和销毁对象。

二、对象的大小相似。

三、堆上分配对象很慢或可能导致内存碎片化。

四、每个对象都封装了一个资源,例如数据库或网络连接,这些资源很昂贵,可以被重用。

你通常依靠一个垃圾收集器或者新的和删除来处理你的内存管理, 通过使用对象池,您说的是“我更好地了解这些字节应该如何处理”。这意味着你可以处理这种模式的局限性。

需要根据游戏的需要调整对象池的大小, 调整时,当池太小时,通常很明显(没有什么像碰撞引起你的注意), 还要注意池不算太大, 一个较小的池释放可用于其他东西的存放。

大多数池实现将对象存储在一个对象数组中, 如果所有的对象都是相同的对象,那就行了。 但是,如果要在池中存储不同类型的对象或可能添加字段的子类的实例,则需要确保池中的每个插槽具有足够的可用对象的内存。 否则,一个意想不到的大对象会踩下下一个对象并将其记录在内。

同时,当您的对象尺寸不同时, 每个插槽需要足够大以容纳最大的对象,如果对象很少,那么每次在该插槽中放一个较小的对象时,都会丢弃内存。 这就像通过机场安全,并为您的钥匙和钱包使用一个巨大的携带大小的行李托盘。    当你发现自己使用了很多内存的时候,可以考虑将对象池分成不同大小的物体 - 不同大小的物品 - 行李箱的大托盘,小容器的小托盘。    大多数内存管理器都有一个调试功能,可以将新分配或释放的内存清除为一些明显的数值,如0xdeadbeef。 这可以帮助您找到由未初始化的变量引起的错误,或者在释放后使用内存。

由于我们的对象池在重用对象时不再经历内存管理器,所以我们失去了这个安全网,更糟糕的是,用于“新”对象的内存以前拥有完全相同类型的对象。 这使得几乎不可能告诉您是否在创建新对象时忘记初始化某些内容:存储对象的内存可能已经包含了几乎正确的数据。

因此,请特别注意,初始化池中新对象的代码完全初始化对象,甚至可能花费一点时间添加一个调试功能,以便在对象被回收时清除对象插槽的内存。

对象池在支持垃圾收集的系统中不常见,因为内存管理器通常会为您处理碎片。 但是池仍然有用,以避免分配和释放的成本,特别是在CPU速度较慢的移动设备和更简单的垃圾收集器上。    如果您使用对象池与垃圾收集器协同工作,请注意潜在的冲突。 由于池不再使用对象时不会重新分配对象,所以它们保留在内存中。 如果它们包含对其他对象的引用,它将阻止收集器再次收回它们。 为避免这种情况,当一个池化对象不再使用时,请清除其它对象所引用的任何引用。

对象池的优劣

https://blog.csdn.net/johnlee175/article/details/50826252

对象池的优点: 复用池中对象, 没有分配内存和创建堆中对象的开销, 没有释放内存和销毁堆中对象的开销, 进而减少垃圾收集器的负担, 避免内存抖动; 不必重复初始化对象状态, 对于比较耗时的constructor和finalize来说非常合适;

对象池的缺点: 
    (1)现在Java的对象分配操作不比c语言的malloc调用慢, 对于轻中量级的对象, 分配/释放对象的开销可以忽略不计; 
    (2)并发环境中, 多个线程可能(同时)需要获取池中对象, 进而需要在堆数据结构上进行同步或者因为锁竞争而产生阻塞, 这种开销要比创建销毁对象的开销高数百倍; 
    (3)由于池中对象的数量有限, 势必成为一个可伸缩性瓶颈; 
    (4)很难正确的设定对象池的大小, 如果太小则起不到作用, 如果过大, 则占用内存资源高, 可以起一个线程定期扫描分析, 将池压缩到一个合适的尺寸以节约内存,但为了获得不错的分析结果, 在扫描期间可能需要暂停复用以避免干扰(造成效率低下), 或者使用非常复杂的算法策略(增加维护难度); 
    (5)设计和使用对象池容易出错, 设计上需要注意状态同步, 这是个难点, 使用上可能存在忘记归还(就像c语言编程忘记free一样), 重复归还(可能需要做个循环判断一下是否池中存在此对象, 这也是个开销), 归还后仍旧使用对象(可能造成多个线程并发使用一个对象的情况)等问题;

对象池有其特定的适用场景: 
    (1)受限的, 不需要可伸缩性的环境(比如移动设备): cpu性能不够强劲, 内存比较紧张, 垃圾收集, 内存抖动会造成比较大的影响, 需要提高内存管理效率, 响应性比吞吐量更为重要; 
    (2)数量受限的资源, 比如数据库连接; (自己写比较容易埋坑, 建议使用成熟的库方案, 比如c3p0) 
    (3)创建成本高昂的对象, 可斟酌是否池化, 比较常见的有线程池, 字节数组池等; (如果有, 则建议使用成熟的库方案, 比如jdk自带的ThreadPoolExecutor, 而不是自己写)

android在支持库中提供了池的构件单元–Pools, 其中Pools.SimplePool实现比较简单, 采用固定长度的数组和后进先出的策略, 池中对象的内存不会再被释放, 直到池本身被垃圾回收; Pools.SynchronizedPool仅仅是在Pools.SimplePool基础上加了个同步锁; 
当然也可以使用apache commons pool2类库作为池的构件单元;

注: 
  响应性是指一个任务单元需要”多快”能处理完; 
  吞吐量是指一定的计算资源(如CPU, 内存, 硬盘容量, IO带宽)和单位时间内, 能完成”多少”任务; 
  可伸缩性是指增加计算资源(如CPU, 内存, 硬盘容量, IO带宽), 程序的吞吐量的能得到多大程度的增加; 
  Example1: 
  并行GC缩短了每次stop-the-world的时间来提供响应性, 但做完一次full-GC的任务量要比串行GC耗费更长的时间(吞吐量降低); 
  Example2: 
  程序分为彼此独立的表现层/业务逻辑层/持久化层会提供可伸缩性, 但由于在不同系统间传递数据, 比对应的未使用分层模型的程序要慢;

以上参考来自于<java并发编程实战>, <effective java>, <java程序性能优化-让你的Java程序更快, 更稳定>, 均反对滥用池化技术;

Unity对象池技术相关推荐

  1. Unity中的资源管理-对象池技术(3)

    本文分享Unity中的资源管理-对象池技术(3) 在上两篇文章中, 我们一起学习了普通类的两种对象池实现, 今天接着介绍Unity中GameObject(主要是预制实例化对象)的对象池. GameOb ...

  2. 面试官问:对象池技术了解吗?apache common pool2呢?

    欢迎关注方志朋的博客,回复"666"获面试宝典 对象池顾名思义就是存放对象的池,与我们常听到的线程池.数据库连接池.http连接池等一样,都是典型的池化设计思想. 对象池的优点就是 ...

  3. java对象工厂池_[转载]Java对象池技术的原理及其实现

    作者:汪永好 出处:计算机与信息技术 责任编辑: 方舟 [ 2006-11-25 07:00 ] 摘 要 :本文在分析对象池技术基本原理的基础上,给出了对象池技术的两种实现方式.还指出了使用对象池技术 ...

  4. java 对象池 博客_Java对象池技术的原理及其实现的小结

    一起学习 Java对象的生命周期大致包括三个阶段:对象的创建,对象的使用,对象的清除.因此,对象的生命周期长度可用如下的表达式表示:T = T1 T2 T3.其中T1表示对象的创建时间,T2表示对象的 ...

  5. java 对象池 实现_Java对象池技术的原理及其实现

    看到一片有关于java 对象基础知识,故转载一下,同时学习一下. 摘 要 本文在分析对象池技术基本原理的基础上,给出了对象池技术的两种实现方式.还指出了使用对象池技术时所应注意的问题. 关键词 对象池 ...

  6. U3D客户端框架之类对象池技术优化C#语言GC

    一.类对象池概念 1.类对象池介绍 类对象池,类似对象池,顾名思义就是一定数量的已经创建好的类对象(Object)的集合.当需要创建对象时,先在池子中获取,如果池子中没有符合条件的对象,再进行创建新对 ...

  7. 从入门到掉坑:Go 内存池/对象池技术介绍

    作者:deryzhou,腾讯 PCG 后台开发工程师 Go 中怎么实现内存池,直接用 map 可以吗?常用库里 GroupCache.BigCache 的内存池又是怎么实现的?有没有坑?对象池又是什么 ...

  8. unity 对象池模式

    1.理解 对象池用于减少内存开销,其原理就是把可能用到到的对象,先存在一个地方(池),要用的时候就调出来,不用就放回去.而不是要用的时候创建,不用的时候销毁. Eg: 我有个飞机,射击子弹,按传统的方 ...

  9. Unity对象池简单应用

    1.简单介绍 在Unity开发过程中,对象池是一种很好的能用于减少内存开销的方式.在许多场景中,比如角色射击出去的子弹,以及在游戏运行过程中频繁生成的敌人-如果在运行时实时在场景中Instance和D ...

最新文章

  1. linux当卡片机的手机,卡片机不如手机?看完你就不这么想了
  2. [入门]MyEclipse+tomcat搭建java web环境
  3. 一文带你全面了解电商在线支付
  4. Singing Superstar 字符串哈希-map操作
  5. vue 添加全局组件_自定义vue2.0全局组件(下篇)
  6. 孜然网址导航系统源码v1.0
  7. SV processses
  8. 【Python成长之路】python 基础篇 -- global/nonlocal关键字使用
  9. csstd超出部分用...替换
  10. 从零开始的Python学习Episode 20——面向对象(3)
  11. Unicode汉字编码表
  12. java中uri与url的区别_URL和URI的区别与总结
  13. 【原理+实战+视频+源码】马士兵Java高级互联网架构
  14. 一次让你搞懂Android应用签名
  15. 计算机毕业后的打算英语作文,大学毕业后的职业生涯规划的英语作文
  16. 理解java的内存结构——运行时数据区域
  17. 信阳市的计算机本科学校,郭华平 - 信阳师范学院 - 计算机与信息技术学院
  18. 大神爆料:红米K30S至尊纪念版和红米10XPro哪个好-哪个更值得入手-参数对比
  19. 第三阶段:1.数据分析:2.定性定量数据分析
  20. Family Show 3.0分析(一)项目文件结构分析

热门文章

  1. 快钱联手浩方 开拓网络游戏运营
  2. SUSE Linux 软件管理
  3. OpenvSwitch — Hardware Offload
  4. hikari如何切换数据源_Hikari 数据源参数配置说明
  5. 81、PON网络分光器基本常识汇总,弱电人要熟知!
  6. 晓羊教育获新东方、华创资本领投近1.5亿元人民币B轮融资 打造基础教育信息化大数据新生态...
  7. 【java笔记】有序集合SortedSet和有序映射SortedMap的使用
  8. 【图像分割】基于均值聚类+OUST+区域生长法实现MRI图像分割附matlab代码
  9. preadv与pwritev
  10. 数据仓库物理分层_大数据之数据仓库分层