iOS 性能优化

如何做启动优化,如何监控

iOS启动优化是提升应用程序启动速度和响应性能的一系列技术和方法。下面是一些常用的iOS启动优化方法和监控工具:

启动优化方法:

  1. 减少冷启动时间:冷启动是指应用进程不在系统中,需要系统分配新的进程来启动应用。为了减少冷启动时间,可以考虑以下优化方法:

    • 合并动态库并减少使用Embedded Framework。
    • 删除无用代码并抽取重复代码。
    • 避免在+load方法中执行耗时操作,使用+initialize代替。
    • 避免使用attribute((constructor)),可将要实现的内容放在初始化方法中配合dispatch_once使用。
    • 减少非基本类型的C++静态全局变量的个数。
  2. 优化main函数代理阶段:main函数代理阶段是指从main()函数开始执行到didFinishLaunchingWithOptions方法执行结束的耗时。在这个阶段可以考虑以下优化方法:

    • 删除不必要的初始化代码。
    • 延迟加载不必要的模块和功能。
    • 使用异步加载和懒加载来提高启动速度。

监控工具:

  1. Xcode Instruments:Xcode自带的性能分析工具,可以使用Time Profiler和System Trace等工具来监控应用程序的启动时间和性能。
  2. DYLD_PRINT_STATISTICS:通过设置环境变量DYLD_PRINT_STATISTICS或DYLD_PRINT_STATISTICS_DETAILS,可以在Xcode中查看应用程序启动过程中各个阶段的耗时统计信息。

以上是一些常用的iOS启动优化方法和监控工具,通过优化启动流程和使用合适的工具,可以提升应用程序的启动速度和响应性能。


Learn more:

  1. 深入探索 iOS 启动速度优化 - 掘金
  2. iOS启动优化看我就够了 - 掘金
  3. IOS优化篇之启动速度优化(一) - 简书

如何做卡顿优化,如何监控

iOS卡顿优化方法可以从两个方面入手:CPU优化和GPU优化。下面将介绍一些常用的优化方法,并提供一些监控工具供参考。

CPU优化方法:

  1. 减少计算量:

    • 提前计算好布局,避免在显示时进行复杂的计算 [1].
    • 使用轻量级对象,如CALayer代替UIView,避免不必要的事件处理 [1].
    • 避免重复执行的方法,如多个地方监听同一个通知,通知中执行多次的清除缓存的方法 [1].
    • 将耗时的操作放到子线程,避免阻塞主线程 [1].
    • 将文本处理放在子线程进行,如文本尺寸计算和绘制 [1].
  2. 图片解码优化:

    • 使用SDWebImage等库,在后台线程将图片绘制到CGBitmapContext中,然后直接从Bitmap创建图片 [1].

GPU优化方法:

  1. 减少渲染量:

    • 合并多张图片为一张图片显示,减少短时间内大量图片的显示 [1].
    • 控制纹理尺寸不超过4096*4096,避免占用CPU资源进行处理 [1].
    • 减少视图数量和层次,避免混合过程中消耗CPU资源 [1].
    • 尽量使用不透明的视图,设置opacity为YES,避免alpha通道的合成 [1].
    • 避免离屏渲染,如光栅化、遮罩、圆角等操作 [1].
  2. 画圆角避免离屏渲染:

    • 使用CAShapeLayer与UIBezierPath配合画圆角 [1].

监控工具:

  1. Instruments:Xcode自带的性能分析工具,可以监控CPU、内存、网络等性能指标,帮助定位卡顿问题 [2].
  2. FPS监控:通过在App中添加FPS监控代码,可以实时监测帧率,判断是否存在卡顿 [2].
  3. 卡顿检测工具:如Facebook的Chisel、Tencent的GT等,可以监测主线程卡顿情况,并提供详细的卡顿堆栈信息 [2].

以上是一些常用的iOS卡顿优化方法和监控工具


Learn more:

  1. iOS卡顿优化-腾讯云开发者社区-腾讯云
  2. iOS界面卡顿原理及优化 - 掘金
  3. 深入探索 iOS 卡顿优化 - 掘金

FPS 用 CADisplayLinker 来计数

使用CADisplayLink来计算FPS的步骤如下:

  1. 创建CADisplayLink对象,并将其添加到当前的run loop中的NSRunLoopCommonModes中。这样可以确保CADisplayLink在屏幕刷新时被调用。
  2. 在CADisplayLink的回调方法中,记录每次调用的次数,并计算时间间隔。
  3. 当时间间隔超过1秒时,计算FPS并进行相应的处理(例如打印、显示在界面上等)。
  4. 重置计数和时间戳,以便下一次计算。

以下是一个示例代码:

swift 复制代码
import UIKit

class ViewController: UIViewController {
    var displayLink: CADisplayLink?
    var frameCount = 0
    var timestamp = 0.0

    override func viewDidLoad() {
        super.viewDidLoad()
        setupDisplayLink()
    }

