使用 Swift 代码优化项目编译速度
引言
软件的性能是评价一个软件质量的重要指标,尤其在今天这个时代,性能已成为大型项目不可或缺的考虑因素之一。对于用户量极大的软件,如网银系统、在线购物商城等,更是必须保证其高效稳定的性能。在这种背景下,优化项目的编译速度就显得尤为重要。本文将介绍如何使用 Swift 代码优化项目编译速度。
找出编译耗时过长的文件
要优化项目的编译速度,首先需要把耗时过长的文件找出来,然后进行重点优化。这里会用到 Xcode build 的两个OTHER_SWIFT_FLAGS:
-Xfrontend
:如果编译或类型检查时耗时多长,则在 Xcode 中输出警告。-debug-time-function-bodies
:输出每个函数的编译时长。
添加这些 flag 的方法为:
- 选中 Target
- 选中 Build Settings
- 搜索 “Other Swift Flags”
- 添加
-Xfrontend -debug-time-function-bodies
基于这两个 flag,有 3 个方法可以找到耗时过长的文件:
方法一:使用克魔助手
克魔助手是一款专为苹果手机 iOS 应用开发设计的辅助工具,提供了丰富的性能监控功能,帮助开发者优化应用的性能。以下是使用克魔助手找到编译耗时过长的文件的步骤:
-
下载克魔助手:用户可以前往克魔助手工具官网进行免费下载,该工具提供绿色软件版本,无需其他安装流程。下载后解压即可开始使用。下载地址是 https://www.keymob.com 。
-
注册和登录:为了使用克魔助手工具,用户需要在电脑上安装并登录该工具。在登录后,用户可以继续其他操作流程。克魔开发助手提供了简单的登录码获取流程,确保用户能够方便地使用该工具。
3.选择文件管理界面并开始监听:双击克魔开发助手.exe 启动克魔助手后,点击右上角的登录按钮,输入邮箱后,没登录码的点击获取登录码,有的可以直接输入登录码,登录成功后,选择文件管理界面。然后自定义选择列,并点击 “开始监听” 来查看应用程序的性能情况。
方法二:使用 Xcode 控制台
在 Xcode 的控制台中输入以下命令即可输出时间最久的前 10 个文件:
find . -type f -name '*.swift' -exec \sh -c "echo '{}' && swiftc -v -c '{}' 2>&1 | awk '/^.{10}[ ]+[0-9\.]+ms/{print \$0}' | sort -rn | head -10" \;
方法三:使用 Xcode 插件
使用 Xcode 插件 SwiftLint 可以自动输出编译耗时最长的文件。安装方法如下:
- 打开 Terminal,输入以下命令:
brew install swiftlint
- 在 Xcode 中打开 Preferences(快捷键
Command + ,
),选择 Text Editing,然后选择 Code completion。 - 在 Code completion 下面的 Fuzzy matching 一栏中,勾选 Show snippets using: 和 Swift。然后再选择 Edit All-in-One Snippet…。
- 进入 Snippet 编辑页面,复制以下代码并保存:
// MARK: - Performance Metrics// Prints the compile time of each function or method in this file.
// Add to the `OTHER_SWIFT_FLAGS` build setting for the target.
// -Xfrontend -debug-time-function-bodies
//
// For more information about how to use debug-time-function-bodies see:
// - https://pspdfkit.com/blog/2018/how-to-reduce-swift-compile-times/
// - https://github.com/apple/swift/pull/13132#issuecomment-312358040
// - WWDC 2018 session 404 Optimizing Swift build times
// - https://youtu.be/nJwVabxL5Gw?t=11m16s
//
// If you add this to a Swift file, it will print the compile time of each
// method in this file to the console on build.
//
// Usage:
// In Xcode 9.x and later:
// 1. Open your project
// 2. Go to the Build Phases tab of your app's target
// 3. Click the + button in the top left and select "New Run Script Phase"
// 4. Add the following code to the script area below the shell:
// "${PODS_ROOT}/SwiftLint/swiftlint" --no-cache --config "${PODS_ROOT}/SwiftLint/.swiftlint.yml"
// "${PROJECT_DIR}/Scripts/perf.swift"
// Note: You may need to customise the paths to suit your project structure.
// 5. Drag the new run script phase to be just before the "Compile Swift Sources"
// phase in the list.
// 6. Rebuild your project (Command-B)
// 7. The compile time for each function in each source file will now be logged
// to the console, sorted by longest compile time first.import Foundationlet numBitsInByte = 8extension Double {func rounded(toPlaces places: Int) -> Double {let divisor = pow(10.0, Double(places))return (self * divisor).rounded() / divisor}
}extension String {func padding(toLength length: Int, withPad padCharacter: Character) -> String {let padding = String(repeatElement(padCharacter, count: max(0, length - count)))return self + padding}
}func readableTime(_ time: Double) -> String {if time < 0.001 {return "< 0.001ms"} else if time < 1 {return "\(time.rounded(toPlaces: 3))ms"} else {var timeStr = "\(time.rounded(toPlaces: 2))s"if time > 60 {let minutes = Int(time / 60)let seconds = time.truncatingRemainder(dividingBy: 60)timeStr = "\(minutes)m \(seconds.rounded(toPlaces: 2))s"}return timeStr.padding(toLength: 10, withPad: " ")}
}func measure<A>(name: String, _ f: () -> A) -> A {let start = DispatchTime.now()let result = f()let end = DispatchTime.now()let time = Double(end.uptimeNanoseconds - start.uptimeNanoseconds) / Double(numBitsInByte * 1000000)print("\(readableTime(time)): \(name)")return result
}
- 在 Xcode 的 Build Phases 中添加一个 Run Script,将以下代码复制到 Run Script 中:
"${PODS_ROOT}/SwiftLint/swiftlint" --no-cache --config "${PODS_ROOT}/SwiftLint/.swiftlint.yml"
"${SRCROOT}/Scripts/perf.swift"
总结
优化项目的编译速度是一个不断迭代的过程,需要不断地寻找和解决问题。本文介绍了如何使用 Swift 代码来找出编译耗时过长的文件,并介绍了三种方法:使用克魔助手、使用 Xcode 控制台和使用 Xcode 插件 SwiftLint。希望这些方法能够帮助读者优化项目的编译速度。
参考资料
- 克魔助手官网
相关文章:

