Framework - 性能统计

摘要

近期对接客户时,客户方希望提供 SDK 的性能、内存、隐私支持等一些数据,所以就对 SDK 进行了一些性能测试。

在用表格统计整理这些数据时,突然发现,经常用统计的方式看 SDK 的相关数据,似乎也是一个发现优化的好方式。

所以想记录下来统计表格式、测试工具等,方便后面去优化 SDK。

SDK 数据表格

首先把 SDK 中性能、内存有关的数据给整理一下,我这边做成如下图的表格,方便统计和查看。

Framework - 性能统计

接下来,按照表格中的各个项目,去获取。

性能数据

CPU 消耗和内存消耗,这两个数据可以直接通过 Xcode 中获取到。把程序运行起来后,按照下图切换到这个面板,就可以查看到 CPU 消耗和内存消耗的实时数值。这里获取到分别是它们的最大值。

Framework - 性能统计

CPU 消耗

这里比较有意思的数据是 CPU。看到 CPU 的刻度能到 600%,为什么这么大?

因为我这是用的手机是 iphone 12Pro,它有 6 CPU,所以它的 CPU 最高就是 6 个 CPU满载运行,即 600%。所以获取到的值需要除以 6 才是真正的 CPU 消耗占比

这里用到不同设备获取 CPU,在上图的面板中都会获取到不同的数值,所以,不可以拿面板中的值直接去放在其他设备上计算获得,比如不能直接除以 2 获取到 iphone 7 的 CPU 消耗占比。

内存消耗

内存消耗,是整体跑完 SDK 的功能之后,获取到内存消耗的最大值。这里在统计数据时要记得减去初始内存消耗,也就是不运行 SDK 中的功能时的内存消耗。

因为在 APP 启动完成时,也会需要内存消耗,这部分的内存消耗是维持 APP 正常运行,使用 SDK 的功能时,就会在这个基础上去增加它的内存消耗。

FPS(每秒传输帧数-Frames Per Second)

FPS 是图像领域中的定义,是指画面每秒传输帧数,每秒帧数越多,所显示的动作就会越流畅。通常,要避免动作不流程的最低是 30。

FPS 也可以理解为常说的“刷新率(单位为 Hz)‘,比如,75 Hz 的刷新率指屏幕一秒内只扫描 75 次,即 75 帧/秒。

监测 FPS

苹果提供 CADisplayLink 类监测 FPS。CADisplayLink 可以创建一个计时对象,允许应用程序将绘图与显示的刷新率同步。

下面是相关的代码:

import UIKit
class FPSLabel: UILabel {
 
    private var link:CADisplayLink?
    private var lastTime:TimeInterval = 0.0;
    private var count:Int = 0;
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        //receiver是指didTick方法
        link = CADisplayLink.init(target: self, selector: #selector(FPSLabel.didTick(link:)))
        
        //commom会无论用户的app处于什么停止还是滑动都会进行fps打印(commonMode会添加timer到所有mode上面)
        link?.add(to: RunLoop.current, forMode: .common)
    }
    
    required init?(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
    }
    
    @objc func didTick(link:CADisplayLink) {
        
        if lastTime == 0 {
            
            lastTime = link.timestamp
            return
        }
        //用来记录一秒进入这个方法多少次,如果进入了20次那么count就变成20,20帧
        count += 1
        //在一秒内打印的次数
        let delta = link.timestamp - lastTime
        if delta < 1{
            //不够一秒就返回,继续往上面count加一,这样就可以获得一秒内有多少个页面
            return
        }
        //这时候已经到一秒了,我们先把lastTime更新至当前时间以便下一次计算
        lastTime = link.timestamp
        //delta是1.0000000....
        print("delta :\(delta)")
        let fps = Double(count)/delta
        
        count = 0
        
        text = String.init(format: "%02.0f帧", round(fps))
        
        print(text ?? "0")
    }
}

兼容

兼容项就很容易获取到,首先是 SDK 可以运行的最低系统版本,这个在项目工程中就可以设置,也可以轻松获取到。另外一个是设备,这个范围就比较广,移动设备、iPad、iWatch 还是其他设备,这个根据项目来处理。

加载时间

这里使用比较的方法来获取加载时间,即先跑一下没有 Framework 的加载时间,然后再跑一下有 Framework 的加载时间,做个差值就出来了(方法比较简单)。

在项目里面,选择 Edit Scheme.. 选项,然后在 Run 选项中设置 DYLD_PRINT_STATISTICS 为 1。

Framework - 性能统计

之后,每次运行项目的时候都会在打印的工作台中显示这些数据:

Total pre-main time: 242.05 milliseconds (100.0%)
 dylib loading time: 151.75 milliseconds (62.6%)
rebase/binding time:  22.21 milliseconds (9.1%)
		ObjC setup time:   6.99 milliseconds (2.8%)
	 initializer time:  61.09 milliseconds (25.2%)
slowest intializers :
libSystem.B.dylib :   7.70 milliseconds (3.1%)
libBacktraceRecording.dylib :   8.65 milliseconds (3.5%)
libMainThreadChecker.dylib :  40.24 milliseconds (16.6%)

计算的时候,只需要看第一项的时间就好,其他选项有别的用处,这里不做深入的探讨。

安装包大小

安装包大小参考的值可以在 appStore 发布平台上查看。主要看安装大小这个指标就可以。安装大小就是应用安装到设备中用到的内存大小。

这里获取 Framework 安装大小是先上传一个空应用,然后再上传一个有 Framework 的应用,前后比较得到 Framwork 包的安装大小。不要通过查看 .ipa 包文件这些看似直接快速的手段,数据非常的不真实,没有实际的参考意义。

Framework - 性能统计

隐私权限

隐私权限部分分为两个部分,一个是在 SDK 中要使用到的设备权限,比如需要使用摄像头拍照权限,那么在项目中就要设置获取权限。另外一个是要在 App Store 中要公示给用的隐私相关。这两部分都要给到应该对接方,以免因为缺少必要的隐私设置,影响到应用上线审核。

上一篇:【Java并发编程】并发编程大合集


下一篇:asp.net中virtual和abstract的区别