app优化篇
Time Profiler分析原理:它按照固定的时间间隔来跟踪每一个线程的堆栈信息,通过统计比较时间间隔之间的堆栈状态,来推算某个方法执行了多久,并获得一个近似值。
平常采用instrument中的core animation进行性能检测
着重优化点:
1、图层的混合:"Color Blended Layers"正是用于检测哪里发生了图层混合,并用红色标记出来。
控件不要设置透明度,默认值opaque = true,记得设置控件的backgroundColor。确保UIImage没有alpha通道。
2、光栅化:Color Hits Green and Misses Red”,它表示如果命中缓存则显示为绿色,否则显示为红色
将一个layer预先渲染成位图(bitmap),然后加入缓存中。如果对于阴影效果这样比较消耗资源的静态内容进行缓存,可以得到一定幅度的性能提升。
光栅化仅适用于较复杂的、静态的效果。
3、正确的图片格式:比如png,jpeg。从网络下载的图片,而GPU恰好不支持这个格式,这就需要CPU预先进行格式转化。“Color Copied Images”就用来检测这种实时的格式转化,如果有则会将图片标记为蓝色。
4、正确的图片尺寸:“Color Misaligned Images”。它表示如果图片需要缩放则标记为黄色,如果没有像素对齐则标记为紫色。
5、离屏渲染:“Color Offscreen-Rendered Yellow”会把需要离屏渲染的地方标记为黄色。
6、手动进行图片解码:采用异步绘制,在display中进行图片的解码操作,主要使用bitmap和colorspace等手段。
7、尤其在scrollview中避免使用xib:直接从代码创建和读文件创建,肯定读文件要慢很多,
8、尤其在复杂视图中不使用autolayout:增加cpu的计算任务
9、采用coretext代替label:label需要计算他的size,进行布局
10、避免动态创建视图:懒加载,设置hidden属性
11、必要时layer代替view:
12、复杂视图必要时合为一张图片处理:
13、异步操作db,计算等工作
14、通知,VoIP,定位,蓝牙等都会使设备从 Standby 状态唤起
15、imageNamed:
与 imageWithContentsOfFile:
的差异
16、少用NSDateFormatter
17、不要随意使用 NSLog()
18、[NSFileManager attributesOfItemAtPath:error:]
会浪费大量时间读取可能根本不需要的附加属性:
#import <sys/stat.h>
struct stat statbuf;
const char *cpath = [filePath fileSystemRepresentation];
if (cpath && stat(cpath, &statbuf) == ) {
NSNumber *fileSize = [NSNumber numberWithUnsignedLongLong:statbuf.st_size];
NSDate *modificationDate = [NSDate dateWithTimeIntervalSince1970:statbuf.st_mtime];
NSDate *creationDate = [NSDate dateWithTimeIntervalSince1970:statbuf.st_ctime];
// etc
}
19、内存泄漏工具:MLeakFinder
20、尽量少使用定时器:会频繁唤醒runloop执行任务
21、异步绘制:VVeboTableViewDemo :异步计算空间frame,将不交互的空间绘制到一张图片中
21、tableview方面:
高度缓存:预先layout、或者UITableView-FDTemplateLayoutCell
cell中不要使用drawRect绘制图片,改用CALayer
的-drawInContext:
Core Animation
将会为这个图层申请一个后备存储,用来保存那些方法绘制进来的位图。那些方法内的代码将会运行在 CPU
上,结果将会被上传到GPU
。
按需加载:VVeboTableViewDemo : 监听runloop的default模式,预加载指定行的样式
离屏渲染:
真正的离屏渲染发生在GPU。
如果要在显示屏上显示内容,我们至少需要一块与屏幕像素数据量一样大的frame buffer,作为像素数据存储区域,而这也是GPU存储渲染结果的地方。如果有时因为面临一些限制,无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域,之后再写入frame buffer,那么这个过程被称之为离屏渲染。
常见的触发离屏渲染场景:
1、cornerRadius+clipsToBounds:
容器的子layer因为父容器有圆角,那么也会需要被裁剪,而这时它们还在渲染队列中排队,尚未被组合到一块画布上,自然也无法统一裁剪。
此时我们就不得不开辟一块独立于frame buffer的空白内存,先把容器以及其所有子layer依次画好,然后把四个角“剪”成圆形,再把结果画到frame buffer中。
2、shadow:
阴影默认是作用在其中”非透明区域“的,而且需要显示在所有layer内容的下方,阴影的本体(layer和其子layer)都还没有被组合到一起,怎么可能在第一步就画出只有完成最后一步之后才能知道的形状呢?这样一来又只能另外申请一块内存,把本体内容都先画好,再根据渲染结果的形状,添加阴影。不过如果我们能够预先告诉CoreAnimation(通过shadowPath属性)阴影的几何形状,那么阴影当然可以先被独立渲染出来,不需要依赖layer本体。
3、group opacity:
alpha并不是分别应用在每一层之上,而是只有到整个layer树画完之后,再统一加上alpha,最后和底下其他layer的像素进行组合。显然也无法通过一次遍历就得到最终结果。
4、mask:
我们知道mask是应用在layer和其所有子layer的组合之上的,而且可能带有透明度,那么其实和group opacity的原理类似。
5、渐变。
6、shouldRasterize
尽管离屏渲染开销很大,但是当我们无法避免它的时候,可以想办法把性能影响降到最低。
shouldRasterize。一旦被设置为true,Render Server就会强制把layer的渲染结果(包括其子layer,以及圆角、阴影、group opacity等等)保存在一块内存中,这样一来在下一帧仍然可以被复用,而不会再次触发离屏渲染。
layer的内容(包括子layer)必须是静态的,因为一旦发生变化(如resize,动画),之前辛苦处理得到的缓存就失效了。
如果layer的子结构非常复杂,渲染一次所需时间较长,同样可以打开这个开关,把layer绘制到一块缓存,然后在接下来复用这个结果,这样就不需要每次都重新绘制整个layer树了。
开启“Color Hits Green and Misses Red”来检查该场景下光栅化操作是否是一个好的选择。绿色表示缓存被复用,红色表示缓存在被重复创建。
启动和优化:
iOS的启动流程
1、根据 info.plist 里的设置加载闪屏,建立沙箱,对权限进行检查等
2、加载可执行文件
3、加载动态链接库,进行 rebase 指针调整和 bind 符号绑定
4、Objc 运行时的初始处理,包括 Objc 相关类的注册、category 注册、selector 唯一性检查等;
5、初始化,包括了执行 +load() 方法、attribute((constructor)) 修饰的函数的调用、创建 C++ 静态全局变量。
6、执行 main 函数
7、Application 初始化,到 applicationDidFinishLaunchingWithOptions 执行完
8、初始化帧渲染,到 viewDidAppear 执行完,用户可见可操作。
启动优化
1、减少动态库的加载
2、减少系统库和第三方库的加载
3、去除掉无用的类和C++全局变量的数量,减少项目文件中Category,静态变量等的使用数量
4、尽量让load方法中的内容放到首屏渲染之后再去执行,或者使用initialize替换
5、去除在首屏展现之前非必要的功能
6、检查首屏展现之前主线程的耗时方法,将没必要的耗时方法滞后或者延迟执行
AutoLayout:
- 预编译:主要处理以“#”开始的预编译指令。
- 编译:
- 词法分析:将字符序列分割成一系列的记号。
- 语法分析:根据产生的记号进行语法分析生成语法树。
- 语义分析:分析语法树的语义,进行类型的匹配、转换、标识等。
- 中间代码生成:源码级优化器将语法树转换成中间代码,然后进行源码级优化,比如把 1+2 优化为 3。中间代码使得编译器被分为前端和后端,不同的平台可以利用不同的编译器后端将中间代码转换为机器代码,实现跨平台。
- 目标代码生成:此后的过程属于编译器后端,代码生成器将中间代码转换成目标代码(汇编代码),其后目标代码优化器对目标代码进行优化,比如调整寻址方式、使用位移代替乘法、删除多余指令、调整指令顺序等。
- 汇编:汇编器将汇编代码转变成机器指令。
- 静态链接:链接器将各个已经编译成机器指令的目标文件链接起来,经过重定位过后输出一个可执行文件。
- 装载:装载可执行文件、装载其依赖的共享对象。
- 动态链接:动态链接器将可执行文件和共享对象中需要重定位的位置进行修正。
- 最后,进程的控制权转交给程序入口,程序终于运行起来了。
异步绘制:
改变frame、更新UIView/CALayer,或者自己去调用setNeedsLayout/setNeedsDisplay
方法,内部调用流程为:
当前runloop
即将结束的时候调用CALayer
的display
方法;
系统绘制流程为:
CGBitmapContextCreate()
可以创建一个CGCentextRef
,在异步线程使用这个context进行绘制。- (void)display {
dispatch_async(backgroundQueue, ^{
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
///获取当前上下文
CGContextRef context = UIGraphicsGetCurrentContext();
///将坐标系反转
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
///文本沿着Y轴移动
CGContextTranslateCTM(context, 0, size.height);
///文本反转成context坐标系
CGContextScaleCTM(context, 1.0, -1.0);
///创建绘制区域
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0, 0, size.width, size.height));
///创建需要绘制的文字
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:self.asynText];
[attStr addAttribute:NSFontAttributeName value:self.asynFont range:NSMakeRange(0, self.asynText.length)];
[attStr addAttribute:NSBackgroundColorAttributeName value:self.asynBGColor range:NSMakeRange(0, self.asynText.length)];
///根据attStr生成CTFramesetterRef
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attStr);
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, attStr.length), path, NULL);
///将frame的内容绘制到content中
CTFrameDraw(frame, context);
UIImage *getImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
///子线程完成工作, 切换到主线程展示
dispatch_async(dispatch_get_main_queue(), ^{
self.layer.contents = (__bridge id)getImg.CGImage;
});
});
}
网络层的优化:
减少DNS请求,使用HttpDNS获取原始ip地址进行请求,在header请求头中增加host字段,指定为原始请求地址
数据传输使用gzip
合并请求,减少请求并发数(埋点SDK,crash日志收集)
使用断点续传,否则网络不稳定时可能多次传输相同的内容
结合ETag 和 Last-Modified 减少数据重复传输
网络请求本地缓存
避免频繁发起请求
请求失败缓存后重发请求
2G、3G、4G、wifi下设置不同的超时时间
弱网环境下,减少并发请求
http2本身支持的长连接,多路复用机制
网络不可用时,不要进行网络请求
上传和下载大数据时,一次下载多点
app优化篇的更多相关文章
- 百度APP移动端网络深度优化实践分享(二):网络连接优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<二>连接优化>,感谢原作者的无私分享. 一.前言 在<百度APP移动端网 ...
- 百度APP移动端网络深度优化实践分享(一):DNS优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<一>DNS优化>,感谢原作者的无私分享. 一.前言 网络优化是客户端几大技术方 ...
- 百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<三>弱网优化>,感谢原作者的无私分享. 一.前言 网络优化解决的核心问题有三个 ...
- 【转】Android性能优化之布局优化篇
转自:http://blog.csdn.net/feiduclear_up/article/details/46670433 Android性能优化之布局优化篇 分类: andorid 开发2015 ...
- 【HELLO WAKA】WAKA iOS客户端 之一 APP分析篇
由于后续篇幅比较大,所以调整了内容结构. 全系列 [HELLO WAKA]WAKA iOS客户端 之一 APP分析篇 [HELLO WAKA]WAKA iOS客户端 之二 架构设计与实现篇 [HELL ...
- HTML5进阶(三)HBuilder实现软件自动升级(优化篇)
HBuilder实现软件自动升级(优化篇) 前言 受前篇博客<HTML5进阶(二)HBuilder实现软件自动升级>(点击查看详情)的影响,测试过程中发现APP自动更新还是存在问题,第一次 ...
- Hybrid APP基础篇(二)->Native、Hybrid、React Native、Web App方案的分析比较
说明 Native.Hybrid.React.Web App方案的分析比较 目录 前言 参考来源 前置技术要求 楔子 几种APP开发模式 概述 Native App Web App Hybrid Ap ...
- Android App优化之ANR详解
引言 背景:Android App优化, 要怎么做? Android App优化之性能分析工具 Android App优化之提升你的App启动速度之理论基础 Android App优化之提升你的App ...
- Hybrid APP基础篇(四)->JSBridge的原理
说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:J ...
随机推荐
- “2014年CityEngine三维建模与设计精英培训班”——全国巡回举办
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYXJjZ2lzX2FsbA==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- 【转载】Hadoop官方文档翻译——HDFS Architecture 2.7.3
HDFS Architecture HDFS Architecture(HDFS 架构) Introduction(简介) Assumptions and Goals(假设和目标) Hardware ...
- golang:iconv
最近在做邮件解析的工作,遇到需要转字符集编码的情况,go官方好像没有提供这样的库,于是从github上找了一下. https://github.com/qiniu/iconv 开发环境: linux ...
- Git命令速查表
- perl 里面如何写出阅读友好的代码提示
在我们使用别人写好的程序时,经常会使用-h 之类的东西查看一下简单的帮助手册或者说明信息: 对于perl 语言而言,写起来简单,经常随手一写,解决了当时的问题,但是过几天去看,你都不知道这个脚本该怎么 ...
- C# 获取对象 大小 Marshal.SizeOf (sizeof 只能在不安全的上下文中使用)
C# 能否获取一个对象所占内存的大小? 今日,在项目重构的时候忽然想到一个问题,一个类哪些成员的增加,会影响一个类所占内存的大小?C#有没有办法知道一个对象占多少内存呢? 第一个问题:很快想到是类的非 ...
- bootstarpTable load data
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> ...
- 自动化测试工具Ranorex的录制功能使用
由于帆软的 Report 包含gui和web端 设计器 web预览 做自动化测试不适合使用 Katalon 发现了Ranorex Ranorex 是一款在Windows操作系统的上运行的GUI自动测试 ...
- nginx && apache 图片代理
location ~ /mmopen/ { proxy_set_header Host thirdwx.qlogo.cn; rewrite /(.+)$ /$ break; proxy_pass ht ...
- hello 2019 D
一开始sb了考虑总的因子疯狂T,做题太少了...没意识到会有辣么多因子... 神仙说1e9以内的最多的就有800个因子的了... 然后我们可以考虑质因子 我觉得已经说得很明白了... 唔逆元好像exg ...