使用 Swift 代码优化项目编译速度
引言 软件的性能是评价一个软件质量的重要指标,尤其在今天这个时代,性能已成为大型项目不可或缺的考虑因素之一。对于用户量极大的软件,如网银系统、在线购物商城等,更是必须保证其高效稳定的性能。在这种背景下,优化…...

基于springboot+vue的社区团购系统(前后端分离)
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…...

three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera</title><script src"ThreeJS/three.js"></script><script src&qu…...
Golang 搭建 WebSocket 应用(七) - 性能、可用性
在前面的文章中,提到过非功能性需求决定了架构。 今天我们再来考虑一下另外两个非功能性需求:性能和可用性。 前言 关于性能,其实并不是只有我们这个消息推送系统独有的问题。 对于所有的开发者而言,都多多少少会处理过性能相关…...
Qt 状态机框架:The State Machine Framework (一)
传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 一、什么是状态机框架 状态机框架提供了用于创建和执行状态图/表[1]的类。这些概念和表示法基于Harel的Statecharts:一种复杂系统的可视化形式,也是UML状态图的基…...

高通平台学习一
什么是QMI? Qualcom Message Interface 高通信息接口 高通平台目前都是非对称多核心,最主要的是AP和Modem。两个处理器怎么进行通信呢,我们把AP和Modem当作两个主机,问题就变得了很简单,TCP/IP协议不是一种非常成功的进程间跨主…...

Python爬虫时被封IP,该怎么解决?四大动态IP平台测评
在使用 Python 进行爬虫时,很有可能因为一些异常行为被封 IP,这主要是因为一些爬虫时产生的异常行为导致的。 在曾经的一次数据爬取的时候,我尝试去爬取Google地图上面的商家联系方式和地址信息做营销,可是很不幸,还只…...

积分梳状滤波器CIC原理与实现
CIC(Cascade Intergrator Comb):级联积分梳状滤波器,是由积分器和梳状滤波器级联而得。滤波器系数为1,无需对系数进行存储,只有加法器、积分器和寄存器,资源消耗少,运算速率高&#…...

