春困秋乏,想正经写篇blog都难,可有良方奉上?
首先我们对本篇进行概括,将分以下几点讲解:
1、断电以及捕捉事件绑定
2、Audits和Chrome性能插件
3、Timeline掌控帧渲染模式
4、Profiles分析NodeJS内存泄露问题
概要:
(1)断点
(2)寻找事件监听
(3)DOM元素断点
说道打断点,js编辑器中似乎听说的只有MS 的 Visual Studio,这傻X,MS从来没抛弃它~
(1)基本断点
新建一个debug.html文件:
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<label for="email">Email:</label>
<input type="email" id="email"/>
<button type="button" id="btn-test" class="btn btn-success">测试</button>
<div id="test-div">
一段文字
</div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript"> $("#btn-test").click(function(){ var val=$("#email").val(); alert(val); }); </script>
</body>
</html>
然后我们进行调式,审查元素:
在这里我们定位需要调式的DOM元素,然后查看该元素绑定的事件监听Event Listeners.
我们在这里可以找到对应的事件监听,由此我们定位到具体的执行函数。
(2)DOM断点调式
接着,我们再来看一个案例:
代码如下:
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<label for="email">Email:</label>
<input type="email" id="email"/>
<button type="button" id="btn-test" class="btn btn-success">测试</button>
<div id="test-div">
一段文字
</div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript"> $("#btn-test").click(function(){ var val=$("#email").val(); alert(val); $("test-div").remove();//添加一个remove事件 }); </script>
</body>
</html>
如图:
我们在相应的DOM节点上打上事件断点,右击DOM,选择Break On.有三种选项:
(1)Subtree Modifications:表示监听所选择的DOM的子节点的事件,当该节点的子节点发生变化,就会打上相应的断点进行调式;
(2)Attributes Modifications:表示监听所选择的DOM的属性,当该DOM的属性发生变化的时候,就去打断点监听调式;
(3)Node Removal:表示监听该DOM的remove()事件,当该DOM被移除的时候,就会触发;
如下图所示:
由于我们对id=”test-div”执行的是remove()事件,所以,在该div打上一个Node Removeal断点的时候,当执行到这里,就会跳入断点调式,找到调用的remove事件的具体方法。这就是基于DOM的断点调式。
说道性能分析工具,可谓层出不穷。但是Chrome自带的插件也很强大了,特别是Chrome看不惯Firefox,在小小的DevTool中内插了巨多功能。这是要上天了~
Audits就是性能分析插件,类似雅虎军规。能够根据性能优化规则对你的网站提出优化意见。
Chrome性能插件有:
(1)Page Speed
(2)performance.timing(API):能够捕捉网页从输入到输出的一个过程,例如DNS、TCP、Request、Response(在做性能优化时,常常关注这几个点)时间。
如图:该图完整阐述了网页从输入到输出的一个过程。
来看一个例子:
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" scr="test.js"></script>
</head>
<body>
<label for="email">Email:</label>
<input type="email" id="email"/>
<button type="button" id="btn-test" class="btn btn-success">测试</button>
<div id="test-div">
一段文字
</div>
<script type="text/javascript"> $("#btn-test").click(function(){ var val=$("#email").val(); alert(val); $("#test-div").remove(); }); </script>
</body>
</html>
这段代码中,我们引用了两个cdn文件和一个外部test.js文件,这3个文件都会对页面的加载产生阻塞。
然后我们使用Audits来调式一下:
如图:
点击Run。于是,我们会看到如下图结果:
Audits就会根据相应规则做出意见.
但是,Audits在视觉上得表现并不是那么好。所以,我们再来看看另一个插件:pageSpeed。(注意:运行pageSpeed需要在服务器环境下)如图:
但是,pageSpeed还是不能满足专业的性能优化,这时候performance.timing就出现了,performance.timing 是一个API,接口中包含了当前页面中与时间相关的信息。
操作:
在你要测试的页面,打开控制台输入window.performance,即可看到timing信息:
如图:
具体你可以参考:
https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceTiming
需要注意的是:
在性能优化的时候,你需要理解这张图,这里也是对window.performance每个属性的具体定义。我们再次来回顾下前面提到过的这张图:
你需要理解DNS、TCP三次握手、请求与响应时间等等,如果要做到极致的话,你还可以去了解负载均衡等服务器端的知识。
上面我们介绍了Audits和Page SPeed以及performance.timing API。在实际的优化的过程中,通常我们会将以上几个工具进行配合使用。例如:可以先用Audits进行一个初步的判断,然后用Page Speed对问题进行具体的查看。
看了辣么久,是不是不赖烦了,真的很烦啦。我们来看看内涵图:
网页动画能够做到每秒60帧,就会跟显示器同步进行刷新,一秒之内进行60次重新渲染,每次重新渲染的时间不能超过16.66毫秒(1s/1000=16.66毫秒)。
如果让浏览器的刷新与显示器的刷新同步,那么就会变得很流畅。
在Timeline帧渲染的过程中,会产生以下几种颜色:
(1)蓝色:网络通信和HTML解析
(2)黄色:javascript执行
(3)紫色:样式计算和布局,即重排
(4)绿色:重绘
(5)两个函数:window.requestAnimationFrame()下一次重新渲染时,
以及window.requestIdleCallback()下几次重新渲染时。这两个函数能够加快帧的渲染。我们可以对卡顿的帧执行这样的操作。
window.requestAnimationFrame:表意为请求动画帧。
写法:
$(window).on('scroll',function(){
window.requestAnimationFrame(scrollHandler);
})
参考:CSS3动画那么强,requestAnimationFrame还有毛线用?
window.requestIdleCallback():哪几帧空了,就加速那几帧的渲染。
(1)获取DOM并将其分割为多个层(联想到:photoshop中的分层);
(2)将每个层独立的绘制进位图中;
(3)将层作为纹理上传至GPU;(层在GPU中如果不变,也会缓存)
(4)复合多个层来生成最终的屏幕图像。
具体过程:
(1)DOM子树渲染层(RenderLayer)–(对应)->RenderObject–(对应)->GraphicsContext(根元素、position、transform、半透明、CSS滤镜、Canvas2D、video、溢出,这些都会产生层,这些发生在CPU中)
如果需要GPU参与,则需要如下合成:
(2)(正常渲染,写一遍画一遍)Compositor->渲染层子树的图形层(GraphicsLayer)–>RenderLayer–>RenderObject
Compositor将所有的拥有compositing layer进行合成,合成过程GPU进行参与。合成完毕就能够将纹理映射到一个网格几何结构之上——在视频游戏或者CAD程序中,这种技术用来给框架式的3D模型添加“皮肤”。Chrome采用纹理把页面中的内容分块发送给GPU。纹理能够以很低的代价映射到不同的位置,而且还能够以很低的代价通过把它们应用到一个非常简单的矩形网格中进行变形。这就是3D CSS的实现原理啦。
(能够触发合层的:CSS 3D透视变换、video、webGL、transform动画、加速CSS滤镜、叠加在已经触发合成层,这些发生在GPU中)
网页生成的时候,至少会渲染一次。用户访问的过程总还会不断重新渲染。以下三种情况,会导致网页重新渲染:
(1)修改DOM
(2)修改样式表
(3)用户事件
注释:
重新渲染,就需要重新生成布局(俗称“重排”reflow)和重新绘制(俗称“重绘”repaint)。
需要注意的是:
“重绘”不一定需要“重排”,比如改变某个网页元素的颜色,就只会触发“重绘”。因为布局没有改变,所以没有触发“重排”。
但是,“重排”必然导致“重绘”,比如改变一个网页元素的位置,就会同时触发“重绘”和“重排”,因为布局改变了。
(1)样式表越简单,重排和重绘越快;(OOCSS)
(2)重排和重绘的DOM元素层级越高,成本越高;
(3)table元素的重排和重绘成本,要高于div元素;
(4)尽量不要把读操作和写操作放在一个语句里面;
(5)统一改变样式;
(6)缓存重排结果;
(7)离线DOM Fragment/clone
(8)虚拟DOM React
(9)必要的时候display:none不可见元素不影响重排重绘。visibility对重排影响不影响重绘。
达到高效的原则:
影响重绘,但不影响重排,而且能让GPU参与。
同时,需要深刻理解“层”的概念。
书籍推荐:WebKit技术内幕
Nodejs内存泄露问题——严重可导致CPU、服务器爆表;
Nodejs引起的内存泄露问题来源以及解决方法:
(1)全局变量需要进程退出才能释放;
(2)闭包引用中间函数,中间函数也不会释放。
所以,使用过后重置为NuLL等待垃圾回收。
(3)谨慎使用内存当做缓存,建议采用Redis或者Memcached.
好处:外部缓存软件有着良好的缓存过期淘汰策略以及自有的内存管理,不影响Node主进程的性能。减少内部常驻内存的对象数量垃圾回收更高效率,进程间共享缓存。
OK,就到这里啦~
http://www.biaodianfu.com/html5-performance.html
http://www.jb51.net/css/125615.html 浏览器实现移动端高性能css3动画(开启gpu加速)