    func setupDisplayLink() {
        displayLink = CADisplayLink(target: self, selector: #selector(update))
        displayLink?.add(to: .current, forMode: .common)
    }

    @objc func update() {
        if timestamp == 0 {
            timestamp = displayLink?.timestamp ?? 0
            return
        }

        frameCount += 1
        let elapsed = displayLink?.timestamp ?? 0 - timestamp

        if elapsed >= 1.0 {
            let fps = Double(frameCount) / elapsed
            print("FPS: \(fps)")

            // Reset
            frameCount = 0
            timestamp = displayLink?.timestamp ?? 0
        }
    }
}

这段代码创建了一个CADisplayLink对象,并将其添加到当前的run loop中。在每次屏幕刷新时,会调用update方法。在update方法中,我们记录每次调用的次数,并计算时间间隔。当时间间隔超过1秒时,我们计算FPS并进行相应的处理。最后,我们重置计数和时间戳,以便下一次计算。

请注意,使用CADisplayLink计算的FPS只是一个指导意义,不能代表真实的FPS。因为CADisplayLink是以屏幕刷新频率为基准的,而在实际应用中,可能存在其他因素(例如CPU和GPU的性能)影响帧率。因此,这个FPS指示器只能作为一个参考,不能完全准确地反映屏幕的帧率。


Learn more:

  1. iOS中基于CADisplayLink的FPS指示器详解 - 简书
  2. 使用CADisplayLink编写FPS检测工具 - 掘金
  3. CADisplayLink的使用,显示屏幕帧数-CSDN博客

怎样监听 runloop 的 source0 事件和进入休眠前,然后设定一个阈值,监听卡顿

要监听 RunLoop 的 source0 事件和进入休眠前的方法,可以使用 CFRunLoopObserver 来实现。CFRunLoopObserver 是一个观察者,可以监听 RunLoop 的状态变化,并在特定的时间点执行相应的操作。

以下是具体的步骤:

  1. 创建一个 CFRunLoopObserver 对象,并指定观察的时间点和观察的事件类型。可以使用 CFRunLoopObserverCreate 函数来创建观察者对象。

  2. 定义一个回调函数,用于在观察的时间点执行相应的操作。回调函数的参数包括观察者对象、观察的事件类型和上下文信息。

  3. 将观察者对象添加到 RunLoop 的指定模式下。可以使用 CFRunLoopAddObserver 函数将观察者对象添加到 RunLoop 中。

  4. 在回调函数中,可以根据观察的事件类型执行相应的操作。例如,在监听进入休眠前的事件时,可以记录当前时间,并与上一次记录的时间进行比较,判断是否发生了卡顿。

  5. 根据需要,可以设置一个阈值来判断卡顿的时间。如果超过了阈值,可以进行相应的处理,例如打印日志、发送通知或采取其他措施。

以下是一个示例代码,演示如何监听 RunLoop 的 source0 事件和进入休眠前的方法,并设定一个阈值来监听卡顿:

objective-c 复制代码
// 定义观察者的回调函数
void runLoopObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
    if (activity == kCFRunLoopBeforeSources) {
        // 在 source0 事件之前执行的操作
        NSLog(@"Before sources");
    } else if (activity == kCFRunLoopBeforeWaiting) {
        // 在进入休眠前执行的操作
        NSLog(@"Before waiting");
        
        // 记录当前时间
        NSDate *currentDate = [NSDate date];
        
        // 获取上一次记录的时间
        NSDate *lastDate = (__bridge NSDate *)(info);
        
        // 计算时间差
        NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:lastDate];
        
        // 设置阈值,判断是否发生卡顿
        NSTimeInterval threshold = 1.0; // 1秒
        if (timeInterval > threshold) {
            NSLog(@"Cardon detected");
        }
        
        // 更新上一次记录的时间
        CFDateRef dateRef = (__bridge_retained CFDateRef)(currentDate);
        CFRelease((__bridge CFTypeRef)(lastDate));
        *(CFDateRef *)(info) = dateRef;
    }
}

// 创建观察者对象
CFRunLoopObserverContext context = {0, (__bridge void *)([NSDate date]), NULL, NULL, NULL};
CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &runLoopObserverCallback, &context);

// 将观察者对象添加到 RunLoop 的默认模式下
CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopDefaultMode);

// 运行 RunLoop
CFRunLoopRun();

// 释放观察者对象
CFRelease(observer);

这样,就可以监听 RunLoop 的 source0 事件和进入休眠前的方法,并设定一个阈值来监听卡顿。


Learn more:

  1. [iOS面试]第7章 RunLoop相关面试问题 | codeTao
  2. iOS Runloop 总结 | Edgar's Blog
  3. GitHub - fanren5119/iOS-runloop: 本届详细讲解了ios的runloop

如何做耗电优化,如何监控

