性能优化_子查询的优化,性能优化之mysql优化 - CSDN
  • 本文为性能优化系列的总纲,主要介绍性能调优专题计划、何为性能问题、性能调优方式及前面介绍的数据库优化、布局优化、Java(Android)代码优化、网络优化具体对应的调优方式。   1、调优专题博客计划 目前...

    本文为性能优化系列的总纲,主要介绍性能调优专题计划、何为性能问题、性能调优方式及前面介绍的数据库优化、布局优化、Java(Android)代码优化、网络优化具体对应的调优方式。

     

    1、调优专题博客计划

    目前性能优化专题已完成以下部分:

    性能优化总纲——性能问题及性能调优方式

    性能优化第四篇——移动网络优化

    性能优化第三篇——Java(Android)代码优化
    性能优化第二篇——布局优化
    性能优化第一篇——数据库性能优化

    性能优化实例

     

    后续计划性能优化——诊断及工具(目前只有关于TraceView的介绍)、性能优化——内存篇、性能优化——JNI篇,性能优化——电量篇。

     

    2、何为性能问题
    在性能测试中存在两个概念:
    (1). 响应时间
    指从用户操作开始到系统给用户以正确反馈的时间。一般包括逻辑处理时间 + 网络传输时间 + 展现时间。对于非网络类应用不包括网络传输时间。

    展现时间即网页或 App 界面渲染时间。

     

    响应时间是用户对性能最直接的感受。

     

    (2). TPS(Transaction Per Second)

    TPS为每秒处理的事务数,是系统吞吐量的指标,在搜索系统中也用QPS(Query Per Second)衡量。TPS一般与响应时间反相关。

     

    通常所说的性能问题就是指响应时间过长、系统吞吐量过低。

     

    对后台开发来说,也常将高并发下内存泄漏归为性能问题。
    对移动开发来说,性能问题还包括电量、内存使用这两类较特殊情况。

     

    3、性能调优方式

    明白了何为性能问题之后,就能明白性能优化实际就是优化系统的响应时间,提高TPS。优化响应时间,提高TPS。方式不外乎这三大类:
    (1) 降低执行时间
    又包括几小类

    a. 利用多线程并发或分布式提高 TPS
    b. 缓存(包括对象缓存、IO 缓存、网络缓存等)
    c. 数据结构和算法优化
    d. 性能更优的底层接口调用,如 JNI 实现
    e. 逻辑优化
    f. 需求优化

     

    (2) 同步改异步,利用多线程提高TPS

     

    (3) 提前或延迟操作,错峰提高TPS

     

    对于数据库优化、布局优化、Java代码部分优化、网络优化都可以归纳到上面的几种方式中。具体见:

    性能优化第四篇——移动网络优化

    性能优化第三篇——Java(Android)代码优化
    性能优化第二篇——布局优化
    性能优化第一篇——数据库性能优化

    性能优化实例 

    展开全文
  • MySQL 高级性能优化实战包含范式设计,索引原理,执行计划,慢查询,锁和事务。旨在帮助程序设计人员架构千万级高并发交易一致性系统时全面,本课程适合Java初中高级程序员、开发经理、项目经理、架构师、CTO。
  • 前端优化是复杂的,针对方方面面的资源都有不同的方式。那么,前端优化的目的是什么 ?  1. 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。  2. 从服务商...

    前言:关于优化问题,随着项目经验不断累积,多方查找资料进行拼接合并,形成如下文章,之后遇到类似好的方法,会不断补充完善。

    前端是庞大的,包括 HTML、 CSS、 Javascript、Image 、Flash等等各种各样的资源。前端优化是复杂的,针对方方面面的资源都有不同的方式。那么,前端优化的目的是什么 ?

    1. 从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。
    2. 从服务商角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。
    总之,恰当的优化不仅能够改善站点的用户体验并且能够节省相当的资源利用。

    大概有如下优化方法:



      具体参考:http://www.cnblogs.com/developersupport/p/webpage-performance-best-practices.html
      一、页面级优化
      1. 减少 HTTP请求数
      这条策略基本上所有前端人都知道,而且也是最重要最有效的。都说要减少 HTTP请求,那请求多了到底会怎么样呢 ?首先,每个请求都是有成本的,既包含时间成本也包含资源成本。一个完整的请求都需要经过 DNS寻址、与服务器建立连接、发送数据、等待服务器响应、接收数据这样一个 “漫长” 而复杂的过程。时间成本就是用户需要看到或者 “感受” 到这个资源是必须要等待这个过程结束的,资源上由于每个请求都需要携带数据,因此每个请求都需要占用带宽。另外,由于浏览器进行并发请求的请求数是有上限的 (具体参见此处 ),因此请求数多了以后,浏览器需要分批进行请求,因此会增加用户的等待时间,会给用户造成站点速度慢这样一个印象,即使可能用户能看到的第一屏的资源都已经请求完了,但是浏览器的进度条会一直存在。
      减少 HTTP请求数的主要途径包括:
      (1). 从设计实现层面简化页面
      如果你的页面像百度首页一样简单,那么接下来的规则基本上都用不着了。保持页面简洁、减少资源的使用时最直接的。如果不是这样,你的页面需要华丽的皮肤,则继续阅读下面的内容。
      (2). 合理设置 HTTP缓存
      缓存的力量是强大的,恰当的缓存设置可以大大的减少 HTTP请求。以有啊首页为例,当浏览器没有缓存的时候访问一共会发出 78个请求,共 600多 K数据 (如图 1.1),而当第二次访问即浏览器已缓存之后访问则仅有 10个请求,共 20多 K数据 (如图 1.2)。 (这里需要说明的是,如果直接 F5刷新页面的话效果是不一样的,这种情况下请求数还是一样,不过被缓存资源的请求服务器是 304响应,只有 Header没有Body ,可以节省带宽 )
      怎样才算合理设置 ?原则很简单,能缓存越多越好,能缓存越久越好。例如,很少变化的图片资源可以直接通过 HTTP Header中的Expires设置一个很长的过期头 ;变化不频繁而又可能会变的资源可以使用 Last-Modifed来做请求验证。尽可能的让资源能够在缓存中待得更久。关于 HTTP缓存的具体设置和原理此处就不再详述了,有兴趣的可以参考下列文章:
    HTTP1.1协议中关于缓存策略的描述
    Fiddler HTTP Performance中关于缓存的介绍
      (3). 资源合并与压缩
      如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合为一个。另外, CSS、 Javascript、Image 都可以用相应的工具进行压缩,压缩后往往能省下不少空间。
      (4). CSS Sprites
      合并 CSS图片,减少请求数的又一个好办法。
      (5). Inline Images

      使用 data: URL scheme的方式将图片嵌入到页面或 CSS中,如果不考虑资源管理上的问题的话,不失为一个好办法。如果是嵌入页面的话换来的是增大了页面的体积,而且无法利用浏览器缓存。使用在 CSS中的图片则更为理想一些。

    .sample-inline-png {
        padding-left: 20px;
        background: white url('data:image/png;base64,iVBORw0KGgoAA
    AANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0l
    EQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6
    P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC') no-repeat scroll left top;
    }
      (6). Lazy Load Images(自己对这一块的内容还是不了解)
      这条策略实际上并不一定能减少 HTTP请求数,但是却能在某些条件下或者页面刚加载时减少 HTTP请求数。对于图片而言,在页面刚加载的时候可以只加载第一屏,当用户继续往后滚屏的时候才加载后续的图片。这样一来,假如用户只对第一屏的内容感兴趣时,那剩余的图片请求就都节省了。 有啊首页 曾经的做法是在加载的时候把第一屏之后的图片地址缓存在 Textarea标签中,待用户往下滚屏的时候才 “惰性” 加载。

      2. 将外部脚本置底(将脚本内容在页面信息内容加载后再加载)
      前文有谈到,浏览器是可以并发请求的,这一特点使得其能够更快的加载资源,然而外链脚本在加载时却会阻塞其他资源,例如在脚本加载完成之前,它后面的图片、样式以及其他脚本都处于阻塞状态,直到脚本加载完成后才会开始加载。如果将脚本放在比较靠前的位置,则会影响整个页面的加载速度从而影响用户体验。解决这一问题的方法有很多,在 这里有比较详细的介绍 (这里是译文和 更详细的例子 ),而最简单可依赖的方法就是将脚本尽可能的往后挪,减少对并发下载的影响。
      3. 异步执行 inline脚本(其实原理和上面是一样,保证脚本在页面内容后面加载。)
      inline脚本对性能的影响与外部脚本相比,是有过之而无不及。首页,与外部脚本一样, inline脚本在执行的时候一样会阻塞并发请求,除此之外,由于浏览器在页面处理方面是单线程的,当 inline脚本在页面渲染之前执行时,页面的渲染工作则会被推迟。简而言之, inline脚本在执行的时候,页面处于空白状态。鉴于以上两点原因,建议将执行时间较长的 inline脚本异步执行,异步的方式有很多种,例如使用 script元素的defer 属性(存在兼容性问题和其他一些问题,例如不能使用 document.write)、使用setTimeout ,此外,在HTML5中引入了 Web Workers的机制,恰恰可以解决此类问题。

      4. Lazy Load Javascript(只有在需要加载的时候加载,在一般情况下并不加载信息内容。)

      随着 Javascript框架的流行,越来越多的站点也使用起了框架。不过,一个框架往往包括了很多的功能实现,这些功能并不是每一个页面都需要的,如果下载了不需要的脚本则算得上是一种资源浪费 -既浪费了带宽又浪费了执行花费的时间。目前的做法大概有两种,一种是为那些流量特别大的页面专门定制一个专用的 mini版框架,另一种则是 Lazy Load。YUI 则使用了第二种方式,在 YUI的实现中,最初只加载核心模块,其他模块可以等到需要使用的时候才加载。


      5. 将 CSS放在 HEAD中
      如果将 CSS放在其他地方比如 BODY中,则浏览器有可能还未下载和解析到 CSS就已经开始渲染页面了,这就导致页面由无 CSS状态跳转到 CSS状态,用户体验比较糟糕。除此之外,有些浏览器会在 CSS下载完成后才开始渲染页面,如果 CSS放在靠下的位置则会导致浏览器将渲染时间推迟。
      6. 异步请求 Callback(就是将一些行为样式提取出来,慢慢的加载信息的内容)
      在某些页面中可能存在这样一种需求,需要使用 script标签来异步的请求数据。类似:
      Javascript:

    function myCallback(info){ 
    //do something here 

      HTML:

      cb返回的内容 :
    myCallback('Hello world!');
    像以上这种方式直接在页面上写 <script>对页面的性能也是有影响的,即增加了页面首次加载的负担,推迟了 DOMLoaded和window.onload 事件的触发时机。如果时效性允许的话,可以考虑在 DOMLoaded事件触发的时候加载,或者使用 setTimeout方式来灵活的控制加载的时机。
      7. 减少不必要的 HTTP跳转
      对于以目录形式访问的 HTTP链接,很多人都会忽略链接最后是否带 ’/',假如你的服务器对此是区别对待的话,那么你也需要注意,这其中很可能隐藏了 301跳转,增加了多余请求。具体参见下图,其中第一个链接是以无 ’/'结尾的方式访问的,于是服务器有了一次跳转。
      8. 避免重复的资源请求
      这种情况主要是由于疏忽或页面由多个模块拼接而成,然后每个模块中请求了同样的资源时,会导致资源的重复请求

            9 精简Javascript和CSS

    精简就是将Javascript或CSS中的空格和注释全去掉,

    复制代码
    复制代码
    body {
        line-height: 1;
    }
    ol, ul {
        list-style: none;
    }
    blockquote, q {
        quotes: none;
    }
    复制代码
    复制代码

    精简后版本

    复制代码
    body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}
    复制代码

    统计表明精简后的文件大小平均减少了21%,即使在应用Gzip的文件也会减少5%。

    用来帮助我们做精简的工具很多,主要可以参考如下,

    JS compressors:

    CSS compressors:

    与VS集成比较好的工具如下.


      二、代码级优化
      1. Javascript
      (1). DOM
      DOM操作应该是脚本中最耗性能的一类操作,例如增加、修改、删除 DOM元素或者对 DOM集合进行操作。如果脚本中包含了大量的 DOM操作则需要注意以下几点:
      a. HTML Collection(HTML收集器,返回的是一个数组内容信息)
      在脚本中 document.images、document.forms 、getElementsByTagName()返回的都是 HTMLCollection类型的集合,在平时使用的时候大多将它作为数组来使用,因为它有 length属性,也可以使用索引访问每一个元素。不过在访问性能上则比数组要差很多,原因是这个集合并不是一个静态的结果,它表示的仅仅是一个特定的查询,每次访问该集合时都会重新执行这个查询从而更新查询结果。所谓的 “访问集合” 包括读取集合的 length属性、访问集合中的元素。
      因此,当你需要遍历 HTML Collection的时候,尽量将它转为数组后再访问,以提高性能。即使不转换为数组,也请尽可能少的访问它,例如在遍历的时候可以将 length属性、成员保存到局部变量后再使用局部变量。
      b. Reflow & Repaint
      除了上面一点之外, DOM操作还需要考虑浏览器的 Reflow和Repaint ,因为这些都是需要消耗资源的,具体的可以参加以下文章:
    如何减少浏览器的repaint和reflow?
    Understanding Internet Explorer Rendering Behaviour
    Notes on HTML Reflow

      (2). 慎用 with
    with(obj){ p = 1}; 代码块的行为实际上是修改了代码块中的 执行环境 ,将obj放在了其作用域链的最前端,在 with代码块中访问非局部变量是都是先从 obj上开始查找,如果没有再依次按作用域链向上查找,因此使用 with相当于增加了作用域链长度。而每次查找作用域链都是要消耗时间的,过长的作用域链会导致查找性能下降。
      因此,除非你能肯定在 with代码中只访问 obj中的属性,否则慎用 with,替代的可以使用局部变量缓存需要访问的属性。
      (3). 避免使用 eval和 Function
      每次 eval 或 Function 构造函数作用于字符串表示的源代码时,脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作 —— 通常比简单的函数调用慢 100倍以上。
      eval 函数效率特别低,由于事先无法知晓传给 eval 的字符串中的内容,eval在其上下文中解释要处理的代码,也就是说编译器无法优化上下文,因此只能有浏览器在运行时解释代码。这对性能影响很大。
      Function 构造函数比 eval略好,因为使用此代码不会影响周围代码 ;但其速度仍很慢。
      此外,使用 eval和 Function也不利于Javascript 压缩工具执行压缩。
      (4). 减少作用域链查找(这方面设计到一些内容的相关问题)
      前文谈到了作用域链查找问题,这一点在循环中是尤其需要注意的问题。如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的。
      低效率的写法:
    // 全局变量 
    var globalVar = 1; 
    function myCallback(info){ 
    for( var i = 100000; i--;){ 
    //每次访问 globalVar 都需要查找到作用域链最顶端,本例中需要访问 100000 次 
    globalVar += i; 
    }

      更高效的写法:
    // 全局变量 
    var globalVar = 1; 
    function myCallback(info){ 
    //局部变量缓存全局变量 
    var localVar = globalVar; 
    for( var i = 100000; i--;){ 
    //访问局部变量是最快的 
    localVar += i; 

    //本例中只需要访问 2次全局变量
    在函数中只需要将 globalVar中内容的值赋给localVar 中区
    globalVar = localVar; 
    }
      此外,要减少作用域链查找还应该减少闭包的使用。
      (5). 数据访问
      Javascript中的数据访问包括直接量 (字符串、正则表达式 )、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问需要更大的开销。当出现以下情况时,建议将数据放入局部变量:
      a. 对任何对象属性的访问超过 1次
      b. 对任何数组成员的访问次数超过 1次
      另外,还应当尽可能的减少对对象以及数组深度查找。
      (6). 字符串拼接
      在 Javascript中使用"+" 号来拼接字符串效率是比较低的,因为每次运行都会开辟新的内存并生成新的字符串变量,然后将拼接结果赋值给新变量。与之相比更为高效的做法是使用数组的 join方法,即将需要拼接的字符串放在数组中最后调用其 join方法得到结果。不过由于使用数组也有一定的开销,因此当需要拼接的字符串较多的时候可以考虑用此方法。

      关于 Javascript优化的更详细介绍请参考:
    Write Efficient Javascript(PPT)
    Efficient JavaScript
      2. CSS选择符
      在大多数人的观念中,都觉得浏览器对 CSS选择符的解析式从左往右进行的,例如
    #toc A { color: #444; }
      这样一个选择符,如果是从右往左解析则效率会很高,因为第一个 ID选择基本上就把查找的范围限定了,但实际上浏览器对选择符的解析是从右往左进行的。如上面的选择符,浏览器必须遍历查找每一个 A标签的祖先节点,效率并不像之前想象的那样高。根据浏览器的这一行为特点,在写选择符的时候需要注意很多事项,有人已经一一列举了, 详情参考此处。

      3. HTML
      对 HTML本身的优化现如今也越来越多的受人关注了,详情可以参见这篇 总结性文章 。

      4. Image压缩
      图片压缩是个技术活,不过现如今这方面的工具也非常多,压缩之后往往能带来不错的效果,具体的压缩原理以及方法在《 Even Faster Web Sites》第10 章有很详细的介绍,有兴趣的可以去看看。
      总结
      本文从页面级以及代码级两个粒度对前端优化的各种方式做了一个总结,这些方法基本上都是前端开发人员在开发的过程中可以借鉴和实践的,除此之外,完整的前端优化还应该包括很多其他的途径,例如 CDN、 Gzip、多域名、无 Cookie服务器等等,由于对于开发人员的可操作性并不强大,在此也就不多叙述了,详细的可以参考 Yahoo和Google 的这些“金科玉律。
    展开全文
  • 性能优化概述

    2018-02-03 22:38:14
    如何做性能优化 确定优化目标 定位性能瓶颈 制定优化方法 测试优化效果 性能优化目标是什么 吞吐量,越大越好 延时,越低越好 同样的资源下(前提),吞吐量越高越好,响应时间越低越好。通俗的讲就是:多...

    如何做性能优化

    1. 确定优化目标
    2. 定位性能瓶颈
    3. 制定优化方法
    4. 测试优化效果

    性能优化目标是什么

    1. 吞吐量,越大越好
    2. 延时,越低越好

    同样的资源下(前提),吞吐量越高越好,响应时间越低越好。通俗的讲就是:多快好省。

    如何定位系统性能的瓶颈呢

    1. 资源分析
    2. 代码分析

    资源分析

    资源分析以对系统资源的分析为起点,涉及的系统资源有:CPU,内存,磁盘,网卡。通过对资源使用率的分析,判断某项资源是否已经处于或接近极限。

    常用的分析工具有:top,free,vmstat,iostat,iotop,netstat。更多工具见下图:

    来自 Brendan Gregg 的性能观测工具图

    通常资源使用率超过 60% 可能会是问题,为什么呢?因为时间间隔的均值,掩盖了使用率 100% 的短期爆发。

    定位瓶颈之后,可以通过增加资源来提升性能,也可以通过优化系统减少资源占用来优化性能。

    代码分析

    根据2:8原则来说,20%的代码消耗了80%的性能,找到那20%的代码,你就可以优化那80%的性能。

    通常使用 Profiler 工具,来收集程序运行时的信息。如果 CPU 是瓶颈,寻找那些消耗 CPU 最多的代码去优化。如果内存是瓶颈,则优化消耗内存最多的代码。

    常用的 Profiler,有 Linux 的 OProfile/perf,Java 的 JProfiler/JMC。

    常见的性能优化方法

    一般性能优化方法有两种:一是,从代码层面优化,提升某个方法的性能,从而提升单机性能;二是,从系统结构层面优化,通过减少无用功,来减少资源消耗。

    代码层面优化

    1. Buffer:缓解应用系统上下层组件之间的性能差异,比如通常的 IO Buffer。
    2. Cache:通常用于读多写少的情况,也是用来缓解应用系统上下层组件之间的性能差异。比如,应用 local cache,Memcached/Redis。
    3. Batch:网络或磁盘里的批量操作,通过合并小任务或小请求为大任务大请求,来提升数据传输效率低。比如 TCP 中的 nagle 算法,就是通过合并多个小分组来提升网络传输效率的。
    4. Pool:通过减少对象创建,连接建立的开销来提升性能。比如线程池,连接池,对象池。
    5. Concurrency:通过将串行改为并行,能过有效的降低系统延时。在多核系统中,并行处理才能提升 CPU 使用率。
    6. Lock Less:多线程访问共享资源时,通常需要加锁。重量级的锁往往引起线程切换,而线程切换非常耗时。那么可以通过优化锁的使用来提升性能,优化锁有两种方法:
      • 通过减小锁的粒度,分离竞争点来减少竞争。比如 Java 里 HashTable 中锁的粒度是整个对象,ConcurrentHashMap 中锁的粒度只是一个 Segment。
      • 在竞争较少的情况下,使用轻量级锁来代替重量级锁,减少线程切换带来的性能消耗,比如自旋锁代替互斥锁。

    系统架构优化

    可以看看:性能优化案例(一):通过修改路由算法提升系统性能

    如何做性能基准测试

    什么是有效的性能基准测试呢?

    基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。有以下特性:
    1. 可重复:就像科学实验一样,能够被他人重复,才能被认可
    2. 可观测:测试结果能过被分析和理解
    3. 可对比:通过对比,才能知道性能优化的效果
    3. 符合现实:测量结果符合现实情况
    4. 易执行:开发人员能快速地修改系统并测试

    基准测试有三种类型:微基准测试,模拟,回放。从下图可以看出来,回放最接近生产环境。
    基准测试类型

    微基准测试利用人造的工作负载对某类特定的操作做测试,例如执行一种类型文件系统I/O,数据库查询,系统调用。其优势是简单:
    1. 对组件的数量和所牵扯的代码路径做限制,能更容易地研究目标,从而快速地确定性能差异的根源。
    2. 因为来自其他组件的变化以及尽可能的被玻璃了,所以测试通常是可重复的。

    许多基准测试会模拟客户应用程序的工作负载,基于生产环境的工作负载特征,来决定所要模拟的特征。模拟所生成的结果与客户在真实世界所执行的工作负载是相似的。相较于微基准测试。模拟能覆盖复杂系统相互作用的影响,这点是微基准测试可能缺失的。

    回放:用真实捕捉到的客户机的操作,来测试性能。有很多分布式服务框架带有复制线上流量,引流到测试机器的功能。

    做性能测试时,要多去思考性能数据背后的根本原因,避免因各种外界因素的干扰导致测试失真。

    参考资料:

    1. 《性能之巅:洞悉系统,企业与云计算》
    2. Linux Performance
    展开全文
  • 课程总结sql server运行过程中对系统资源的使用和由此产生性能问题,介绍数据库规划设计、事务和锁的基本知识,如何处理阻塞和死锁,优化索引和读懂统计信息和执行计划等知识,同时详细介绍SQL 2014新功能特性内存...
  • 性能优化原则和方法 借助性能优化工具分析解决问题 性能优化指标 性能问题分类 1、渲染问题:过度绘制、布局冗杂 2、内存问题:内存浪费(内存管理)、内存泄漏 3、功耗问题:耗电 性能优化原则和方法 1、...

    结合以下四个部分讲解:

    • 性能问题分类

    • 性能优化原则和方法

    • 借助性能优化工具分析解决问题

    • 性能优化指标

    性能问题分类

    1、渲染问题:过度绘制、布局冗杂

    2、内存问题:内存浪费(内存管理)、内存泄漏

    3、功耗问题:耗电

    性能优化原则和方法

    1、性能优化原则

    • 坚持性能测试(开发和测试同学的测试方法略有不同):不要凭感觉去检测性能问题、评估性能优化的效果,应该保持足够多的测量,用数据说话(主要针对测试同学)。使用各种性能工具测试及快速定位问题(主要针对开发同学)。

    • 使用低配置的设备:同样的程序,在低端配置的设备中,相同的问题会暴露得更为明显。

    • 权衡利弊:在能够保证产品稳定、按时完成需求的前提下去做优化。

    2、优化方法

    • 了解问题(分为可感知和不可感知的性能问题):对于性能问题来讲,这个步骤只适用于某些明显的性能问题,很多无法感知的性能问题需要通过工具定位。例如:内存泄漏、层级冗杂、过度绘制等无法感知。滑动卡顿是可以感知到的。

    • 定位问题:通过工具检测、分析数据,定位在什么地方存在性能问题。

    • 分析问题:找到问题后,分析针对这个问题该如何解决,确定解决方案。

    • 解决问题:根据分析结果寻找解决方案。

    • 验证问题:保证优化有效,没有产生新的问题,以及产品稳定性。

    性能优化工具

    1、手机开发者选项:调试GPU过度绘制、启用严格模式、显示CPU使用情况、GPU呈现模式分析、显示所有”应用程序无响应”。(小米手机开发开发者选项中名字)

    2、IDE中:Android Studio,比如静态代码检测工具、Memory Monitor、CPU Monitor、NetWork Monitor、GPU Monitor、Layout Inspector、Analyze APK等。

    3、SDK中:sdk\tools,比如DDMS、HierarchyViewer、TraceView等。

    4、第三方工具:MAT、LeakCanary、GT等。

    性能优化指标

    1、渲染

    • 滑动流畅度:FPS,即Frame per Second,一秒内的刷新帧数,越接近60帧越好;

    • 过度绘制:单页面的3X(粉红色区域) Overdraw小于25%

    • 启动时间:这里主要说的是Activity界面启动时间,一般低于300ms,需要用高频摄像机计算时间。

    2、内存

    • 内存大小:峰值越低越好,需要优化前后做对比

    • 内存泄漏:需要用工具检查对比优化前后

    3、功耗

    • 单位时间内的掉电量,掉电量越少越好,业内没有固定标准。华为有专门测试功耗的机器,以及自己的标准。

    一、渲染问题

    先来看看造成应用UI卡顿的常见原因都有哪些?

    1、人为在UI线程中做轻微耗时操作,导致UI线程卡顿;

    2、布局Layout过于复杂,无法在16ms内完成渲染;

    3、同一时间动画执行的次数过多,导致CPU或GPU负载过重;

    4、View过度绘制,导致某些像素在同一帧时间内被绘制多次,从而使CPU或GPU负载过重;

    5、View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染;

    6、内存频繁触发GC过多(同一帧中频繁创建内存),导致暂时阻塞渲染操作;

    7、冗余资源及逻辑等导致加载和执行缓慢;

    8、臭名昭著的ANR;

    大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。(Google官方说的)

    Android系统每隔16ms发出VSYNC信号(vertical synchronization –场扫描同步,场同步,垂直同步),触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms(1000/60=16.67ms)内完成。

    如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。

    这里写图片描述

    1、过度绘制

        Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。
        在多层次的UI结构里面,如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。
        这就浪费大量的CPU以及GPU资源,找出界面滑动不流畅、界面启动速度慢、手机发热。
    
    • 如何查看过度绘制?

      设置 — 开发中选项 — 调试GPU过度绘制
      
    • 来看看手雷里的过度绘制和优化效果(目前手雷还存在很多待优化的页面)

    这里写图片描述

    • 上图中的各种颜色都代表什么意思?

    这里写图片描述

         每个颜色的说明如下:
    
          原色:没有过度绘制
          紫色:1 次过度绘制
          绿色:2 次过度绘制
          粉色:3 次过度绘制
          红色:4 次及以上过度绘制
    
    • 造成过度优化的关键是什么?多余的背景(Background)

    • 接下来举例说明:

    1、MainTabActivity

    在MainTabActivity的Theme中修改背景
    

    这里写图片描述

    去除布局(main_activity_linerlayout.xml)中的background
    

    这里写图片描述

    如果不给当前Activity设置主题,默认主题是什么,默认主题背景是什么?
    

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    可以在默认主题中添加通用主题背景
      <item name="android:windowBackground">@drawable/common_layout_content_bkg</item>
      去除背景
      <item name="android:windowBackground">null</item>
    

    2、除了布局中多余背景,还有可能在代码里添加了多余的背景。

    这里写图片描述

    查看分享弹窗的布局代码发现只有一个background,但为什么会过度绘制呢?
    

    这里写图片描述

    这里写图片描述

    代码修改(SharePlatformsDialog.java)
    

    这里写图片描述

    3、弹窗底部布局不会导致弹窗本身过度绘制

    这里写图片描述

        弹窗的绘制是属于剪切式绘制不是覆盖绘制,蒙层是透明度亮度的调节不是绘制一层灰色。
    如果我们不想用系统dialog而是自定义一个弹窗view,就需要考虑过度绘制问题。
    

    4、自定义view时,通过Canvas的clipRect方法控制每个视图每次刷新的区域,这样可以避免刷新不必要的区域,从而规避过渡绘制的问题。还可以使用canvas.quickreject()来判断是否和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。参考:http://jaeger.itscoder.com/android/2016/09/29/android-performance-overdraw.html

    • 优化方法和步骤关键总结
     总结一下,优化步骤如下:
    
      1、移除或修改Window默认的Background
      2、移除XML布局文件中非必需的Background
      3、按需显示占位背景图片
      4、控制绘制区域

    2、布局优化

    布局太过复杂,层级嵌套太深导致绘制操作耗时,且增加内存的消耗。
    我们的目标就是,层级扁平化
    
    • 布局优化的建议:

    1、第一个建议:可以使用相对布局减少层级的就使用相对布局,否则使用线性布局。Android中RelativeLayout和LinearLayout性能分析,参考:http://www.jianshu.com/p/8a7d059da746#
    2、第二个建议:用merge标签来合并布局,这可以减少布局层次。

    3、第三个建议:用include标签来重用布局,抽取通用的布局可以让布局的逻辑更清晰明了,但要避免include乱用。

    4、第四个建议:避免创建不必要的布局层级。(最容易发生的!)

    5、第五个建议:使用惰性控件ViewStub实现布局动态加载

    • 如何借助工具查看代码布局?

      Android SDK 工具箱中有一个叫做 Hierarchy Viewer 的工具,能够在程序运行时分析 Layout。
      可以用这个工具找到 Layout 的性能瓶颈
      该工具的使用条件:模拟器或者Root版真机。
      如何开启该功能:AndroidStudio中,Tools — Android — Android Devices Monitor
      该工具的缺点:使用起来麻烦。
      

    这里写图片描述

    • 看看项目中遇到的问题(MainTabAvtivity)。

    1、merge标签的使用

    这里写图片描述

    未使用merge,例如:XLTabLayout.java
    

    这里写图片描述

    这里写图片描述

    使用merge,例如:账号信息页的条目UserAccountItem
    

    这里写图片描述

    2、include标签的使用导致的问题

    这里写图片描述

    这里写图片描述

    3、避免创建不必要的层级(MainTabActivity)

    这里写图片描述

    4、ViewStub的使用

        这个标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。
    通常情况下我们需要在某个条件下使用某个布局的时候会通过gone或者invisible来隐藏,其实这样的方式虽然隐藏了布局,但是当显示该界面的时候还是将该布局实例化的。使用ViewStub可以避免内存的浪费,加快渲染速度。
    其实ViewStub就是一个宽高都为0的一个View,它默认是不可见的,只有通过调用setVisibility函数或者Inflate函数才会将其要装载的目标布局给加载出来,从而达到延迟加载的效果,这个要被加载的布局通过android:layout属性来设置。
    

    这里写图片描述

        当准备inflate ViewStub时,调用inflate()方法即可。还可以设定ViewStub的Visibility为VISIBLE或INVISIBLE,也会触发inflate。注意的是,使用inflate()方法能返回布局文件的根View。
    
    ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
      // or
      View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
    setVisibility的时候会触发了inflate
    

    这里写图片描述

        注意:使用ViewStub加载的布局中不能使用merge标签。
    
    • 看看Space标签(不常用)

          space标签可以只在布局文件中占位,不绘制,Space标签有对应的java类Space.java,
          通过阅读源码可以发现,它继承至View.java,并且复写了draw方法,
          该方法为空,既没有调用父类的draw方法,也没有执行自己的代码,表示该类是没有绘制操作的,
          但onMeasure方法正常调用,说明是有宽高的。
          主要功能用来设置间距,这个标签不常用,常使用margin或padding。
      

    3、介绍一下查看渲染性能的工具

    • GPU呈现模式分析(大致定位问题)

      开发者选项 — GPU呈现模式分析 — 选择“在屏幕上显示为条形图”
      

    这里写图片描述

    Android开发者选项——Gpu呈现模式分析,参考:http://www.voidcn.com/blog/gjy211/article/p-6210447.html
    自动播放的视频停止的时候会有两条很长的柱线,下个视频播放的时候还会有一条。这里有一个明显的卡顿。
    播放器操作(DefaultPlayerView.java - doPlay,player_auto_control_layout.xml):

    这里写图片描述

     上图的E total time = 68 是播放器停止播放的时候耗费的时间。
    
      total time = 29 是播放器开始播放的时候耗费的时间。
      其中,大部分时间耗费在了 5total time = 18 上面,这个是inflate播放器界面的时候耗费的时间。

    这里写图片描述

        是不是所有的inflate都很耗费时间,看一下账号信息页:
    

    这里写图片描述

    这里写图片描述

    • GPU Monitor

    这里写图片描述

    • 启用严格模式(不止渲染性能)
    应用在主线程上执行长时间操作时会闪烁屏幕。
    通过代码进行严格模式(StrictMode)调试,参考:http://www.tuicool.com/articles/ueeM7b6

    二、内存问题

    1、内存浪费

    程序内存的管理是否合理高效对应用的性能有着很大的影响。
    推荐阅读Android性能优化典范-第3季,参考:http://hukai.me/android-performance-patterns-season-3/
    • ArrayMap(我们项目中没有用到,Android源码中很多使用)
    Android为移动操作系统特意编写了一些更加高效的容器,例如ArrayMap、SparseArray。
    为了解决HashMap更占内存的弊端,Android提供了内存效率更高的ArrayMap。

    1、先来看看HashMap的原理

    HashMap的整体结构如下:
    

    这里写图片描述

    存储位置的确定流程:
    

    这里写图片描述

    2、再看来看看ArrayMap是如何优化内存的

    它内部使用两个数组进行工作,其中一个数组记录key hash过后的顺序列表,
    另外一个数组按key的顺序记录Key-Value值,如下图所示:
    

    这里写图片描述

    当你想获取某个value的时候,ArrayMap会计算输入key转换过后的hash值,然后对hash数组使用二分查找法寻找到对应的index,
    然后我们可以通过这个index在另外一个数组中直接访问到需要的键值对。
    

    这里写图片描述

    既然ArrayMap中的内存占用是连续不间断的,那么它是如何处理插入与删除操作的呢?它跟HashMap有什么区别?
    二者之间的删除插入效率有什么差异?请看下图所示,演示了Array的特性:
    

    这里写图片描述

    这里写图片描述

        HashMap与ArrayMap之间的内存占用效率对比图如下:
    

    这里写图片描述

    与HashMap相比,ArrayMap在循环遍历的时候更加高效。
    

    这里写图片描述

    什么时候使用ArrayMap呢?

    1、对象个数的数量级最好是千以内,没有频繁的插入删除操作
    2、数据组织形式包含Map结构
    • Autoboxing(避免自动装箱)

      Autoboxing的行为还经常发生在类似HashMap这样的容器里面,对HashMap的增删改查操作都会发生了大量的autoboxing的行为。
      当key是int类型的时候,HashMap和ArrayMap都有Autoboxing行为。
      
    • SparseArray(项目中用到较多 – 后面再说如何利用工具查找该用SparseArray而没有用到的地方)

      为了避免Autoboxing行为Android提供了SparseArray,此容器使用于key为int类型。
      SparseBooleanMap,SparseIntMap,SparseLongMap等容器,是key为int,value类型相应为boolean、int、long等。
      
    • Enum(枚举,项目中较多使用,应尽量避免)

      Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
      Android官方强烈建议不要在Android程序里面使用到enum。
      
      关于enum的效率,请看下面的讨论。假设我们有这样一份代码,编译之后的dex大小是2556 bytes,
      在此基础之上,添加一些如下代码,这些代码使用普通static常量相关作为判断值:
      

    这里写图片描述

        增加上面那段代码之后,编译成dex的大小是2680 bytes,相比起之前的2556 bytes只增加124 bytes。假如换做使用enum,情况如下:
    

    这里写图片描述

    使用enum之后的dex大小是4188 bytes,相比起2556增加了1632 bytes,增长量是使用static int的13倍。
    不仅仅如此,使用enum,运行时还会产生额外的内存占用,如下图所示:
    

    这里写图片描述

    推荐一些文章:

    2、内存泄漏

    • 什么是内存泄漏?

      一些不用的对象被长期持有,导致内存无法被释放。
      
    • 可能发生内存泄漏的地方有哪些?

    1、内部类引用导致Activity的泄漏

        在Java中,非静态(匿名)内部类会默认隐性引用外部类对象。而静态内部类不会引用外部类对象。
    最典型的场景是Handler导致的Activity泄漏,如果Handler中有延迟的任务或者是等待执行的任务队列过长,
    都有可能因为Handler继续执行而导致Activity发生泄漏。
    
    为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。
    或者是使用Static + WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的。
    举例,MainTabActivity - MainTabHandler:
    

    这里写图片描述

    这里写图片描述

    这里写图片描述

    如何修复?
    

    这里写图片描述

    这里写图片描述

    这里写图片描述

    Android Weak Handler:可以避免内存泄漏的Handler库,参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1123/2047.html
    

    2、Activity Context被传递到其他实例中,这可能导致自身被引用而发生泄漏。

    考虑使用Application Context而不是Activity Context。
    例如:全局Dialog或者Context被单例持有。
    

    3、静态造成的内存泄漏

    这里写图片描述

    这里写图片描述

    4、还有静态变量持有View,例如:

    private static View view;
    
      void setStaticView() {
          view = findViewById(R.id.sv_button);
      }

    5、注意监听器的注销(稍后利用工具分析一个例子)

    regist就要unregist
    

    6、注意Cursor对象是否及时关闭(项目中也存在,不再列举)

    7、WebView的引起的泄漏(暂时没有研究)

    • 使用工具分析定位解决内存泄漏

    1、Memory monitor

    通过MemoryMonitor可以看到,启动手雷进入手雷的内存情况如下(为什么没有做任何操作内存一直在增加?):
    

    这里写图片描述
    这里写图片描述

        通过实例分析一处内存泄漏,操作步骤如下:
    启动手雷 - 进入首页 - 切换底部tab到我的tab - 点击登录弹窗弹窗 - 登录成功返回首页
    

    这里写图片描述
    这里写图片描述

    2、MAT(Memory Analyzer Tool)

    需要下载MAT独立版,可到这里下载解压使用:\\192.168.8.188\上传2\ltsoft
    分析刚才的操作内存情况
    

    这里写图片描述
    这里写图片描述
    这里写图片描述

    进入首页并没有进行任何活动操作,为什么会有那么多bitmap对象呢?
    

    这里写图片描述

    3、LeakCanary

    这里写图片描述

    LeakCanary 中文使用说明,参考:https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
    LeakCanary:让内存泄露无所遁形,参考:https://www.liaohuqiu.net/cn/posts/leak-canary/
    

    4、TraceView(不做详细分析)

    5、GT(应该更适合测试同学测试APP性能)

    利用GT,仅凭一部手机,无需连接电脑,您即可对APP进行快速的性能测试(CPU、内存、流量、电量、帧率/流畅度等等)、
    开发日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等。
    GT官网:http://gt.qq.com/index.html
    
    • 内存使用策略优化

    1、看看下载一个视频加上浏览一下精选页,然后将应用切到后台,内存使用情况

    这里写图片描述

    这里写图片描述
    这里写图片描述

    2、有什么优化内存的策略

    A、onLowMemory():Android系统提供了一些回调来通知当前应用的内存使用情况,通常来说,当所有的background应用都被kill掉的时候,forground应用会收到onLowMemory()的回调。在这种情况下,需要尽快释放当前应用的非必须的内存资源,从而确保系统能够继续稳定运行。

    B、onTrimMemory(int):Android系统从4.0开始还提供了onTrimMemory()的回调,当系统内存达到某些条件的时候,所有正在运行的应用都会收到这个回调,同时在这个回调里面会传递参数,代表不同的内存使用情况,收到onTrimMemory()回调的时候,需要根据传递的参数类型进行判断,合理的选择释放自身的一些内存占用,一方面可以提高系统的整体运行流畅度,另外也可以避免自己被系统判断为优先需要杀掉的应用。

    • 文章推荐:

    1、Android内存优化之OOM:http://hukai.me/android-performance-oom/

    2、内存泄露从入门到精通三部曲之基础知识篇:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=21&extra=page%3D4

    3、内存泄露从入门到精通三部曲之排查方法篇:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=62&extra=page%3D5

    4、内存泄露从入门到精通三部曲之常见原因与用户实践:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=125&highlight=%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2

    3、性能优化必备神器推荐(Lint)

    • 上面分析的一些项目中的问题,怎么找到的呢?

      Lint:静态代码分析工具
      
    • 如何通过Lint查找项目中的问题,如何使用?

    这里写图片描述

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    • 如果只想分析某个文件夹的代码

    这里写图片描述
    这里写图片描述

    • 设置代码分析选项
      这里写图片描述

    三、耗电问题

    例如:关闭屏幕时关闭掉登录ping,屏幕亮时再打开。
    以上的很多问题都会导致耗电量增加。
    如何优化后台下载时的耗电手机发烫问题?
    需要具体的硬件工具测试应用耗电量,需要一套耗电量测试标准。
    

    原文:https://www.jianshu.com/p/307ba8911799

    展开全文
  • 当我们谈到性能优化,更多的同学可能想到的是系统层面的性能优化。比如在一个Web服务程序中,通过Redis或者其它缓存来提升网站访问的速度等。这一方面是编译器为我们做了很多优化工作,另外一方面是觉得系统层面的...
  • 性能优化

    2017-09-19 10:08:11
    JavaScript性能优化小窍门汇总(含实例) 由 youj 创建,最后一次修改 2016-11-28 在众多语言中,JavaScript已经占有重要的一席之地,利用JavaScript我们可以做很多事情 , 应用广泛。在web应用...
  • https://download.csdn.net/download/qq_30353203/10616634,这是一个JVM体系结构与GC调优PPT,写的非常好。 我的技术公众号,有兴趣可以关注一起交流 ...1 性能调优简介 1.1为什么要进行性能调优? ...
  • 网站性能优化注意点

    2019-05-06 19:32:16
    一、网络传输性能优化 重定向→拉取缓存→DNS查询→建立TCP链接→发起请求→接收响应→处理HTML元素→元素加载完成。 (1)设置浏览器缓存 去除network面板顶部的Disable cache 勾选,查看缓存数据来源(from ...
  • 本文全面讲解性能优化中的所有知识,献上一份 Android性能优化的详细攻略, 含:优化方向、原因 &amp; 具体优化方案,希望你们会喜欢 文章较长,建议预留较长时间阅读 / 收藏 目录 1. 性能优化...
  • MySQL性能优化的最佳20+条经验
  • 从V8中看JS性能优化

    2020-06-19 10:15:36
    从V8中看JS性能优化 注意:该知识点属于性能优化领域。 性能问题越来越成为前端火热的话题,因为随着项目的逐步变大,性能问题也逐步体现出来。为了提高用户的体验,减少加载时间,工程师们想尽一切办法去优化...
  • android性能优化在实际开发中会经常应用到,当项目越来越庞大时,性能优化就显得更加重要,写出性能优化代码不但需要丰富的经验,而且还需要了解其原理,这样才有助于我们写出高性能的代码,今天我们来总结一下日常...
  • 面向程序员的数据库访问性能优化法则   特别说明: 1、 本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识; 2、 本文许多示例及概念是...
  • Android性能优化总结

    2015-02-17 17:26:34
    性能优化本身是一个很大的主题,涵盖程序的方方面面,任何不慎的操作,都有可能对性能造成比较大的影响,要知道程序的性能是可以累加的,多处的性能低下,会影响整体的性能,其后果可能也是多方面的,本文总结了目前...
  • 数据库性能优化详解

    2018-01-29 16:23:04
    出处: ...1.数据库访问优化法则 ...要正确的优化SQL,我们需要快速定位能性的瓶颈点,也就是说快速找到我们SQL主要的开销在...而大多数情况性能最慢的设备会是瓶颈点,如下载时网络速度可能会是瓶颈点,本地复制
  • App性能优化浅谈

    2016-02-18 11:04:23
    前言前段时间给公司的小伙伴们进行了关于app性能优化的技术分享,这里我稍微整理一下也给大家分享一下,关于性能优化这个话题很大,涉及面可以很广,也可以很深入,本人能力有限,不会给大家讲特别难懂,特别底层的...
  • 性能优化方法论 在我们历经千辛万苦,通过各种性能分析方法,终于找到引发性能问题的瓶颈后,是不是立刻就要开始优化了呢?别急,动手之前,你可以先看看下面这三个问题。 首先,既然要做性能优化,那要怎么...
  • H5性能优化方案

    2016-08-17 18:06:07
    H5性能优化意义对于一个H5的产品,功能无疑很重要,但是性能同样是用户体验中不可或缺的一环。原本H5的渲染性能就不及native的app,如果不把性能优化做起来,将极大地影响用户使用产品的积极性。用户感受当用户能够...
1 2 3 4 5 ... 20
收藏数 994,193
精华内容 397,677
关键字:

性能优化