分析Swift性能高效的原因

绝大多数公司选择Swift语言开发iOS应用,主要原因是因为Swift相比Objc有更快的运行效率,更加安全的类型检测,更多现代语言的特性提升开发效率;这一系列的优点使Swift语言的热度越来越高。

自从2014年Apple发布Swift语言以来,历时六年多,Swift已经发布到5.3版本,在5.0版本已经ABI stability,5.2版本也已经module stability,不管是语言还是基础库都日趋稳定,目前国内外大厂也都积极拥抱Swift阵营。

大多数人知道Swift语言相比于Objc语言运行效率更高,但是却不知道为什么效率更高,在这里我们Swift编译层探讨一下Swift语言高效的原因。

在开始讨论Swift数据类型之前,我们先讨论一下Swift的函数派发机制;
静态派发、动态派发、消息派发(static dispatch、dynamic dispatch、message dispatch)

动态派发(dynamic dispatch): 动态派发是指编译期无法确定应该调用哪个方法,需要在运行时才能确定方法的调用。

静态派发(static dispatch):是在编译期就能确定的调用方法的派发方式。

除了上面两种方式之外,在Swift里面还会使用Objc的**消息派发(message dispatch))**机制;Objc采用了运行时采用obj_msgsend进行消息派发,所以Objc的一些动态特性在Swift里面也可以被限制的使用。

静态派发相比于动态派发更快,而且静态派发还会进行内联等一些优化,减少函数的寻址及内存地址的偏移计算等一系列操作,使函数的执行速度更快,性能更高。

数据类型(struct/class)

我们都知道,内存分配可以分为堆区(Heap)和栈区(Stack)。由于栈区内存是连续的,内存的分配和销毁是通过入栈和出栈操作进行的,速度要高于堆区。堆区存储高级数据类型,在数据初始化时,查找没有使用的内存,销毁时再从内存中清除,所以堆区的数据存储不一定是连续的。

类(class)和结构体(struct)在内存分配上是不同的,基本数据类型和结构体默认分配在栈区,而像类这种高级数据类型存储在堆区,且堆区数据存储不是线程安全的,在频繁的数据读写操作时,要进行加锁操作。

我们在swift文档里面能看到对结构的描述,结构体是值类型(Value Type),当值类型的数据赋值给一个变量或常量,或者传递给一个函数时,是值拷贝;
例如:

struct Resolution {
    var width = 0
    var height = 0
}

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048

print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"

print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"

通过这个例子我们能清楚的看到,当hd赋值给cinema时,是将hd中存储的值拷贝给cinema,所以当给cinemawidth属性赋值的时候,并不会改变hd中的属性值,如下图所示:
image

结构体除了属性的存储更安全、效率更高之外,其函数的派发也更高效。由于结构体不能被继承,也就是结构体的类型被final修饰,根据我们对于动态派发及静态派发的描述,那么其内部函数应该是属于静态派发,在编译期就确定了函数的执行方式,其函数的调用通过内联(inline)的方式进行优化,其内存连续,减少了函数的寻址及内存地址的偏移计算,其运行相比于动态派发更加高效。

协议类型(protocol type)

多态是面向对象的一大特性,在结构体中不能通过继承或者引用语言的多态,swift就引入了协议(protocol),通过协议来实现了结构体的多态特性,这也是swift面向协议编程的核心所在。

对于类(class)来说,每个类都会创建一个虚拟函数表指针,这个指针则指向一个v-table表,也就是虚函数表,表内存储着该类的函数指针数组,拥有继承关系的子类会在虚函数表内通过继承顺序(C++可以实现多继承)去展示虚函数表指针。类里面方法的派发则是根据v-table表里面函数指针来进行派发。

而结构体(struct)没有继承,也就是说结构体并没有v-table表用于函数的派发。为了实现这一特性,在结构体的协议(protocol)的实现里添加了Protocol Witness Table用于管理协议类型的方法派发。

编译过程

上面介绍了一些swift在数据结构上的一些优化,除了数据结构优化之外,swift在编译过程也进行了大量的优化,其中最核心的优化,是在编译过程中引入SIL。
SIL,Swift Intermediate Language,是为了优化swift编译过程而设计的中间语言,主要包含了以下功能:

1、一系列的高级别优化保障,用于对运行时和诊断行为提供可预测的基线;
2、对swift语言数据流分析强制要求,对不满足强制要求的问题产生诊断。例如变量和结构体必须明确初始化,代码可达性即方法return的检测,switch的覆盖率;
3、确保高级别优化。包含retain/release优化,动态方法的去虚拟化,闭包内联,内存初始化提升和泛型方法实例 化.
4、可用于分配"脆弱"内联的稳定分配格式,将Swift库组件的泛型优化为二进制。

Clang编译流程

image

Clang编译过程有以下几个缺点:

1、与代码与LLVM IR之间有巨大的抽象鸿沟(Wide abstraction gap between source and LLVM IR );
2、IR不适合源码级别的分析(IR isn’t suitable for source-level analysis );
3、CFG(Control Flow Graph)缺少精准度(CFG lacks fidelity );
4、CFG偏离主道(CFG is off the hot path );
5、在CFG和IR降级中会出现重复分析(Duplicated effort in CFG and IR lowering)。

由于以上这些缺点,swift语言开发团队在开发过程中进行了一系列的优化,其中最关键的是引入SIL.

swift编译流程

Swift作为一个高级别和安全的语言具有以下特点:
高级别语言

  • 通过代码充分的展示语言的特性(Move more of the language into code)
  • 支持基于协议的泛型(Protocol-based generics)

