构建性能分析,加速Xcode的构建及Xcode15中Cosole Options

1,278 阅读4分钟

前言

  1. 可以在Xcode中分析构建性能以加快构建速度。
  2. 为了研究构建性能,我们需要清除构建的缓存作为一个起始。这可以通过 Command + SHIFT + K 或者 Product ➔ Clean Build Folder... 来清理

开始编译

  1. 编译之后我们可以通过如图,选择主工程的BuildLog并且打开Assistant查看编译的时间线
  2. 你可以通过双指放大缩小时间线,进而查看某个库的编译时间。当然也可以点击上方编译的Target,时间线会自动切换到该Target的Timeline image.png

查看编译概览

也可以通过 Product ➔ Perform Action ➔ Build with Timing Summary查看编译时间概览

image.png 编译完成后,按照下图,选择Recent,滚动到最下面就能看到编译时间的概览

注意:我这里是一次增量构建。如果是全量构建,会有更多的信息可以查看 image.png 下面的图是一次全量构建的概览

可以看到CompileC花费了1112.13秒,而实际编译时间为235.418秒。这是因为整个构建系统是并发编译,CompileC是统计的编译源码的所有时间,所以看起来会比并发编译的时间长的多

image.png image.png

构建阶段的优化

  1. 可以将一些在Debug下不需要运行的脚本忽略,让它只在Release下运行
  2. 可以使用 --quiet 静默编译,但该效果比较微弱

给编译器添加标记来统计单个表达式较长的耗时

  • -Xfrontend -warn-long-function-bodies=<limit>
  • -Xfrontend -warn-long-expression-type-checking=<limit>

limit是一个毫秒数,如果表达式检查超过这个时间,编译器会发出警告

可以在build Settings中设置这些参数

image.png

Xcode15中Console的Options

可以通过 Command + SHIF + Y 或者 View → Debug Area → Show Debug Area打开Xcode底部的Console面板,然后按照下图可以查看Console的Options有哪些

image.png

  • Type: 在每个log最前面的小图标
  • Timestamp: log打印的时间戳
  • Library: 在哪个库里打印的
  • PID:TID: 进程以及线程id
  • Subsystem: 使用logger的子系统,这个可以自己定义,一般使用自己的App名字就行
  • Category: logger的分类,也可以自定义,大多数情况下每个模块是一个Category。比如网络、日志、数据库等 看个例子

image.png

过滤日志

可以通过底部的Filter来过滤日志。过滤的条件可以选择本类型以及非本类型

image.png

image.png

导航到log代码处

可以通过点击每条log右下角的向右箭头,直接导航到代码处 image.png

快速概览功能

还可以选中log,点击小眼睛,查看该条log的概览内容。在不打开Metadata Options时也依然有效 image.png

OSLog

OSLog是苹果推出的用于替代NSLog、print等方法的日志记录工具,它有更好的性能并且存储在设备上,在Mac上可以通过控制台程序读取

使用

使用时可以为Logger写一个扩展,针对每个模块功能创建一个单独的static属性

import OSLog 
extension Logger {
    /// Using your bundle identifier is a great way to ensure a unique identifier. 
    private static var subsystem = Bundle.main.bundleIdentifier! 
    /// Logs the view cycles like a view that appeared. 
    static let viewCycle = Logger(subsystem: subsystem, category: "viewcycle") 
    /// All logs related to tracking and analytics. 
    static let statistics = Logger(subsystem: subsystem, category: "statistics") 
}
  1. Logger初始化时最好提供一个subsystem和category
  2. 创建后就可以使用里面各种level的日志输出方法

Logger可以怎么用?

  1. 可以使用字符串差值或字符串字面量输出日志,就和使用print一样
let username = "Example Username" 
Logger.viewCycle.info("User \(username) logged in")
  1. 可以控制日志里部分字段的隐私

下面的代码对username使用了.private修饰,在控制台我们就看不到username了

Logger.viewCycle.info("User \(username, privacy: .private) logged in")
  1. 可以控制部分字段的对齐规则
Logger.statistics.debug("\(person.index) \(person.name, align: .left(columns: 10)) \(person.identifier)")
Logger.statistics.debug("\(person.index) \(person.name, align: .left(columns: Person.maxNameLength)) \(person.identifier) \(person.age, format: .fixed(precision: 2))")

Logger日志级别

  1. default (notice):默认的日志级别。最好通过使用其他日志级别来明确。
  2. info:调用这个函数来获取可能对故障排除有帮助但不是必需的信息。
  3. debug:在开发环境中主动调试时使用的调试级消息。
  4. trace:相当于调试方法。
  5. warning:用于报告意外的非致命故障的警告级别消息。
  6. error:用于报告严重错误和失败的错误级别消息。
  7. fault:故障级消息,仅用于捕获系统级或多进程错误。
  8. critical:功能等同于fault方法。

使用控制台查看日志

打开控制台,选择你的手机或者电脑,点击开始进行日志实时记录

image.png

开始记录后,可以在搜索栏搜索关键字,并且设置匹配条件进行过滤

image.png 甚至可以设置多个条件

image.png 同时设置可以搜索简介和调试信息

image.png

资料

  1. www.avanderlee.com/optimizatio…
  2. www.avanderlee.com/xcode/xcode…
  3. www.avanderlee.com/debugging/o…