使用处理程序,消息和包最小化内存分配

时间:2011-05-27 05:18:23

标签: android memory-management

我有activity不断(每秒几次)通过AIDL将byte[]数据发送到serviceservice使用message - bundle *将这些消息转发给网络主题handler。网络线程也不断接收数据,并将其作为service - handler发送给message的{​​{1}}。 bundle通过AIDL将此service发送给其他bundle

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

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

  • 正在初始化bundles
  • 正在创建的哈希映射
  • 我添加的bundle数据作为哈希表的条目

我想尽量减少内存分配。

是否有更好的方式跨活动/线程发送byte []而不是通过包有消息的消息?

* byte[] - message ,我的意思是bundle,其中message为数据

尝试:制作一个bundle个对象池,但效果不好 - 难以在活动之间进行管理,我不知道如何使用bundle预分配它数据...

2 个答案:

答案 0 :(得分:3)

这些字节数组是否真的需要担心?在不知道你的应用程序的任何内容的情况下,我猜你所描述的app中的瓶颈将出现在网络处理程序中,而不是服务和Activity之间的消息传递。除非您在某处泄漏Bundles,否则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 ms才能释放该内存,效果可以忽略不计。我知道这里的数字不考虑哈希映射和包所需的内存,但它们仍然与您了解我们正在谈论的数量级有关。现在,考虑网络请求从网络中获取这64个字节的时间。即使它只需要50毫秒,这是GC所需时间的1/4到1/2,每个网络请求。这甚至没有考虑您的活动处理该数据所需的时间。

因此,总而言之,在重构代码以提高其效率之前,请确保您修改的步骤实际上是瓶颈,或者您的所有努力都可能被浪费。只需我0.02美元。

答案 1 :(得分:1)

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

RGDS, 马丁