安全语言

  • 充分的数据流检查:未初始化变量,函数返回处理检测,这些项在检测不合格时会产生对应的编译错误(Uninitialized vars, unreachable code should be compiler errors)
  • 边界和溢出的检测(Bounds and overflflow checks)

swift编译流程:
image

Swift 源码到IR之间的流程:

image

Swift 编译过程引入SIL有几个优点:

1、完成的变数程序的语义(Fully represents program semantics );
2、既能进行代码的生成,又能进行代码分析(Designed for both code generation and analysis );
3、处在编译管线的主通道(Sits on the hot path of the compiler pipeline );
4、架起桥梁连接源码与LLVM,减少源码与LLVM之间的抽象鸿沟(Bridges the abstraction gap between source and LLVM)

Swift编译器的流程

Swift编译器作为高级编译器,具有以下严格的传递流程结构。
Swift编译器的流程如下:

  • Parse: 语法分析组件从Swift源码构成AST
  • 语义分析组件对AST进行类型检查,并对其进行类型信息注释。
  • SILGen组件从AST形成"原始(raw)"SIL
  • 一系列在 生 SIL上运行的,用于确定优化和诊断合格,对不合格的代码嵌入特定的语言诊断。这些操作一定会执行,即使在-Onone选项下也不例外。之后产生 正式(canonical) SIL.
  • 一般情况下,是否在正式SIL上运行SIL优化是可选的,这个检测可以提升结果可执行文件的性能.可以通过优化级别来控制,在-Onone模式下不会执行.
  • IRGen会将正式SIL降级为LLVM IR.
  • LLVM后端提供LLVM优化,执行LLVM代码生成器并产生二进制码.

在上面的流程中,SIL对Swift的编译过程进行了一系列的优化,即保证的代码执行的安全性,又提升了代码执行的效率.以上就是分析Swift性能高效的原因的详细内容,希望对大家有所帮助

原文地址

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python是一种易于学习和使用的编程语言,适用于各种领域,如数据分析、人工智能、网络爬虫等。 JavaScript是前端开发的主要语言,在网页开发、移动应用开发等方面有广泛应用。 Swift是苹果公司开发的编程语言,用于开发苹果的操作系统和iOS应用。 因此,学习这三种语言可以为您的职业发展提供更多机会。 ### 回答2: 推荐学习Python、JavaScript和Swift主要有以下原因: 1.广泛应用:Python是一门多领域通用编程语言,广泛应用于数据分析、人工智能、Web开发等领域;JavaScript是Web开发事实上的标准脚本语言,用于前端和后端开发;Swift是苹果公司的编程语言,用于开发iOS和macOS应用。学习这些语言可以获得更广阔的就业机会。 2.易学易用:这三门语言都是高级语言,相比于其他编程语言来说,语法相对简单,容易入门。Python语法简洁易懂,强制缩进方式更符合自然语言的阅读习惯;JavaScript灵活易用,它还有许多现成的库和框架可以借助;Swift也是一门相对容易上手的语言,适合初学者。 3.强大的社区支持:Python、JavaScript和Swift都有庞大的开发者社区,提供了丰富的资源和技术支持。在开发过程中,可以轻松获取到大量的代码示例、开发工具和解决方案。 4.丰富的框架和库:这三门语言都有许多成熟的框架和库,可以大大减少开发时间和工作量。例如,Python有Django和Flask等框架;JavaScript有React、Angular和Vue.js等框架;Swift有UIKit和SwiftUI等框架。这些框架和库为开发者提供了更快速、更高效地开发应用的方法。 5.可扩展性:Python、JavaScript和Swift拥有良好的可扩展性。在项目开发中,这些语言可以与其他语言、数据库和网络技术无缝配合,可以更好地满足个人和企业的需求。 综上所述,学习Python、JavaScript和Swift能够提升编程技能,扩大就业和应用领域,获得强大的社区支持,同时也能够享受编程的乐趣。无论是初学者还是有一定编程基础的人都可以选择其中一门或多门进行学习。 ### 回答3: Python是一种易学易用的编程语言,因此推荐学习它。首先,Python有简单、直观的语法,对初学者来说非常友好。它不需要太多的代码就能实现复杂的功能,因此可以减少学习者的心理压力。其次,Python有广泛的应用领域。它可以用于数据分析、人工智能、网络开发、自动化测试等多个方面,因此在就业市场上非常有前景。 Javascript是一种网页编程语言,同样推荐学习它。首先,Javascript在前端开发中非常重要。通过学习Javascript,可以掌握与用户进行交互的能力,包括动态网页和网页游戏开发等。其次,Javascript是一门非常灵活的语言。它可以与HTML和CSS无缝结合,为网页注入强大的功能。此外,Javascript也逐渐在后端开发中得到应用,为全栈开发提供了更多的机会。 Swift是一种适用于iOS和macOS开发的编程语言,也是一种很好的选择。首先,Swift是由苹果公司开发的,因此它具有与苹果操作系统完美兼容的优势。学习Swift可以为移动应用开发打下坚实的基础,提供更好的用户体验和性能。其次,Swift是一种现代化的语言,具有简洁、安全和高效的特点。它提供了大量的开发工具和框架,帮助开发者更快速地构建应用程序。 总之,推荐学习Python、Javascript和Swift是因为它们在不同的领域拥有广泛的应用,并且它们都具有易学易用、灵活和高效的特点。通过掌握这些编程语言,可以获得更多的就业机会,为自己的职业发展打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值