iOS耗电优化方法可以通过以下几个步骤来实现:

  1. 使用Energy impact进行耗电检测:

    • 在Xcode中,通过选择Product->Profile或使用快捷键cmd+i,然后选择Energy impact来查看应用的耗电情况[1]
    • 查看Average Energy Impact来评估应用的总体平均耗电量,根据颜色区分耗电等级,如low、high和very high[1]
    • 查看Average Component Utilization来了解各个耗电部分的占比,包括Overhead、Network、CPU、GPU和Location[1]
    • 通过Profiler进一步分析耗电占比大的部分,如使用Time Profiler来查找最耗时的函数或方法[1]
  2. 使用Energy Log进行耗电检测:

    • 在设备上启用Energy Log功能,可以通过iPhone的设置->开发者->Logging->Start Recording来开始记录耗电数据[1]
    • 运行应用并进行各种操作,然后停止记录,将数据导入到Xcode的Instruments工具中进行分析[1]
  3. 使用sysdiagnose进行耗电检测:

    • sysdiagnose是一种收集系统诊断信息的工具,可以用于分析电池使用情况[2]
    • 通过sysdiagnose可以获取电压、电流、温度等电池相关数据,以及应用的功耗信息[2]
  4. 优化耗电量:

    • 优化CPU使用:通过分析Time Profiler或sysdiagnose的数据,找出CPU占用高的函数或方法,并进行优化,如减少循环次数、使用异步操作等[1][2]
    • 优化网络使用:减少网络请求次数,合并请求,使用缓存等方式来降低网络耗电[1]
    • 优化定位使用:根据需求选择合适的定位精度,避免过高的精度导致的额外能耗[1]
    • 优化GPU使用:减少不必要的图形渲染操作,避免过度绘制等[1]

Learn more:

  1. iOS性能优化之耗电检测 | 杂货铺
  2. iOS系统APP耗电量检测分析和优化 - 掘金
  3. iOS耗电量优化实践 - 简书

如何做网络优化,如何监控

iOS网络优化方法可以从减少请求带宽和降低请求延迟两个方面进行优化。同时,监控网络性能也是很重要的,可以帮助我们了解应用的网络状况并及时发现问题。

以下是一些iOS网络优化的方法和监控网络性能的工具:

iOS网络优化方法:

  1. 减少请求带宽:

    • 使用高效的数据交互模式。
    • 在可能的情况下使用预先压缩的数据。
    • 压缩每一个请求与响应负载[1]
  2. 降低请求延迟:

    • 最小化DNS查询的数量,可以使用DNS预下载进行更早的DNS解析。
    • 最大程度减少应用发起的连接数,请求结束时不要关闭HTTPS连接,使用域分片等方式来减少SSL握手时间。
    • 在单个TCP连接上发送HTTP请求,以管道的形式发送HTTP请求,避免多个TCP连接的开销[1]

iOS网络性能监控工具:

  1. Network Link Conditioner:是iOS开发者工具中的一个功能,可以模拟不同网络环境下的网络连接状况,帮助开发者测试应用在不同网络条件下的性能表现。

  2. Charles Proxy:是一款常用的网络抓包工具,可以用于监控和分析iOS设备上的网络请求和响应,帮助开发者了解应用的网络状况。

  3. Firebase Performance Monitoring:是Google提供的一款移动应用性能监控工具,可以监控应用的网络请求、响应时间等性能指标,并提供实时的性能报告和分析。

  4. Alamofire Network Logger:是一款基于Alamofire网络库的日志记录工具,可以记录和显示iOS应用的网络请求和响应的详细信息,方便开发者进行网络性能分析。

以上是一些常用的iOS网络优化方法和监控工具,通过优化网络性能和监控网络状况,可以提升应用的用户体验和性能表现。


Learn more:

  1. iOS网络性能优化 - 简书
  2. iOS网络优化-CSDN博客
  3. iOS网络请求优化 - 任超的博客 | Renchao's Blog
相关推荐
爱摄影的程序猿2 小时前
JAVA springboot面试题今日分享
java·spring boot·spring·面试
Pandaconda3 小时前
【C++ 面试 - 新特性】每日 3 题(六)
开发语言·c++·经验分享·笔记·后端·面试·职场和发展
涛涛酱100867 小时前
前端面试实录,(回答均为个人见解)
前端·面试·原型模式
蒙娜丽宁7 小时前
掌握Go语言中的映射、常量与指针
开发语言·ios·golang·go
老豆88 小时前
[ios]准备好app后使用xcode发布ios操作
ios·mac·xcode
好家伙VCC8 小时前
一些面试和找工作的技巧-新资要的低并不会给你加分薪资要的高不会成为公司拒绝你的核心理由
单片机·嵌入式硬件·学习·面试·职场和发展·鲁棒优化
归辞...11 小时前
「iOS」折叠cell
ios
程序员小雷11 小时前
字节面试 | 如何测试RocketMQ、RocketMQ?
测试工具·面试·职场和发展·单元测试·测试用例·rocketmq·postman
Flutter鸿蒙梁典典学院11 小时前
Flutter自动打包ios ipa并且上传
flutter·ios·cocoa
鱼跃鹰飞12 小时前
Leetcode面试经典150题-2.两数相加
算法·leetcode·面试