看看别家的APP性能优秀不?

栏目: IOS · 发布时间: 5年前

内容简介:APP的性能大家应该都比较关注,那么咱们的自己APP性能如何呢?如何在拿不到源码的情况下去调试第三方应用的性能呢?下面我就简单实践一下。就以比较著名的今日头条和贝壳找房为例吧!大家看看自己的APP和他们还有多少差距。下面我们对这个指标以2个APP进行性能分析,分别是贝壳找房2.6.1版本、今日头条7.2.2版本。手机我们使用12.2系统的iPhoneX。我们借助于Instruments中的Activity Monitor工具进行分析。首先我们去拿到这几个ipa的脱壳包(这里可以借鉴这两篇文章,传送门一->点

APP的性能大家应该都比较关注,那么咱们的自己APP性能如何呢?如何在拿不到源码的情况下去调试第三方应用的性能呢?下面我就简单实践一下。就以比较著名的今日头条和贝壳找房为例吧!大家看看自己的APP和他们还有多少差距。

二、分析启动时和启动后的cpu和内存占用

下面我们对这个指标以2个APP进行性能分析,分别是贝壳找房2.6.1版本、今日头条7.2.2版本。手机我们使用12.2系统的iPhoneX。我们借助于Instruments中的Activity Monitor工具进行分析。首先我们去拿到这几个ipa的脱壳包(这里可以借鉴这两篇文章,传送门一->点击我, 传送门二->点击我;或者可以去越狱市场直接下载脱壳好的包),脱壳后使用development的证书进行重签名(可以参考:传送门->点击我)。然后我们将这两个包安装到手机中去。

如图:

看看别家的APP性能优秀不?

以下我们分别对这2个APP测试APP启动前5秒的CPU峰值以及对应的内存占用和启动后某一平稳时段的CPU占用以及对应的内存。

2.1

先看今日头条的数据:

如图:

看看别家的APP性能优秀不?

今日头条在前5秒的CPU峰值达到了148.1%,此时的内存占用是63.66M

然后我们再看看启动后的平稳数据

如图:

看看别家的APP性能优秀不?

CPU是3.9%,此时的内存占用是102.06M

2.2

我们再看贝壳找房的数据:

如图:

看看别家的APP性能优秀不?

贝壳找房在前5秒的CPU峰值达到了116.4%,此时的内存占用是77.30M

然后我们再看看启动后的平稳数据

如图:

看看别家的APP性能优秀不?

CPU是2.9%,此时的内存占用是77.02M

从以上数据看,两个APP的突发峰值都还好,平峰比较稳定,大家可以对比看下自己的APP是否和他们差不多,我们再看下一个指标,APP启动时间。

三、分析APP启动时常

下面我们使用 MonkeyDev (传送门-> 点击我 ) 工具将上面的那两个包运行起来,在Environment Variables中加入DYLD_PRINT_STATISTICS变量,得到Total pre-main time。我们对每个APP分别测量3次,取平均值。

如图:

看看别家的APP性能优秀不?

3.1

我们先看今日头条的3次测量数据

第一次:

看看别家的APP性能优秀不?

第二次:

看看别家的APP性能优秀不?

第三次:

看看别家的APP性能优秀不?

得到最终今日头条的平均值是:1.3s

3.2

然后我们再看贝壳找房的3次数据

第一次:

看看别家的APP性能优秀不?

第二次:

看看别家的APP性能优秀不?

第三次:

看看别家的APP性能优秀不?

得到最终贝壳找房的平均值是:954.66ms

从以上数据分析,各个APP之间的pre-main之间耗费的时间差别并不多,我们看下各个内容的含义。

  • dylib loading time
    载入动态库,这个过程中,会去装载app使用的动态库,而每一个动态库有它自己的依赖关系,所以会消耗时间去查找和读取。对于Apple提供的的系统动态库,做了高度的优化。而对于开发者定义导入的动态库,则需要在花费更多的时间。Apple官方建议尽量少的使用自定义的动态库,或者考虑合并多个动态库,其中一个建议是当大于6个的时候,则需要考虑合并它们
  • rebase/binding time

    重构和绑定,rebase会修正调整处理图像的指针,并且会设置指向绑定(binding)外部的图像指针。所以为了加快rebase/binding,则需要更少的做指针修复。当你的app当中有太多的Objective-C的类,方法选择器,和类别会增加这一部分的启动时间。有一个数据当大于20000个时候,会增加800ms的时间。另一点:当你的app中使用了很少的C++的虚拟函数,使用Swift会更加高效

  • ObjC setup time

    在Objective-C的运行时(runtime),需要对类(class),类别(category)进行注册,以及选择器的分配,所以参照rebase/binding time,尽量减少类的数量,可以达到减少这一部分的时间

  • initializer time

    这一份指代的是执行+initialize方法的时间。如果你执行了+load方法(不建议),尽量使用+initialize代替。

  • slowest intializers

    这个列出的是最慢的几个dylib文件。

从以上数据来看,他们大致的耗时操作都差不多,需要从以上几点进行一下优化。不过我看来优化启动的时间应该从pre-main之后入手,测试main到第一个viewcontroller的viewDidAppear的时间。

四、分析APP第一个控制器的启动时间

下面我以贝壳找房进行详细描述,用FLEXible获取贝壳找房的首页控制器名称

如图:

看看别家的APP性能优秀不?

然后我们注入如下代码:获取首页控制器的viewDidLoad到viewDidAppear的执行时间

CHDeclareClass(LJHomePageViewController)

CHOptimizedMethod1(self, void, LJHomePageViewController, viewDidAppear, BOOL, animated)
{
    CHSuper1(LJHomePageViewController, viewDidAppear, animated);
    NSLog(@"第一个视图完毕");
    // 得到加载时间
    NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:self.testDate];
    NSLog(@":blush::blush::blush::blush::blush::blush::blush::blush::blush::blush::blush::blush:%g", duration);
}

