当前位置: 首页 > 知识库问答 >
问题:

小对象池是否比Android的Java垃圾收集器更高效?

邬宏扬
2023-03-14

所以,我读了这篇文章:http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html说,“公共服务公告:对象池现在对除了最重量级的对象之外的所有对象来说都是一个严重的性能损失,即使这样,在不引入并发瓶颈的情况下进行正确的处理也是很棘手的”,并从表面上看。这篇文章讨论了代GC、释放、线程本地分配和转义分析。

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

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

因此...这里有人知道对于经常使用的小对象,池是否比Android的GC更有效吗?

共有2个答案

严高峻
2023-03-14

你的推理有谬误。GC运行得更频繁并不表示性能有所下降。那些更频繁的GC运行也可能比那些必须在对象池中混匀的不太频繁的GC运行更快,寿命更短。

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

建议预先分配用户在下一系列交互中可能需要的所有内容是游戏的一个好主意。本质上遵循实时应用程序的口头禅,与在应用程序的用户体验部分期间具有一致的可衡量性能相比,这些应用程序不太担心整体性能。

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

饶骁
2023-03-14

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

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

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

>

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

属性集(AttributeSet)对象被回收,作为视图(View)的一部分

等等。

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

然而,即使在今天,对象池还有一个超越即时性能的巨大优势:堆碎片。

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

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

游戏开发者长期以来一直在Android中使用对象池,这源于Android的垃圾回收机制是非并发的,当GC进行时“停止世界”。现在,大多数Android设备都使用并发垃圾收集器,这在一定程度上减轻了这里的痛苦。

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

 类似资料:
  • 有人能给我解释一下原因吗?

  • [GC(分配失败)[defnew:10931K->472K(12288K),0.0053905秒]10931K->10712K(39616K),0.0054285秒][times:user=0.00 sys=0.00,real=0.01秒] [GC(分配失败)[defnew:10712k->472k(12288k),0.0057686秒]20952k->20952k(39616k),0.00580

  • 每个java开发人员都知道,java对象不再使用时将被垃圾收集。我想知道JVM如何识别必须为垃圾收集选择的对象。(例如,如果我有10个对象。如果对10个对象中的2个进行垃圾收集,jvm将如何找到这两个对象)。 JVM使用标记和扫描算法(如果我是对的)。 1)例如我在下面提供字符串对象场景 //现在s1

  • 问题内容: 该问题已发布在某个网站上。我在这里找不到正确的答案,因此我将其再次发布在这里。 我的查询与停止线程无关。让我改一下我的问题。A行(请参见上面的代码)启动一个新线程;和B行使线程引用为空。因此,JVM现在具有一个线程对象(处于运行状态),该对象不存在引用(如B行中的t = null)。所以我的问题是,为什么这个线程(在主线程中不再有引用)一直保持运行状态,直到主线程运行。根据我的理解,线

  • 问题内容: 有没有一种方法可以检查垃圾收集器是否可以提取对象? 在我的代码中的某个地方,我有一个对象的引用: 然后,通过Eclipse Debugger,获得对象的存储位置。之后,我将引用设置为null: 有什么方法可以检查以前引用的对象现在是否适合垃圾回收,或者是否有其他引用? 非常感谢, 斯特凡 问题答案: 您无法在运行时使用任意对象执行此操作,实际上,不可能完全确定地执行此操作。但是,有两种

  • 问题内容: 我知道当分配DirectbyteBuffer时,它不受垃圾回收的限制,但是我想知道的是 包装 对象是否被垃圾回收了。 例如,如果我分配了一个新的DirectByteBuffer dbb,然后使用dbb.duplicate()将其复制(浅复制),则我将在同一块内存中使用两个包装器。 这些包装器是否要进行垃圾收集?如果我做了 我最终会自己OOM吗? 问题答案: 在Sun JDK中,由创建的