百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

性能优化案例之app卡顿优化

ztj100 2024-11-22 00:13 24 浏览 0 评论

享学课堂诚邀作者:周周

转载请声明出处!

前言

手把手讲解系列文章,是我写给各位看官,也是写给我自己的。

文章可能过分详细,但是这是为了帮助到尽量多的人,毕竟工作5,6年,不能老吸血,也到了回馈开源的时候.

这个系列的文章:

1、用通俗易懂的讲解方式,讲解一门技术的实用价值

2、详细书写源码的追踪,源码截图,绘制类的结构图,尽量详细地解释原理的探索过程

3、提供Github 的 可运行的Demo工程,但是我所提供代码,更多是提供思路,抛砖引玉,请酌情cv

4、集合整理原理探索过程中的一些坑,或者demo的运行过程中的注意事项

5、用gif图,最直观地展示demo运行效果**

如果觉得细节太细,直接跳过看结论即可。

本人能力有限,如若发现描述不当之处,欢迎留言批评指正。

学到老活到老,路漫漫其修远兮。与众君共勉 !

本文接上一篇

正文大纲

  • DDMS
  • systrace
  • TraceView
  • 关于过度绘制

正文

DDMS

DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik[虚拟机]调试监控服务

以前用eclipse的时候,有个直接的入口可以打开DDMS,但是自从用了AndroidStudio,入口没了....但是其实在SDK目录内部还是有的.

打开DDMS之后:

具体有啥用,稍后再说。

systrace

systrace是sdk的一个命令,它是用python语言写的,当时用的是python2.7,但是后来python更新了3.0 谷歌却没有更新这个命令,导致我们现在要使用systrace命令,只能用python的2.7版本,正常情况下,用2.7的最新版2.7.16就行了,官网有下载的。

那么systrace命令在哪里?

前提

