实战Hybird app:内存溢出与优化

简介:

主要的问题:

heap过大,内存低性能差的机子上引起奔溃,直接退出

关于web app的优化,不仅仅只是js方面,包括HTML布局嵌套,CSS的属性使用,数据的读取,还有浏览器的重排与回流之类的这里就不讨论了,

本章涉及的是脚本代码引发的性能问题,更进一步说就是闭包带来的内存泄露

 


关于性能:

首先我不得不承认一个事实,移动端的性能跟PC端,那完全不是一回事

比如用innerHTML绘制大段的HTML结构,之后同步获取生成HTML中的ID节点,结果不存在

这种问题在单页面模拟多页面,动态创建DOM的时候,尤为明显

var element   = $('<div id = "aaron">...填充大量结构...</div>');

$(root).html(element)

$('#aaron')  //为空
  • 这个是很简单的一段代码,按照常规的认识,JS主线程与GUI的渲染线程是互斥的,所以在执行JS的时候,GUI应该就是挂起的, 同理执行GUI的时候亦然, 因为JS可以动态操作节点,所以如果我们在GUI绘制的时候做操作明显就会打乱了,所以互斥的解释也合理
  • 但是实际上这样并不能直接获取到$('#aaron'),PC上基本不会出现,常规的办法都是加setTimeout
  • 实际上由于setTimeout的机制,所以也是不准确的,当然我已经有一个比较完美的方式解决

 


关于JavaScript内存管理:

原文:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

JavaScript会给开发者一个错觉:可以不用考虑内存管理

现代浏览器已经够聪明了,从2012年起,所有现代浏览器都使用了标记-清除垃圾回收算法。所有对JavaScript垃圾回收算法的改进都是基于标记-清除算法的改进,并没有改进标记-清除算法本身和它对“对象是否不再需要”的简化定义。

所以引用计数收集与循环引用之类的都不再是问题了,过去导致内存泄漏的许多经典模式在现代浏览器中以不再导致泄漏内存。

但是,如今有一种不同的趋势影响着内存泄漏。许多人正设计用于在没有硬页面刷新的单页中运行的 Web 应用程序。在那样的单页中,从应用程序的一个状态到另一个状态时,很容易保留不再需要或不相关的内存。

典型的就是: 单页面模拟多页面的行为

 


简单的内存管理测试

视图:

image

HTML结构:

<button id="start_button">Start</button>
<button id="destroy_button">Destroy</button>

脚本代码:

复制代码
var Leaker = function() {
    this.name = 'aaron'
};

$("#start_button").click(function(){
 leak = new Leaker();
});

$("#destroy_button").click(function(){
  leak = null;
});
复制代码

点击Start  产生一个对象leak new Leaker();

点击Destroy 销毁这个对象 观察下内存中变化(工具后面会提到)

点击Start ,产生一个对象

image

 

点击Destroy,对象销毁

image

那么这个图很形象的说明了,#Delata释放了一个实例,就是内存被回收了

如果不做任何处理,那么这个对象leak始终最存在整个生命周期内(全局上下文的情况)

如果leak null,内存确实是由浏览器GC 自动给回收了

 

闭包引起的内存泄漏:

代码:内部增加了一个定时器,递归调用

复制代码
var count = 0;

var Leaker = function(){};

Leaker.prototype = {
    init:function(){
        this._interval = null;
        this.start();
    },

    start: function(){
        var self = this; //递归调用自身
        this._interval = setInterval(function(){
            self.onInterval();
        }, 100);
    },

    destroy: function(){
        if(this._interval !== null){
            clearInterval(this._interval);
        }
    },

    onInterval: function(){
        count++;
        console.log("Interval",count);
    }
};
复制代码

 

从样的观察

我在按了销毁,leak = null了

可见代码依然还在走,可见此时内存绝对的溢出了,也就是失控了

image

 

但是监视器显示该对象回收了

image

那么这个问题就很明显了,通过leak = null 销毁的只是引用,内部如果还存在引用的话,这个heap是不会被回收的

此时这个内存我们已经管理不到了,会一直递归下去

要解决只能在销毁的时候先停止定时器了

 

由此可见,引用不仅仅只是外部的, 内部同样存在这样的问题,当然引用类型的机制本来就是这样的

 

所以在日常的代码编写方面,JS的坑确实不少,接下来看看我项目中的大坑吧!!!


 

应用截图:

