【问题标题】:Minimizing memory allocations with handlers, messages, and bundles使用处理程序、消息和包最小化内存分配
【发布时间】:2011-09-03 03:16:29
【问题描述】:

我有一个activity,它不断(每秒几次)通过 AIDL 将byte[] 数据发送到serviceservice 使用message-bundle* 将这些消息转发到网络线程的handler。网络线程也不断地接收数据,它以message-bundle 的形式发送到servicehandlerservice 通过 AIDL 将此 bundle 发送给其他 activities

如您所知,为bundles 分配了大量内存。

在 DDMS 上查看我的内存分配后,我看到内存分配给:

  • bundle 正在初始化
  • 正在创建的哈希映射
  • byte[] 数据作为条目添加到哈希表中

我想尽可能少地减少内存分配。

有没有更好的方式在活动/线程之间发送字节[],而不是通过带有捆绑包的消息?

*通过message-bundle,我的意思是messagebundle 作为数据

尝试:创建一个 bundle 对象池,但效果不太好 - 很难在活动之间进行管理,而且我不知道如何使用 byte[] 数据预分配它...

【问题讨论】:

  • 我不这么认为,但我不是安卓专家;如果有办法,那么这对我的 Android 应用程序来说意义重大。当然,您可以尝试回收您创建的对象。就像带有 Singleton 回收类的字节缓冲区一样。
  • 这就是我所说的回收 btw 的意思。获取和释放只是 POJO 的资源:@​​987654321@

标签: android memory-management


【解决方案1】:

你真的需要担心那些字节数组那么大吗?在不了解您的应用程序的情况下,我猜您所描述的应用程序的瓶颈将在网络处理程序中,而不是服务和活动之间的消息传递。除非您在某处泄漏 Bundle,否则 GC 应该处理所有未使用的内存并将其恢复以供您的应用重用。

如果有的话,我会尽量保持这些数组足够小(以避免一次分配和回收大量内存)并改为发送几条小消息。这样,应用程序不会一次性消耗所有可用内存,而是让 GC 以宽松的时间表(即 CPU 空闲时)完成其工作,而不是强制 GC 立即收集对象。

当然,什么是“太大”或“足够小”是您应该在自己的应用程序中测试的内容,并衡量通过一种或其他方法获得的收益(如果有的话)。

更新:

an android dev site article逐字复制:

在性能敏感的代码路径中,例如视图的布局或绘制方法或游戏的逻辑代码,任何分配都是有代价的。在分配过多之后,垃圾收集器将启动并停止您的应用程序以释放一些内存。大多数情况下,垃圾收集发生得足够快,以至于您不会注意到。但是,如果在您滚动浏览项目列表或尝试在游戏中击败敌人时收集,您可能会突然发现应用程序的性能/响应能力下降。 垃圾收集需要 100 到 200 毫秒的时间并不罕见。相比之下,流畅的动画需要在 16 到 33 毫秒内绘制每一帧。如果动画突然中断 10 帧,您可以确定您的用户会注意到。

根据您的评论,我会重新考虑 GC 是否与您的情况相关。堆限制may vary between 16 and 32 MB(并且上限可能正在增长)。假设每秒分配 10 次,每次分配 64 字节,您将每 30 分钟(大约)分配 1 MB。如果 GC 需要 200 毫秒来释放该内存,则效果可以忽略不计。我知道这里的数字不考虑哈希映射或捆绑所需的内存,但它们仍然有助于让您了解我们正在谈论的数量级。现在,考虑网络请求从网络获取这 64 个字节的时间。即使它只需要 50 毫秒,也就是 GC 所需时间的 1/4 到 1/2,每个网络请求。这甚至不考虑您的 Activity 处理该数据所需的时间。

因此,总而言之,在重组代码以尝试提高其效率之前,请确保您正在修改的步骤实际上是一个瓶颈,否则您的所有努力都可能白费。只是我的 0.02 美元。

【讨论】:

  • 字节数组的大小为 [64]。原因是它们包含可变数量的数据
  • 感谢您的帮助。我想我会更多地研究分析我的代码以找到我可以改进的瓶颈。
【解决方案2】:

我经常在嵌入的东西上使用池,几乎正是出于这个原因——提供一些“流控制”,(如果池是空的,一个线程必须等待它,直到从其他地方释放消息),并且防止失控的 malloc/new 耗尽我所拥有的小堆。如果每个池化消息都包含对其池的私有引用,则管理池会更容易。这意味着活动/线程不需要将任何池引用显式传递给它以使其能够将消息释放回池 - 消息的“释放”方法可以在没有任何参数的情况下执行此操作,如果对于某些由于存在多个池,因此没有将消息释放回错误池的危险。

Rgds, 马丁

【讨论】:

  • 我认为私人参考的想法很有用。有时间我会试试看的。
猜你喜欢
  • 1970-01-01
  • 2010-10-17
  • 2012-05-31
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2012-12-05
  • 1970-01-01
  • 2021-08-27
相关资源
最近更新 更多