要使用它,首先我们要安装好python2.7.16,然后配置环境变量,直到我们能够正常使用python命令(这个没必要详述吧,囧- -!,但是我还是给出本人验证过的攻略地址:https://www.jianshu.com/p/e73768e66b8d).

正戏

systrace是我们用来抓取一段时间之内的android设备上的数据指标的工具,我理解为: 设备运行日志,只不过这不是文本日志,而是一个html文件,需要使用谷歌浏览器的 chrome://tracing/插件打开。具体步骤如下:

1、打开CMD,进入systrace目录:

2、输入 python systrace.py -b 32768 -t 5 -o mytrace.html wm gfx input view sched freq,然后回车

解释一下这一串命令(本文不做systrace命令的详解,这些东西都是死命令,百度即可):

  • python 将要执行python脚本
  • systrace.py 脚本名称
  • -b 设置缓存区大小
  • -t 抓取5秒日志
  • -o mytrace.html 输出到这个文件内
  • wm WindowManager 日志内包含windowManager信息
  • gfx Graphics 日志中包含图形绘制的信息
  • input Input 日志中包含设备输入的信息
  • view View System 日志中包含View系统的信息
  • sched CPU Scheduling 日志中包含CPU调度信息
  • freq 日志中包含CPU频率信息

这里有个坑:

在某些真机上,比如vivo X7,它会生成html文件失败,莫名其妙,我换成模拟器,就好了,尚未试验其它真机机型。

我使用网易mumu模拟器做实验的时候,得到如下结果:

3、得到文件之后,打开谷歌浏览器:在地址栏输入 chrome://tracing/ 然后load刚才的文件:( 或者你双击该html文件)

4、这里我们得到了非常多的性能指标,包括上图中红色字体标记的CPU用量,多核CPU调度情况,UI主线程,渲染线程等,但是我们应用层开发,解决的主要是app卡顿问题,一般只需要 去关注 UI主线程的掉帧情况即可. 按照下图:

  • 详解一下这个带圈的F:整个坐标,横轴为时间,从左到右时间刻度增加,代表各项指标随着时间的变化
  • 带圈的F : 有绿色,黄色和红色。其中绿色表示绘制正常,无需我们去关心,需要关注的是 黄色和红色,特别是红色。
  • 鼠标点击其中一个红色的F,然后按键盘G键,就会出现红色的竖线,每两根红线之间代表一帧的时长(大部分手机的屏幕刷新频率还是60帧,所以每次绘制大概是16.67MS),这个F之所以是红色,是因为这一次的UI绘制时长远远超过了1帧,如果UI在1帧时间之内无法完成,便会造成掉帧,一旦掉帧,在用户的感知下,就是卡顿.
  • 看下图:

使用鼠标拖拽,可以通过图形界面看到这一次绘制所花费的时长:为116.868ms

在下面的Alert栏中发现了疑似掉帧元凶

这里反映出,是我们的bitmap图上传导致了掉帧。

我们继续把下面两个箭头展开,能够看到:

这里的英文描述,则是 谷歌工程师给我们的建议.我来大概翻译一下这段话:

  • 第一段的description意思是:修改/新绘制的位图必须上传到GPU。因为如果上传的总像素量很大,这是很昂贵的,所以每帧减少这个动画/上下文中位图的波动量。
  • 第二段description的意思是:生成这个帧的工作被重新调度了几毫秒,这是jank的功劳。确保UI线程上的代码不会阻塞其他线程上的工作,并且后台线程(例如网络或位图加载)在android.os上运行。进程#THREAD_PRIORITY_BACKGROUND或更低,因此它们不太可能中断UI线程。这些后台线程应该在内核进程的调度部分以130或更高的优先级出现。
  • 总的来说,就是Bitmap的使用不当导致掉帧,解决方法大概是:bitmap太大了 要裁剪成合适的大小 或者在背景线程去加载
  • 至于更加具体的其他掉帧情况的解决方法,就要根据具体遇到的情况去查资料了。

关于Trace.beginSection 和 Trace.endSection

这两个api是androidSdk自带的,作用是给systrace加上tag,加了tag,就会在systrace图形上反映出我们这两个api之间囊括的一段代码的执行情况。

简单来说,就是你在 一段代码的前后,加上 Trace.beginSection 和 Trace.endSection ,像这样:

那么,你在 systrace图形上就会发现这个。

可见,我们代码的执行耗时等情况可以 反映在systrace图形上,点击上面红框的区域,就会在systrace界面底部发现:

如果加了tag的代码的执行耗时超过了一帧时长(16.67MS),则说明这一段代码造成了UI主线程掉帧,用户就有可能感觉到卡顿。

这里有个坑

如果你上面加了trace.beginSection和endSection,你在图形中还是没有看到 你自己设置的tag,那么检查一下你的 systrace命令,是不是没有加 -a [app包名]


做个结论

上述例子,我使用的是app冷启动时抓的systrace,所以这里的掉帧,就是反映出冷启动过程中代码写的有问题。注意,抓systrace的时间不要太长,必须在systrace开始执行之后再操作app。

在发现掉帧的情况之后,看alert就能看出谷歌给我们的app优化方向建议,虽然还没有完全解决问题,但是至少确定了一个大方向,知道了大概哪一段代码出了问题。

TraceView

在app代码中加入 Debug.startMethodTracing("/sdCard/zhouzhou");和Debug.stopMethodTracing(); 然后运行app,确保能够执行上面两个代码包含的代码片段 。比如像这样:

坑坑

上面的代码,如果你加了之后运行直接抛了异常,检查一下你有没有加这个权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

接下来,找到这个文件,导出到电脑上:

然后就要用到我们最先说道的DDMS,先打开DDMS,File- openFile 打开刚才的.trace文件


这里包含了这段代码中所有的方法调用。

表格说明

上方有一张表格,每一列的说明如下:

这么多东西,我们不可能全都关注,只需要关注两个:

  • Cpu Time/Call 函数平均执行时间较长的函数;(耗时较长的函数)
  • Call+Recur Calls/Total,调用次数非常频繁的函数。

如果发现,上面两个指标超乎寻常,比如调用次数特别多,每一次调用耗费时间特别长的,而且又能够是我们自己写的方法,那么基本上就能确定优化点了。

关于过度绘制

概念:如果屏幕的一片区域,在渲染的过程中,被绘制了太多次,则称为过度绘制。

如何检查:

上图是mumu模拟器的设置界面,我们点击显示过度绘制区域,就会发现界面颜色发生了变化:

颜色由浅到深,越深,表示过渡绘制会越严重。大致有以下几种颜色:白色:没有过度绘制。

  • 蓝色:Overdraw 一倍。像素绘制了两次,能够接受,但是如果整个界面都是蓝色的,那么说明还是有绘制的浪费,可以节约一层绘制。
  • 绿色:Overdraw 两倍。尝试优化。
  • 浅红:Overdraw 三倍。
  • 暗红:Overdraw 四倍。非常严重,必须优化。

如何优化过渡绘制?

  • 如果你的代码中,通过过度绘制的检查,发现复杂布局显示出大量的过度绘制,那么必须要考虑 用自定义View自己去绘制。
  • 如果你的布局xml中,有大量的嵌套,考虑去掉某些 background ,因为没有了background,UI线程就不会去做这一次绘制
  • 如果非要用到有background的layout,那么在满足业务需求的情况下考虑减少一定的层级。

结语

上述3个工具的使用,是我们app性能优化中必须用到的。大概思路如下

1.用systrace 抓取 .html文件,观察图形,找出掉帧的大概位置

2. 用 Trace.beginSection 和 Trace.endSection 反复推测,确定确切代码块

3. 用traceView抓取.trace日志,用DDMS打开它,寻找耗时较长的函数 或 次数非常多的函数,确定确切掉帧原因

三个工具需要结合使用,才能具体确定我们的app哪里出了问题。

话题拓展

本文只给出了大致思路,并没有给出Demo,这是因为 性能优化可能出现的情况太多了,无法一一列举,具体发生了什么,只有到发生之后,自行根据工具检测出的结果去推断,去论证,去解决。

性能优化是无止境的,永远有能够优化的空间。本文只给出了大致指导方向,具体能够优化到何种程度,全看各位的自我修为。

上面的3个工具,可以用来做性能优化, 但是他们的作用不仅仅是性能优化,千万不要一叶障目。比如systrace这个东西,上述文章我只用来检查了卡顿掉帧的情况,但是它其实还可以 查看CPU调度情况和CPU多核分配情况,还可以检查主线程的线程状态切换情况等。

下一篇预告:内存抖动和泄漏的优化

你的赞和关注是我继续创作的动力~

相关推荐

WPS 隐藏黑科技!OCT2HEX 函数用法全攻略,数据转换不再愁

WPS隐藏黑科技!OCT2HEX函数用法全攻略,数据转换不再愁在WPS表格的强大函数库中,OCT2HEX函数堪称数据进制转换的“魔法钥匙”。无论是程序员处理代码数据,还是工程师进行电路设计...

WPS 表格隐藏神器!LEFTB 函数让文本处理更高效

WPS表格隐藏神器!LEFTB函数让文本处理更高效在职场办公和日常数据处理中,WPS表格堪称我们的得力助手,而其中丰富多样的函数更是提升效率的关键。今天,要为大家介绍一个“宝藏函数”——LEF...

Java lombok 使用教程(lombok.jar idea)

简介Lombok是...

PART 48: 万能结果自定义,SWITCH函数!

公式解析SWITCH:根据值列表计算表达式并返回与第一个匹配值对应的结果。如果没有匹配项,则返回可选默认值用法解析1:评级=SWITCH(TRUE,C2>=90,"优秀",C2...

Excel 必备if函数使用方法详解(excel表if函数使用)

excel表格if函数使用方法介绍打开Excel,在想输出数据的单元格点击工具栏上的“公式”--“插入函数”--“IF”,然后点击确定。...

Jetty使用场景(jetty入门)

Jetty作为一款高性能、轻量级的嵌入式Web服务器和Servlet容器,其核心优势在于模块化设计、快速启动、低资源消耗...

【Java教程】基础语法到高级特性(java语言高级特性)

Java作为一门面向对象的编程语言,拥有清晰规范的语法体系。本文将系统性地介绍Java的核心语法特性,帮助开发者全面掌握Java编程基础。...

WPS里这个EVEN 函数,90%的人都没用过!

一、开篇引入在日常工作中,我们常常会与各种数据打交道。比如,在统计员工绩效时,需要对绩效分数进行一系列处理;在计算销售数据时,可能要对销售额进行特定的运算。这些看似简单的数据处理任务,实则隐藏着许多技...

64 AI助力Excel,查函数查用法简单方便

在excel表格当中接入ai之后会是一种什么样的使用体验?今天就跟大家一起来分享一下小程序商店的下一步重大的版本更新。下一个版本将会加入ai功能,接下来会跟大家演示一下基础的用法。ai功能规划的是有三...

python入门到脱坑 函数—函数的调用

Python函数调用详解函数调用是Python编程中最基础也是最重要的操作之一。下面我将详细介绍Python中函数调用的各种方式和注意事项。...

Excel自定义函数:满足特定需求的灵活工具

...

从简到繁,一文说清vlookup函数的常见用法

VLOOKUP函数是Excel中常用的查找与引用函数,用于在表格中按列查找数据。本文将从简单到复杂,逐步讲解VLOOKUP的用法、语法、应用场景及注意事项。一、VLOOKUP基础:快速入门1.什么是...

Java新特性:Lambda表达式(java lambda表达式的3种简写方式)

1、Lambda表达式概述1.1、Lambda表达式的简介Lambda表达式(Lambdaexpression),也可称为闭包(Closure),是Java(SE)8中一个重要的新特性。Lam...

WPS 冷门却超实用!ODD 函数用法大揭秘,轻松解决数据处理难题

WPS冷门却超实用!ODD函数用法大揭秘,轻松解决数据处理难题在WPS表格庞大的函数家族里,有一些函数虽然不像SUM、VLOOKUP那样广为人知,却在特定场景下能发挥出令人惊叹的作用,OD...

Python 函数式编程的 8 大核心技巧,不允许你还不会

函数式编程是一种强调使用纯函数、避免共享状态和可变数据的编程范式。Python虽然不是纯函数式语言,但提供了丰富的函数式编程特性。以下是Python函数式编程的8个核心技巧:...

取消回复欢迎 发表评论: