Android开发者文档,作为Project Svelte的一部分(座右铭:"你曾尝试将Bugdroid装入紧身牛仔裤吗?!?"),有一个关于管理你的应用程序内存的页面.它包含:
当用户导航到其他应用并且您的UI不再可见时,您应该释放仅由您的UI使用的所有资源.此时释放UI资源可以显着提高系统缓存进程的容量,这直接影响用户体验的质量.
和:
TRIM_MEMORY_RUNNING_LOW
:您的应用程序正在运行且不被视为可用,但设备的内存运行速度要低得多,因此您应该释放未使用的资源以提高系统性能(这会直接影响应用程序的性能).
等等.
但是,如果"释放资源"实际上会以某种方式影响系统RAM,这些只会有意义.
我的印象是Dalvik VM表现得像Java VM一样(或者可能"做",如果他们在我不看的时候改变了它).AFAIK,Java VM分配系统RAM以增加堆大小但从不释放它 - 一旦分配,只要进程运行,它仍然是堆空间的一部分.
如果Dalvik VM的行为方式相同,那么我无法看到如何增加流程中未分配的堆空间量会对整体系统性能产生任何影响.现在,为我们的进程释放堆空间是一件好事,也许这样做会降低我们将来需要更多系统RAM的可能性......但这不是文档所暗示的.文档指出"此时释放UI资源可以显着提高系统缓存进程的容量"; 它没有说"此时释放UI资源没有立竿见影的效果,但将来有助于减少应用程序的系统RAM占用空间".
现在,如果指令告诉我们释放通过NDK分配的内存,那将是有意义的,因为它发生在Dalvik堆之外并且会影响系统RAM.但是文档没有得出这种区别.
除了终止进程之外,Dalvik VM是否实际将已分配的RAM释放回系统?如果是的话,何时?而且,在较小的程度上,考虑到垃圾收集器是非压缩和非复制的,它是如何完成的?
谢谢!
是.基本思想是,如果有一个没有任何内容的4K页面,该页面将返回到系统.
trimHeaps()
在dalvik/vm/alloc/HeapSource.cpp中调用在VM中执行此操作的函数.您可以使用它来查看它mspace_trim()
,它使用OS调用来取消不再需要的块(请参阅malloc.c中第1203行附近的malloc_trim()注释).然后它遍历堆mspace_inspect_all()
,调用releasePagesInRange()
每个区域.回调测试是否传递了一个没有分配的区域,如果是,则将边界截断为4K对齐.如果结果不为空,我们知道该区域跨越一个或多个物理4K页面,可以将其返回给系统madvise(MADV_DONTNEED)
.
trimHeaps()
从几个地方调用,最值得注意的是gcDaemonThread()
,它将在并发GC后五秒启动调整.如果并发GC在五秒钟之前发生,计时器将被重置,这个想法是,如果我们正在进行GC操作,那么VM正忙着分配,这种空闲时间修剪将适得其反.
由于Dalvik GC不进行压实,因此效果不尽如人意.碎片往往随着时间的推移而逐渐增加,因此流程持续的时间越长,情况就越糟糕.应用程序框架可以"回收"长期服务以缓解这种情况.