前言

上周我与阿里的宇果有一次技术的交流,然后对天猫H5站点做了一些浅层次的分析,后面点时间基本天天都会有联系,中途聊了一些技术细节、聊了双方团队在干什么,最后聊到了前端优化。因为我本身参与了几次携程H5站点的优化,在这方面有一些心得,但是与宇果交流的过程中发现我们在优化的时候忽略了一些细节。

携程做优化的时候整个重心基本放到了尺寸的缩减,和宇果的交流过程中他提出了渲染优化,其实渲染优化无非是减少回流,对于减少回流我们也有一些概念,我一直认为这个事情应该业务开发关注而不是框架关注(事实上框架也无法关注),所以对一些BUG采取了表现层面的解决,却对真相视而不见的做法,现在想来真的有点无知,这里便以一个原来的渲染BUG为切入点,将最近与宇果的交流所得整理下。

宇果博客:http://www.ghugo.com/

回流与重绘

首先,我们再次复习一下回流与重绘的知识,浏览器会解析三个东西:HTML、Javascript、CSS。

浏览器首先会根据HTML生成DOM Tree,其次会根据CSS生成CSS Rule Tree,javascript可以通过DOM API与CSS API操作DOM Tree与CSS Rule Tree,从而引起页面变化。

浏览器解析结束会通过DOM Tree与CSS Rule Tree形成render tree,只有display不为none的元素才会形成render Tree,render Tree形成后浏览器会调用GUI绘制页面,在此之前做的一件事情便是layout或者说reflow。上面的描述简单而言可以分为以下流程:

l  生成DOM树

l  计算CSS样式

l  构建render tree

l  reflow,定位元素位置大小

l  绘制页面

在这个过程中,若是javascript动态改变DOM Tree便会引起reflow

页面中的元素改变,只要不影响尺寸,比如只是颜色改变只会引起repaint不会引起回流

否则,reflow不可避免,这个时候便需要重新计算形成render Tree

reflow分为局部回流与全局回流,会影响下面的,不会影响上面的元素

reflow耗用的系统资源较大,DOM Tree中受到影响的节点皆会reflow,然后影响其子节点最坏的情况是所有节点reflow,该问题引发的现象便是低性能的电脑风扇不停的转,手机变得很热,并且非常耗电,以下操作可能引起reflow

l  操作dom结构

l  动画

l  DOM样式修改

l  获取元素尺寸的API

android大屏手机渲染BUG

