目录
- 内存管理为什么要监控??
- Performance工具使用流程
内存问题
- 产生内存问题的现象及本质
- 界定内存问题的标准
监控内存的几种方式
- 浏览器任务管理器
- Timeline时序图记录
堆快照查找分离DOM(可以观察内存泄露)
- DOM存在的几种状态?
- 实例
- 怎么处理分离DOM?
判断是否存在频繁的垃圾回收(需要用不同的工具)
- 为什么要判断?
- 具体怎么用监控判断?
这里讲到的是使用Performance
工具去进行监视内存和垃圾回收的情况,如果对内存管理,垃圾回收以及GC
不太懂的请参考文章 JavaScript —— 内存管理及垃圾回收 , 下面开始进入正题
内存管理为什么要监控?
GC
的目的是为了实现内存空间的良性循环,良性循环的基石是对内存空间合理使用。因为HTML
中没有提供内存操作的API
,所以时刻关注内存变化才能确定是否合理,我们可以通过Performance
这个工具定位问题所在,Performance
工具提供多种监控方式,可以时刻监控内存。
Performance工具使用流程
- 打开浏览器输入目标网址,这里用
Chrome
- 进入开发人员工具面板,选择性能
Performance
- 开启录制功能,访问具体界面
- 执行用户行为,一段时间后停止录制
- 获得报告,分析界面中记录的内存信息
下面的截图,可以看到内存Memory
的选项出来的折线图就表示了内存的时候情况,有升有降就是正常的工作:
内存问题
产生内存问题的现象及本质
限定当前网络问题正常的情况下:
出现的现象 | 存在的问题 |
---|---|
页面出现延迟加载或者经常性暂停 | 内存有问题,与GC 频繁的垃圾回收操作是有关联的,一定存在代码中有让内存爆掉的情况 |
页面持续性出现糟糕的性能 | 存在内存膨胀,当前界面为了达到最佳使用速度,会申请一定的内存空间,这个内存空间大小超过了上限 |
页面的性能随时间延长越来越差 | 伴随内存泄露 |
界定内存问题的标准
- 内存泄露 :内存使用持续升高
- 内存膨胀 :当前应用程序本身为了达到最优效果需要一定的内存空间,也许与当前设备本身硬件不支持有关,所以产生了性能上的差异,需要去判断是程序的问题还是设备的问题。需要多做测试,在多数设备上都存在性能问题说明程序本身有问题。
- 频繁垃圾回收 :通过内存变化图进行分析
监控内存的几种方式
浏览器任务管理器
以数值的形式将程序在执行的过程中内存的变化提现出来
在浏览器中 ->shift+Esc
-> 右键选中【JavaScript
使用的内存】
- 第一列的内存是原生内存【
DOM
节点占据的内存】,这个数据增大表示创建了新的DOM
节点。 - 最后一列
JavaScript
内存是堆内存,界面中所有可达对象正在使用的内存大小。这个数据增大表示要么在创建新对象,要么对象在不断的增长。
下面进行一下实例:
<!--创建一个长度很大的数组-->
<body>
<button id="add">Add</button>
<script>
const add = document.getElementById('add')
add.onclick = function() {
let arrList = new Array(1000000)
}
</script>
</body>
点击按钮知道内存会增大,是因为我们创建了很大的数组。之后的脚本,可以拿这个去进行监控。
Timeline时序图记录
上面的方法只能说我们的内存存在问题,但是无法更精确的定位什么时间发生的,和那些代码有关系。我们可以通过Timeline
时序图直接把当前应用程序的走势以时间点的方式呈现出来。
下面进行一下实例:
<body>
<button id="btn">Add</button>
<script>
const arrList = []
function test() {
for( let i = 0 ; i < 100000; i++) {
document.body.appendChild(document.createElement('p'))
}
arrList.push(new Array(1000000).join('x'))
}
document.getElementById('btn').addEventListener('click',test)
</script>
</body>
进入页面,打开performance
进行录制,点击三次按钮,停止录制。
可以看到内存是正常的,有升有降,降的地方就是GC
在工作了。如果没有降的地方,就是有问题的地方。
堆快照查找分离DOM(可以观察内存泄露)
堆快照是很有针对性的查找当前的界面对象中是否存在一些分离的DOM
,分离DOM
的存在也就是存在内存泄漏。
所以先搞清楚一下 什么是分离DOM?DOM存在的几种状态?
DOM存在的几种状态?
- 界面元素存活在
DOM
树上 - 垃圾对象时的
DOM
节点 ——DOM
从DOM
树上脱离了,js
里面也没有引用。 - 分离状态的
DOM
节点 ——DOM
从DOM
树上脱离了,js
里面有引用,界面上看不见,存在内存里面。
实例
下面实例看一下,下面创建了ul
和li
,这里没有在页面中呈现,但是代码中有引用,这些就是分离DOM
:
<!---->
<body>
<button id="btn">Add</button>
<script>
var tmpEle
function fn() {
var ul = document.createElement('ul')
for (var i = 0; i < 10; i++) {
var li = document.createElement('li')
ul.appendChild(li)
}
tmpEle = ul
}
document.getElementById('btn').addEventListener('click',fn)
</script>
</body>
打开浏览器 -> Memory
-> Profiles
-> Heap snapshot
-> Take snapshot
点击Add
按钮 -> Take snapshot
-> 可以看到多出来的ul
标签和li
标签,这个就是分离DOM
怎么处理分离DOM?
函数中把temEle
置为null
即可
var tmpEle
function fn() {
var ul = document.createElement('ul')
for (var i = 0; i < 10; i++) {
var li = document.createElement('li')
ul.appendChild(li)
}
tmpEle = ul
tmpEle = null
}
这个时候时候堆快照,分离DOM
就没有了。
判断是否存在频繁的垃圾回收(需要用不同的工具)
为什么要判断?
因为GC
工作时应用程序是停止的,如果当前GC
频繁工作,而且时间过长的话对Web
应用来说很不友好,会导致应用假死说我状态,用户使用中会感知应用有卡顿。
具体怎么用监控判断?
- 通过 Timeline时序图 判断,对当前性能面板中的内存走势进行监控,如果其中频繁的上升下降,就出现了频繁的垃圾回收。这个时候要定位代码,看看是执行什么的时候造成了这种情况。
- 使用 浏览器任务管理器 会简单一些,任务管理器中主要是数值的变化,其数据频繁的瞬间增加减小,也是频繁的垃圾回收。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。