CHOptimizedMethod0(self, void, LJHomePageViewController, viewDidLoad)
{
    CHSuper0(LJHomePageViewController, viewDidLoad);
    YYFPSLabel *fpsLabel = [YYFPSLabel new];
    fpsLabel.frame = CGRectMake(180, 200, 120, 30);
    [fpsLabel sizeToFit];
    [[UIApplication sharedApplication].delegate.window addSubview:fpsLabel];

    NSDate *date = [NSDate date];
    // 保存开始时间
    self.testDate = date;
}

////add new property
CHPropertyRetainNonatomic(LJHomePageViewController, NSDate*, testDate, setTestDate);

CHConstructor{
    CHLoadLateClass(LJHomePageViewController);
    CHClassHook0(LJHomePageViewController, viewDidLoad);
    CHClassHook1(LJHomePageViewController, viewDidAppear);

    CHHook0(LJHomePageViewController, testDate);
    CHHook1(LJHomePageViewController, setTestDate);

}

看看别家的APP性能优秀不?

可以看到他第一个控制器的时间约为0.24s,当然网络请求后的渲染时间此处是没有统计的,有兴趣的大家可以再hook网络那部分。

五、分析APP主要列表的FPS

这里我以今日头条为例子,使用FLEXible获取今日头条的主页面,然后分别对各个主页面的viewDidLoad方法进行Hook,然后在这里加入YYFPSLabel。这里直接对APPDelegate进行Hook也可以。

如图:

看看别家的APP性能优秀不?

以下是hook的代码:

@interface TTFeedCollectionViewController
- (void)viewDidLoad;
@end

CHDeclareClass(TTFeedCollectionViewController)

CHOptimizedMethod0(self, void, TTFeedCollectionViewController, viewDidLoad)
{
    CHSuper0(TTFeedCollectionViewController, viewDidLoad);
    YYFPSLabel *fpsLabel = [YYFPSLabel new];
    fpsLabel.frame = CGRectMake(180, 200, 50, 30);
    [fpsLabel sizeToFit];
    [[UIApplication sharedApplication].delegate.window addSubview:fpsLabel];
}

CHConstructor{
    CHLoadLateClass(TTFeedCollectionViewController);
    CHClassHook0(TTFeedCollectionViewController, viewDidLoad);
}

然后我们就可以看到所有页面的帧率

如图:

看看别家的APP性能优秀不?

此处页面稳定后的帧率是接近60,可以看出今日头条优化的还是可以的。

六、总结:

以上是以今日头条和贝壳找房进行了下实践,大家感兴趣可以多试试,然后对比自己的应用,看看有没有需要提高的。另外可以借鉴逆向的思维,去调试一些东西,挖掘和大厂APP之间的差距。这就是这篇文章的初衷。

打赏作者

如果这篇文章帮助了你,可以请作者喝罐可乐,以此激励作者创作更多!

去打赏

支持: 微信支付 支付宝

您的支持将鼓励我继续创作!

看看别家的APP性能优秀不?

[微信] 扫描二维码打赏

看看别家的APP性能优秀不?

[支付宝] 扫描二维码打赏


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

实用Common Lisp编程

实用Common Lisp编程

Peter Seibel / 田春 / 人民邮电出版社 / 2011-10 / 89.00元

由塞贝尔编著的《实用Common Lisp编程》是一本不同寻常的Common Lisp入门书。《实用Common Lisp编程》首先从作者的学习经过及语言历史出发,随后用21个章节讲述了各种基础知识,主要包括:REPL及Common Lisp的各种实现、S-表达式、函数与变量、标准宏与自定义宏、数字与字符以及字符串、集合与向量、列表处理、文件与文件I/O处理、类、FORMAT格式、符号与包,等等。......一起来看看 《实用Common Lisp编程》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具