这个是我们一个tab组件,这个组件按道理说非常简单:

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
<title></title>
<style type="text/css">
body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; } ul, ol { list-style: none; margin: 0; padding: 0; } .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; } .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; } .cui-tab-mod li.cui-tab-current { color: #099fde; } .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease-in-out; -moz-transition: -moz-transform 300ms ease-in-out; -ms-transition: -ms-transform 300ms ease-in-out; transition: transform 300ms ease-in-out; z-index: -1; } .cui-tabnum2 { width: 50%; } .cui-tabnum3 { width: 33.33333%; } .cui-tabnum4 { width: 25%; } .cui-tabnum5 { width: 20%; } .cui-tabnum6 { width: 16.66666%; } .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; } .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); } .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); } .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); } .cui-tab-mod li:nth-of-type(4).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(300%,0,0); -moz-transform: translate3d(300%,0,0); -ms-transform: translate3d(300%,0,0); transform: translate3d(300%,0,0); } .cui-tab-mod li:nth-of-type(5).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(400%,0,0); -moz-transform: translate3d(400%,0,0); -ms-transform: translate3d(400%,0,0); transform: translate3d(400%,0,0); } .cui-tab-mod li:nth-of-type(6).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(500%,0,0); -moz-transform: translate3d(500%,0,0); -ms-transform: translate3d(500%,0,0); transform: translate3d(500%,0,0); }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
</head>
<body> <ul class="cui-tab-mod">
<li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
<li data-key="1" data-index="1" class="cui-item">美国</li>
<li data-key="2" data-index="2" class="cui-item">日本</li>
<i class="cui-tab-scrollbar cui-tabnum3"></i>
</ul>
<script type="text/javascript">
$(function () {
var wrapper = $('.cui-tab-mod');
wrapper.on('click', function (e) {
var el = $(e.target);
if (el.hasClass('cui-item')) {
wrapper.find('li').removeClass('cui-tab-current');
el.addClass('cui-tab-current');
}
});
});
</script>
</body>
</html>

点击一下就让当前item获取class,然后文字样式会改变,下面一个横线也会动画滑动过去,但是这个东西在android大屏手机上却出了问题(比如note2),他会这样表现:

如图所示,class过去了,文字颜色也变了,但是下面对应的竖条却没有过去,我当时一看就知道是渲染的问题并且马上给出了一个解决方案:

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
<title></title>
<style type="text/css">
body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; } ul, ol { list-style: none; margin: 0; padding: 0; } .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; } .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; } .cui-tab-mod li.cui-tab-current { color: #099fde; } .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease-in-out; -moz-transition: -moz-transform 300ms ease-in-out; -ms-transition: -ms-transform 300ms ease-in-out; transition: transform 300ms ease-in-out; z-index: -1; } .cui-tabnum2 { width: 50%; } .cui-tabnum3 { width: 33.33333%; } .cui-tabnum4 { width: 25%; } .cui-tabnum5 { width: 20%; } .cui-tabnum6 { width: 16.66666%; } .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; } .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); } .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); } .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); } .cui-tab-mod li:nth-of-type(4).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(300%,0,0); -moz-transform: translate3d(300%,0,0); -ms-transform: translate3d(300%,0,0); transform: translate3d(300%,0,0); } .cui-tab-mod li:nth-of-type(5).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(400%,0,0); -moz-transform: translate3d(400%,0,0); -ms-transform: translate3d(400%,0,0); transform: translate3d(400%,0,0); } .cui-tab-mod li:nth-of-type(6).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(500%,0,0); -moz-transform: translate3d(500%,0,0); -ms-transform: translate3d(500%,0,0); transform: translate3d(500%,0,0); }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
</head>
<body> <ul class="cui-tab-mod">
<li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
<li data-key="1" data-index="1" class="cui-item">美国</li>
<li data-key="2" data-index="2" class="cui-item">日本</li>
<i class="cui-tab-scrollbar cui-tabnum3"></i>
</ul>
<script type="text/javascript">
$(function () {
var wrapper = $('.cui-tab-mod');
wrapper.on('click', function (e) {
var el = $(e.target);
var toolBar = $('.cui-tab-scrollbar');
if (el.hasClass('cui-item')) {
wrapper.find('li').removeClass('cui-tab-current');
el.addClass('cui-tab-current');
setTimeout(function () {
toolBar.width('width', toolBar.width());
}, 0)
}
});
});
</script>
</body>
</html>

这里设置下划线width的时候触发了其回流,而setTimeout会在主程序执行结束后才触发,于是BUG修复了,核心代码如下:

 $(function () {
var wrapper = $('.cui-tab-mod');
wrapper.on('click', function (e) {
var el = $(e.target);
var toolBar = $('.cui-tab-scrollbar');
if (el.hasClass('cui-item')) {
wrapper.find('li').removeClass('cui-tab-current');
el.addClass('cui-tab-current');
//修复丢帧问题
setTimeout(function () {
toolBar.width('width', toolBar.width());
}, 0)
}
});
});

这个BUG解决后也没有再关注,时序纷飞,一年过去了却和宇果聊天过程中再次想起这个问题,才意识到自己忽略的是什么。

重新认识Timeline

我们常常有一个问题,如何知道页面哪里的渲染有问题,如何捕捉?

如果没有一个实际可用的工具的话,我们只能由外文或者博客获取这类知识,这个时候就和我解决上述问题差不多了,仅仅从皮毛上知道是渲染导致的问题,并且能使用回流解决问题,却是对渲染性能造成负担,所以如何捕捉渲染问题衡量渲染性能这个是第一位,好在chrome提供了Timeline:

以我们的页面为例,我们开始监控,这里稍微改变一下代码:

 var wrapper = $('.cui-tab-mod');
wrapper.on('click', function (e) {
var el = $(e.target);
var toolBar = $('.cui-tab-scrollbar');
if (el.hasClass('cui-item')) {
wrapper.find('li').removeClass('cui-tab-current');
el.addClass('cui-tab-current');
// setTimeout(function () {
// toolBar.width('width', toolBar.width());
// }, 0)
}
}); function setIndex(i) {
var els = wrapper.find('li');
els.removeClass('cui-tab-current');
els.eq(i).addClass('cui-tab-current');
}

我首先点击开始监控,然后鼠标不在页面做任何操作,在控制台输入一句:

setIndex(1)

于是页面会发生改变,这个时候,我们得到的图是:

这张图其实最初我也是看热闹的,昨天根据宇果的指点,才稍微看出点门道了:

首先请看上图中的一个个透明框,每个透明框便是两次显示器刷新周期中等待的时间,其中有一个非常关键的单位叫做fps,这个60fps是个什么东西呢?

60fps与16ms

所谓60fps便是说屏幕1s会刷新60次,意思是大概16.5ms屏幕会刷新一次,在这一次刷新中浏览器会干很多事情,这里还是以图示为例,这里有2个前提:

① 我们鼠标并未操作

② 我们页面很单一

所以在我们执行setIndex前,浏览器根本没有任何消耗,每一次的刷新干了这几件事情:

刚刚整个过程一过经过了2.29秒,浏览器发生了这些事情:

从白条来看,浏览器处理整个动作大概花费320ms,这里出了4种颜色,这个也比较关键。

4种颜色

黄色是说明正在执行javascript脚本,从这里可以看出,js执行的速度是非常快的,这里包含了设值class、移除class,获取width等一系列操作,浏览器会等一次结束后才发生渲染。

紫色是说明正在回流,也就是我们传说中的渲染,这个是非常耗费性能的,我们这里具体跟进去看看:

接下来触发了css3过渡transition的动画,下面的滚动条开始了不停的移动:

可以看到,后续所有的运动只影响了一个元素,这个元素便是滚动条,这里为了验证刚刚所说,我们做两个事情:

① 使用click触发索引更改

② 为下划线添加子元素

这里有个非常不同的就是,我鼠标在界面操作了,不可避免的会引起一些move样式改变,所以有重绘有回流,都比较轻,比较关键的是,其中多了一个click操作(Event),但是下面动画时候影响的元素仍然只是一个,这个有点不明原因,我这里特别将transform改成了left,因为transform更加平滑,我想找出原因,却发现了另一个现象:

可以看出transformd导致的动画只会执行一次paint,便是最初那一次,而使用left的话却在不停的paint,这个是资源消耗的对比:

可以看出,使用left时候出现了锯齿状,这个时候我们可以得出一个结论,transform的动画确实比left节省性能。

至此我们对chrome的Timeline有了一个新的认识,但是我们这里的观察全部是在PC端发生的,而手机端是怎么样的呢?

移动端的渲染

这个图与上图形成了鲜明对比,PC端就只有很小的波动,手机端却引起了很多涟漪,导致这个问题的原因是硬件设施(这里是盗图):

PS:这里苦于没有Android设备,chrome电脑又暂时抽风不能真机调试,便去同事那里草草截图,哎......

丢帧的发生

如前所述,浏览器一次的刷新约16ms,以一次原子行为来说是这样的:

脚本运行时间+渲染时间+绘制时间<16ms

如果中间有一次的操作比如渲染的时间大于了16ms而导致浏览器没有来得及绘制,那么那次的操作便失效了,这个就是所谓的丢帧。

我们在note2上运行程序时会导致丢帧,应该就是其中一次超出了时限,因为class变化会引起样式重新计算,但是只是文字变化的话只是会引起重绘,所以主要问题发生在transition动画。

而我们的解决方案是setTimeout,这个造成的影响是:

我们发现了,就算没有动画,重新计算样式那里依旧是主要导致的回流的因素,是他挤掉了后续的操作吗?他重新计算样式中的因素有很多,我怀疑的目光首先放到了这段css:

    .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); 
-moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }

测试下来,似乎与他相关:

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
<title></title>
<style type="text/css">
body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; }
ul, ol { list-style: none; margin: 0; padding: 0; }
.cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; }
.cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; }
.cui-tab-mod li.cui-tab-current { color: #099fde; }
.cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease ; transition: transform 300ms ease ; z-index: -1; -webkit-backface-visibility:hidden; backface-visibility:hidden; }
.cui-tabnum2 { width: 50%; }
.cui-tabnum3 { width: 33.33333%; }
.cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
</head>
<body>
<ul class="cui-tab-mod">
<li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
<li data-key="1" data-index="1" class="cui-item">美国</li>
<li data-key="2" data-index="2" class="cui-item">日本</li>
<i class="cui-tab-scrollbar cui-tabnum3"><span>1</span></i>
</ul>
<script type="text/javascript">
var wrapper = $('.cui-tab-mod');
var toolBar = $('.cui-tab-scrollbar');
var els = wrapper.find('li');
wrapper.on('click', function (e) {
toolBar.css({
'-webkit-transform': 'translate3d(100%,0,0)',
'transform': 'translate3d(100%,0,0)'
})
var el = $(e.target);
});
</script>
</body>
</html>

如果这样,我直接操作toolBar便可以绕过该BUG,但是我还是不太确定,所以有了这段代码:

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
<title></title>
<style type="text/css">
body { -webkit-text-size-adjust: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-font-smoothing: antialiased; -moz-user-select: none; } ul, ol { list-style: none; margin: 0; padding: 0; } .cui-tab-mod { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; height: 43px; line-height: 43px; border-bottom: #bcbcbc 1px solid; background-color: #fafafa; color: #666; font-size: 15px; position: relative; display: table\9; width: 100%; } .cui-tab-mod li { text-align: center; -webkit-box-flex: 1; -moz-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: table-cell\9; } .cui-tab-mod li.cui-tab-current { color: #099fde; } .cui-tab-mod .cui-tab-scrollbar { position: absolute; left: 0; height: 4px; bottom: -1px; background-color: #099fde; -webkit-transition: -webkit-transform 300ms ease ; transition: transform 300ms ease ; z-index: -1; -webkit-backface-visibility:hidden; backface-visibility:hidden; } .cui-tabnum2 { width: 50%; } .cui-tabnum3 { width: 33.33333%; } .cui-tabnum4 { width: 25%; } .cui-tabnum5 { width: 20%; } .cui-tabnum6 { width: 16.66666%; } .cui-tab-mod li.cui-tab-current ~ .cui-tab-scrollbar { z-index: 2; } .cui-tab-mod cui-tab-current .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); } .cui-tab-mod li:nth-of-type(1).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); transform: translate3d(0,0,0); } .cui-tab-mod li:nth-of-type(2).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(100%,0,0); -moz-transform: translate3d(100%,0,0); -ms-transform: translate3d(100%,0,0); transform: translate3d(100%,0,0); } .cui-tab-mod li:nth-of-type(3).cui-tab-current ~ .cui-tab-scrollbar { -webkit-transform: translate3d(200%,0,0); -moz-transform: translate3d(200%,0,0); -ms-transform: translate3d(200%,0,0); transform: translate3d(200%,0,0); } </style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
</head>
<body> <ul class="cui-tab-mod">
<li data-key="0" data-index="0" class="cui-item cui-tab-current">中国</li>
<li data-key="1" data-index="1" class="cui-item">美国</li>
<li data-key="2" data-index="2" class="cui-item">日本</li>
<i class="cui-tab-scrollbar cui-tabnum3"><span>1</span></i>
</ul>
<script type="text/javascript">
var wrapper = $('.cui-tab-mod');
var toolBar = $('.cui-tab-scrollbar');
var els = wrapper.find('li'); wrapper.on('click', function (e) {
var el = $(e.target);
els.removeClass('cui-tab-current');
el.addClass('cui-tab-current');
toolBar.css('left', '0'); // setTimeout(function () {
// toolBar.width('width', toolBar.width());
// }, 0)
}); </script>
</body>
</html>
 var wrapper = $('.cui-tab-mod');
var toolBar = $('.cui-tab-scrollbar');
var els = wrapper.find('li'); wrapper.on('click', function (e) {
var el = $(e.target);
els.removeClass('cui-tab-current');
el.addClass('cui-tab-current');
toolBar.css('left', '0'); // setTimeout(function () {
// toolBar.width('width', toolBar.width());
// }, 0)
});

这一段代码也可以解决BUG,似乎解决bug的元素是导致了absolute元素的回流而与其它无关,这里再次对比Timeline:

两次对比没有什么差距,这个BUG导致的原因还需要深究,待我哪天去真机测试......

setTimeout动画

另外,最好也不要使用setTimeout之类的定时器来实现动画,下面这个动画操作也是非常消耗的:

这里如果使用requestAnimationFrame便可以避免Timer的影响。

fixed元素

一般来说,fixed元素在手机上尤其卡,我们这里也来追踪一下原因:

可以看到,fixed元素与left一样的都会不断的Paint,所以他卡呢,至于如何避免不同的团队有不同的方案。

结语

今天回顾了与宇果的交流过程中的渲染优化相关,这里还停留在比较浅的层次,需要继续学习,希望对各位有用,文中有误请您提出,最后微博求粉:

【前端优化之渲染优化】大屏android手机动画丢帧的背后的更多相关文章

  1. 转 cocos2d-x 优化(纹理渲染优化、资源缓存、内存优化)

    概述 包括以下5种优化:引擎底层优化.纹理优化.渲染优化.资源缓存.内存优化   引擎优化 2.0版本比1.0版本在算法上有所优化,效率更高.2.0版本使用OpenGl ES 2.0图形库,1.0版本 ...

  2. Android 卡顿优化 2 渲染优化

    1.概述 2015年初google发布了Android性能优化典范,发了16个小视频供大家欣赏,当时我也将其下载,通过微信公众号给大家推送了百度云的下载地址(地址在文末,ps:欢迎大家订阅公众号),那 ...

  3. scrcpy投屏android手机到电脑

    在mac os下 投票iPhone投屏是最简单不过了,只需要用Quicktime player就可以. 但是在mac下咱投屏android的手机呢,就需要用到scrcpy了. 1.打开终端,输入命令: ...

  4. [ios]离屏渲染优化

    原文链接:https://mp.weixin.qq.com/s?__biz=MjM5NTIyNTUyMQ==&mid=2709544818&idx=1&sn=62d0d2e9a ...

  5. Android性能优化之渲染

    Google近期在Udacity上发布了Android性能优化的在线课程,目前有三个篇章,分别从渲染,运算与内存,电量三个方面介绍了如何去优化性能,这些课程是Google之前在Youtube上发布的A ...

  6. Android性能优化之渲染篇

    下面是渲染篇章的学习笔记,部分内容和前面的性能优化典范有重合,欢迎大家一起学习交流! 1)Why Rendering Performance Matters 现在有不少App为了达到很华丽的视觉效果, ...

  7. 【转载】Android性能优化之渲染篇

    下面是渲染篇章的学习笔记,欢迎大家一起学习交流! 1)Why Rendering Performance Matters 现在有不少App为了达到很华丽的视觉效果,会需要在界面上层叠很多的视图组件,但 ...

  8. 【前端性能】高性能滚动 scroll 及页面渲染优化

    最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作. 本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的 ...

  9. 【前端性能】高性能滚动 scroll 及页面渲染优化--转发

    本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的关系,节流与防抖,pointer-events:none 优化滚动.因为本文涉及了很多很多基础,可以对照上面的知 ...

随机推荐

  1. 简历生成平台项目开发-STEP1问卷设计

    周五课程结束完后,小组建立QQ群和微信群,着手讨论项目问题.一开始的大概想法:就业信息平台,收集企业招聘信息和就业生资料,提供给学生和企业的校企对接平台.后来发现群里谭卓同学也有个相关的思路,经过商量 ...

  2. mysql删除重复记录语句的方法

    例如: id name value 1 a pp 2 a pp 3 b iii 4 b pp 5 b pp 6 c pp 7 c pp 8 c iii id是主键 要求得到这样的结果 id name ...

  3. 转: 如何高效利用GitHub

    注:写了很多使用哲学,有意思 from: http://www.yangzhiping.com/tech/github.html

  4. 你还可以再诡异点吗——SQL日志文件不断增长

    前言 今天算是遇到了一个罕见的案例. SQL日志文件不断增长的各种实例不用多说,园子里有很多牛人有过介绍,如果我再阐述这些陈谷子芝麻,想必已会被无数次吐槽. 但这次我碰到的问题确实比较诡异,其解决方式 ...

  5. ASP.NET Web API WebHost宿主环境中管道、路由

    ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...

  6. Atitit 外包管理规范attilax总结

    Atitit 外包管理规范attilax总结 1. 常见的外包问题2 1.1. 使用了过时的语言与技术2 1.2. 不易扩展的架构,架构落后2 1.3. 使用了小众语言,框架类库,组件等技术,导致维护 ...

  7. redis成长之路——(七)

    扩展性封装 虽说现在StackExchange.Redis免费,万一到时候和servicestack.redis一样要收费呢,所以先留一口,后续的可以再处理 实例代码点击这里查看 redis成长之路- ...

  8. WCF学习之旅—WCF服务的批量寄宿(十三)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) WCF学习之旅—WCF ...

  9. SQL Server系列目录

    一.SQL Server基础部分 1  数据库概念及规范化设计 1.1 数据库物理模式设计 1.2 Microsoft SQL Server Management Studio模板资源管理器 2 数据 ...

  10. Dom addEventlistener与id 绑定事件的区别(续)

    addEventListener 第三个参数为 useCapture. 以一个例子说明. <div id="div1" style="background: blu ...