9_T`B{QZZKGCVJHU@0E[]S2image

 

内存使用检测:

Eclipse

image

 

Eclipse不熟悉的路过,我们还是回到前端的角度去处理

使用Chrome DevTools的Timeline和Profiles提高Web应用程序的性能

 

具体的使用就不介绍了,大家接着看

抓怕的heap快照,实时反馈的信息

系统的闭包数

image

 

加上JQuery

image

 

项目中的

image

 

视图解释

列字段解释:

Constructor -- 构造器

Distance -- 估计是对象到根的引用层级距离

Objects Count -- 给出了当前有多少个该类的对象

Shallow Size -- 对象所占内存(不包含内部引用的其它对象所占的内存)(单位:字节)

Retained Size -- 对象所占总内存(包含内部引用的其它对象所占的内存)(单位:字节)

 

小伙伴都吓呆了

项目中除去系统与一些插件的,至少有上千个闭包

 

分析堆快照

image

Object's retaining tree视图显示出了该对象被哪些对象引用了,以及这个引用的名称

 

关于XUTUTIL.Event类

XUTUTIL.Event是一个构函数函数,主要就是一个订阅/发布模式

那么这个图我的理解就是通过XUTUTIL构造生成的的对象都应该是放到这个里面,所以

根据分析图显示,这个类有208个对象,被实例了208次,也就是说存在这么多订阅者了

XUTUTIL部分源码(观察者模式)

XUTUTIL.Event

如图me.events[eventName]标记,是数组保存了观察对象了

 


点击图中的黑色实心圆圈按钮,即可得到第二个内存快照:

点击图中的“Summary”,可弹出一个列表,选择“Comparison”选项,然后选择对比第一个,结果如下图:

image

这个视图列出了当前视图与上一个视图的对象差异。

列名字段解释:

# New -- 新建了多少个对象

# Deleted -- 回收了多少个对象

# Delta -- 对象变化值,即新建的对象个数减去回收了的对象个数

ALLOC -- 变化的内存大小(字节)注意Delta字段,尤其是值大于0的对象

 

很明显翻一页就创建大量的观察对象

image

*注:因为是单页面应用,动态多页面的翻页算法,比如当前是从第2页到第3页,其实是预先创建第4页面,销毁第1页,保留234页,所以这个+14,不是这样算的

 

但是第一个很明显的问题就出来,为什么要动态创建这么多的观察对象,找到代码来源

image

 

找到问题了

注册了大量的观察者模式

image

 

销毁的代码,没有处理注销观察者事件

image

 

啪啪啪啪。。。。一阵修改之后

翻页的时候不处理了

image

 

在进入页面初始化的时候208变成18个了。。。在看看内存占用。。。45016---3240

PC上的消耗,在移动端就会被放大的,所以不要放过过任何一个可优化的地方

修改前

image

修改后

image

因为这个案例比较明显,还有的问题,要靠自己慢慢去分析引用情况了

 

那么很明显了:观察者模式引起的内存泄漏

需要观察者模式(Observer)来解藕一些模块,但如果使用不当,也会带来内存泄漏的问题。

排查这类型的内存泄漏问题,主要重点关注被引用的对象类型是闭包(closure)和数组Array的对象。

1.如果能避免观察模式的使用,就尽量避免,

2.避免不了一定要记得清理

 


总结出以下几种常见的情况:

1.闭包上下文绑定后没有释放;

2.观察者模式在添加通知后,没有及时清理掉;

3.定时器的处理函数没有及时释放,没有调用clearInterval方法;

4.视图层有些控件重复添加,没有移除。

 

本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/p/3403374.html,如需转载请自行联系原作者

相关文章
|
4月前
|
存储 算法 Java
Java内存管理深度剖析与优化策略####
本文深入探讨了Java虚拟机(JVM)的内存管理机制,重点分析了堆内存的分配策略、垃圾回收算法以及如何通过调优提升应用性能。通过案例驱动的方式,揭示了常见内存泄漏的根源与解决策略,旨在为开发者提供实用的内存管理技巧,确保应用程序既高效又稳定地运行。 ####
|
5天前
|
缓存 NoSQL Linux
Linux系统内存使用优化技巧
交换空间(Swap)的优化 禁用 Swap sudo swapoff -a 作用:这个命令会禁用系统中所有的 Swap 空间。swapoff 命令用于关闭 Swap 空间,-a 参数表示关闭 /etc/fstab 文件中配置的所有 Swap 空间。 使用场景:在高性能应用场景下,比如数据库服务器或高性能计算服务器,禁用 Swap 可以减少磁盘 I/O,提高系统性能。
25 3
|
4月前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
180 62
|
4月前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
94 31
|
3月前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
204 3
|
3月前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
279 7
|
3月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
103 5
|
4月前
|
传感器 iOS开发 UED
探索iOS生态系统:从App Store优化到用户体验提升
本文旨在深入探讨iOS生态系统的多个方面,特别是如何通过App Store优化(ASO)和改进用户体验来提升应用的市场表现。不同于常规摘要仅概述文章内容的方式,我们将直接进入主题,首先介绍ASO的重要性及其对开发者的意义;接着分析当前iOS平台上用户行为的变化趋势以及这些变化如何影响应用程序的设计思路;最后提出几点实用建议帮助开发者更好地适应市场环境,增强自身竞争力。
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
102 1
|
4月前
|
JSON JavaScript 前端开发
harmony-chatroom 自研纯血鸿蒙OS Next 5.0聊天APP实战案例
HarmonyOS-Chat是一个基于纯血鸿蒙OS Next5.0 API12实战开发的聊天应用程序。这个项目使用了ArkUI和ArkTS技术栈,实现了类似微信的消息UI布局、输入框光标处插入文字、emoji表情图片/GIF动图、图片预览、红包、语音/位置UI、长按语音面板等功能。
315 2

热门文章

最新文章

  • 1
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
  • 2
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力
  • 3
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 5
    【Azure App Service】基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?
  • 6
    【Azure Function】Function App出现System.IO.FileNotFoundException异常
  • 7
    1688APP 原数据 API 接口的开发、应用与收益
  • 8
    PiliPala:开源项目真香,B站用户狂喜!这个开源APP竟能自定义主题+去广告?PiliPala隐藏功能大揭秘
  • 9
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 10
    语音app系统软件源码开发搭建新手启蒙篇