5

所以,我在读这个:http ://www.ibm.com/developerworks/java/library/j-jtp09275/index.html ,上面写着:“公共服务公告:对象池现在对除了最重量级的对象,即使这样,在不引入并发瓶颈的情况下正确处理也是很棘手的,”并从表面上看。文章讨论了分代 GC、释放、线程局部分配和逃逸分析。

然而,我脑子里只有一点声音问我,“但是Android中的垃圾收集器实现是这样吗?” 我不知道答案。我什至不知道如何去寻找答案。

我记得当我为经常使用的小对象实现池时,GC 在我的 android 应用程序中运行的频率降低了。不确定这是否意味着更快的应用程序。此外,GC 在没有池的情况下运行得更频繁(根据 logcat),所以我假设 Android 的 GC 实现输给了池。但是这个假设几乎没有支持,因为我没有注意到有或没有汇集的任何显着的性能差异。

所以..这里的任何人都知道对于经常使用的小对象,池化是否比 Android 的 GC 更有效?

4

2 回答 2

5

这里的任何人都知道对于经常使用的小对象,池化是否比 Android 的 GC 更有效?

这取决于您如何衡量“高效”、“小”和“经常”。

对象池在 Android 本身的多个地方使用,例如:

  • (和 kin)的整个Adapter框架是围绕对象池设计的,这次是针对相对重量级的对象(例如,一行很容易达到几十 KB)AdapterViewListViewListView

  • SensorEvent对象被回收,这次是每秒可能使用数十次的轻量级对象

  • AttributeSet作为View通货膨胀的一部分,物体被回收

等等。

其中一些基于早期 Android 版本中的 Dalvik 早期版本,当时我们的目标是使用纯解释语言和相当幼稚的 GC 引擎的 100MHz 以下 CPU。

然而,即使在今天,对象池除了即时性能之外还有一大优势:堆碎片。

Java 的 GC 引擎是一个压缩垃圾收集器,这意味着空闲堆空间的连续块被组合成更大的块。Dalvik 的 GC 引擎是一个非压缩垃圾收集器,这意味着您分配的块永远不会成为更大块的一部分。这就是许多开发人员对位图管理感到困惑的地方——OutOfMemoryError他们得到的不是因为堆空间不足,而是由于堆碎片,堆没有足够大的块来进行所需的分配。

对象池避免了堆碎片,只需防止池中的对象再次被垃圾收集,并且不经常为池分配新对象(仅当池由于同时使用过多而需要增长时)。

游戏开发者早就在 Android 中使用了对象池,起源于 Android 的垃圾收集是非并发的,在进行 GC 时“停止了世界”。现在,大多数 Android 设备都使用并发垃圾收集器,这减轻了一些痛苦。

因此,对象池绝对仍然是一项相关技术。不过,大多数情况下,我会将其视为对检测到的问题的反应(例如,Traceview 在 GC 中显示太多时间,Traceview 在对象构造函数中显示太多时间,MAT 表明您有足够的堆但您得到OutOfMemoryErrors)。游戏开发是个例外——游戏开发人员可能有自己的启发式方法,以了解现代 Android 设备仍然需要池化的情况。

于 2013-06-13T23:34:16.687 回答
2

你的推理存在谬误。更频繁地运行 GC 并不表示性能有所下降。那些更频繁的 GC 运行也可能比那些不得不通过对象池的不太频繁的运行更快且寿命更短。

也就是说,我做了一些研究,这里有一些想法……几年前,我的手机只有一个核心。运行 GC 意味着从活动切换到 GC 线程。即使有并发 GC 和多核(现代设备有 2-5 个 afaik),也可能会有轻微的停顿。

建议预先分配用户可能需要的下一个交互序列的所有内容,作为游戏的一个好主意。基本上遵循实时应用程序的口头禅,与在应用程序的用户体验部分具有一致的可测量性能相比,它们不太担心整体性能。

http://developer.android.com/training/articles/perf-tips.html

于 2013-06-13T23:07:21.260 回答