【项目管理】CMMI-原因分析与解决过程(CAR)
概述: “原因分析与解决”通过预防缺陷或者问题的引入以及识别并适当纳入优秀过程性能的原因,改进质量与生产率。 目录 1、文档结构 2、原因分析与解决过程域包括如下活动 3、选择需要加以分析的结果(启动条件) 4、过程活动与实践对照表 5、实例 1、…...

【设计模式】文件目录管理是组合模式吗?
组合模式是什么? 组合模式是一种将对象组合成树形结构以表示"部分-整体"的层次结构的设计模式。它使得用户对单个对象和组合对象的使用具有一致性。 组合模式在什么情况下使用? 当你发现你需要在代码中实现树形数据结构,让整体-部…...

利用appium自动控制移动设备并提取数据
安装appium-python-client模块并启动已安装好的环境 安装appium-python-client模块 在window的虚拟环境下执行pip install appium-python-client 启动夜神模拟器,进入夜神模拟器所在的安装路径的bin目录下,进入cmd终端,使用adb命令建立adb…...
day22_236二叉树最近公共祖先_235二叉搜索树(最近公共祖先_701插入一个节点_450删除一个节点)
文章目录 [236 二叉树的最近公共祖先](https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE)[235 二叉搜索树的最近公共祖先](https://program…...

OpenSource - 工具管理器easy-manager-tool
文章目录 功能说明运行配置环境配置启动docker部署 项目安全UI展示 Easy-Manager-Tool 打造软件行业首款集成工具,不管你是程序员,测试,运维等都可以使用该软件来提升自己的工作效率。 Easy-Manager-Tool 的诞生是为了解决软件行业众多参与者…...

Laravel7 + easyWeChat 实现微信公众号支付功能
注册服务号,需进行微信认证,此时需缴费 300 元/年,必须是认证成功的服务号才能开通微信支付。 注册微信支付商户号 1、登录 https://pay.weixin.qq.com/index.php/core/home/login?return_urlhttps%3A%2F%2Fpay.weixin.qq.com%2Findex.php%…...

Linux环境下,针对QT软件工程搭建C++Test单元测试环境的操作指南
文章目录 前言一、安装QT二、安装CTest三、使用QT生成.bdf文件四、创建CTest工程注意事项 前言 CTest是Parasoft公司出品的一款可以针对C/C源代码进行静态分析、单元测试、集成测试的测试工具。本文主要讲解如何在Linux环境下,搭建QT插件版的CTest测试环境。 一、…...

16k+ start 一个开源的的监控系统部署教程
安装条件 Linux或macOS系统 4GB内存 开放 33014、33174、3183端口 1.安装 1、下载源码 首先使用 git 克隆源码到本地 git clone -b main https://github.com/SigNoz/signoz.git && cd signoz/deploy/ 方式1:运行 install.sh 脚本一键安装 ./install.s…...

Mermaid使用教程(绘制各种图)
Mermaid使用教程(绘制各种图) 文章目录 Mermaid使用教程(绘制各种图)简介饼状图简单的例子应用案例 序列图简单案例应用案例另一个应用案例 甘特图简单案例应用案例一个更为复杂的应用案例 Git图简单案例 总结 简介 本文将主要介…...
OpenAI/ChatGPT Plus 支持的虚拟卡有哪些
最近,有关 OpenAI/ChatGPT Plus 需要信用卡的讨论越来越多。在这篇文章中,我将分享一些我在绑定信用卡过程中得到的经验和教训,以及 OpenAI/ChatGPT Plus 支持的卡类型。 不支持的卡 根据 OpenAI 的地区限制,国内和香港的卡都不…...

ARM多核调度器DSU
1. 背景 从A75开始,ARM提出了一个新的多核心管理系统单元,叫做DSU(DynamIQ Shared Unit)。DSU的核心功能是控制CPU内核,使其成簇Cluster使用,簇内每一个核心可以单独开关、调整频率/电压,能效表现更佳,甚至…...
vue解决部署文件缓存方式
问题:系统上线后,除了bug。紧急修复后,发现安卓正常,ios上海市有问题。通过debug后发现,ios上缓存严重。于是想到了打包文件加时间戳的方式来去除缓存。 vue2 配置打包输出文件名方式: const baseUrl &qu…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...