我正在使用OpenUI5 / SAPUI5编写测试应用程序,即使经过大量测试,优化和研究,我似乎仍然有内存泄漏。
我有几个视图,附加了一个控制器,并使用SAPUI5的SplitApp控件在它们之间导航。每当我向后导航时,我都会破坏这样的视图:
// Get current page
var sCurrentDetailPage = this.oSpiltApp.getCurrentDetailPage().getId();
// Go back
this.oSpiltApp.backDetail();
this.oSpiltApp.removeDetailPage(sCurrentDetailPage);
// Destroy current page
sap.ui.getCore().byId(sCurrentDetailPage).destroy(true);
由于我无法摆脱视图维护的所有内容,因此我在控制器的onExit函数中手动添加了对其元素的destroy调用(在销毁视图时调用onExit)。即使对视图的破坏调用也应该摧毁它的孩子,这似乎摆脱了一些更多的元素,但仍然不够。 我只使用SAPUI5提供的事件和点击处理程序,在调用destroy时应该分离,如果视图订阅了我在onExit中取消订阅的事件。
问题:
如果我创建并导航到新视图然后返回(销毁视图),则只有大约一半的内存分配似乎再次被释放。所以我会打开一个视图,回过头来看一下Chrome中的Heap Snapshot,它显示我20MB。然后我打开并关闭相同的视图5次,最终得到20.5 MB。因此,对于此特定视图,在销毁时不会删除100KB。如果应用程序整天都在使用(它本来就是这样),这可能会导致旧移动设备出现问题。 有没有人有这个问题的经验?非常感谢你。
修改
我使用Chrome时间线记录了内存使用情况。我反复创建了两个视图并再次销毁它们。对于JS Heap,我得到了以下结果:
所以它似乎随着时间的推移而大量增长。
对于节点和监听器,我得到了这个结果,这对我来说似乎没问题:
你会说这是内存泄漏还是我反应过度?这个测试甚至可靠吗?非常感谢你。
答案 0 :(得分:4)
浏览器保持内存是正常的。 JavaScript是一种垃圾收集语言,因此使对象引用无效或使用delete
键盘不会触发垃圾收集器释放该内存。
现代浏览器中的内存垃圾收集通常分两个阶段进行:
检查对象图。任何未被“全局上下文”引用的对象,例如浏览器中的window
对象标记为“陈旧”。
下次运行垃圾收集器时,所有以前“陈旧”的对象释放内存并返回供浏览器使用 - 请注意,从操作的角度来看,此内存未被“释放”系统。浏览器会在需要它们的情况下保留这些内存地址。
在释放“陈旧”对象后,浏览器再次返回步骤#1,将下一批对象标记为“陈旧”。
此外,大多数浏览器只允许垃圾收集器运行一定的毫秒数,因为在此期间浏览器中的UI在技术上没有响应,因此检查中的对象图不会在运行中变异。
内存泄漏的真正考验是利用内置的浏览器工具进行内存分析。我知道Chrome和Firefox都有此功能。其次,随着时间的推移 - 我的意思是超过10到15分钟 - 你应该看到分配给浏览器的内存的锯齿模式,其中短期趋势是上下波动的,但整体趋势是持平的。 / p>
. . . . .
. | . | . | . | . |
. | . | . | . | . |
. |. |. |. |. |
如果您看到随着时间的推移总体趋势向上的锯齿形状,那么可以表示内存泄漏。
.
. . |
. . | . |
. . | . | . |
. | . | . |.
. | . |.
. |.
真正的测试是使用浏览器附带的内置性能监控工具。