- 原文地址:On Performant Arrays in Swift
- 原文做者:JORDAN SMITH
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:jingzhilehuakai
- 校对者:RickeyBoy cbangchen
对于平常应用开发,考虑数组性能是一件不会常常发生的事。若是你正在实现须要扩展的算法,也许高性能数组就能出如今你脑海中。也许你正在写更偏向于底层的代码,好比一个框架,这时任何的性能缺陷都会产生复合效应。当数组性能变得重要的时候,了解一些优化数组性能的方式也是很不错的。让咱们来深刻的了解一下 Swift 中的数组吧。前端
Array
不是 Swift 惟一提供的数组类型。你可能已经注意到 ArraySlice
类型,它能在不复制数组的状况下,展现出数组的局部片断。另外还有 ContiguousArray
类型。和名字所暗示的不一样,它实际上是 Swift 中最简单的数组类型。相比标准的数组,它能够有更好的性能表现,而即使没有,也至少能够提供与 Array
相同性能水平的表现。同时也暴露出相同的接口。因此,为何不用 ContiguousArray
去替代 Array
呢?react
let deliciousArray = ContiguousArray<String>(arrayLiteral: "🌮", "🥞", "🥖")复制代码
好吧,由于 Objective-C 的兼容性,Array
能无缝对接成一个 NSArray
。在底层,一个 Array
实例只要它的元素类型是 class 或是遵循了 Objective-C 兼容协议的类型,就会将数组数据存储在 NSArray
中。只要不是这种状况(例如数组元素为值类型的数组),这个数组就不会被存储在 NSArray
中,而且性能变得和 ContiguousArray
至关。android
为了比较性能,咱们运行了这样一个测试,向每一个数组的实例中添加一百万个单独的引用类型,而后删除。这些引用类型会在开始计时前进行预构建,而结果为超过 100 次的运行后获得的平均值。下面的值是在设置了编译器优化的状况下得到的。总的来讲,你能够看到,若是数组性能是瓶颈的话,在数组元素为引用类型或 @objc
类型的前提下,切换为 ContiguousArray
的使用大约能得到 2 倍性能的提高。ios
Array | ContiguousArray |
---|---|
58.9 ms | 30.3 ms |
看起来 Swift 数组分配的内存与它的长度成正比。若是是这种状况,添加或删除一个元素将须要分配或释放内存,并对数组长度的每个变化都形成性能损失。相反,提早分配最少的内存空间是更有意义的,这样就能够在不引发内存管理性能损失的状况下进行接下来的几个新增操做。这其实是 Swift 所作的:以一种智能的方式进行内存分配,来让分配性能消耗保持在最低的水平。git
尽管有智能内存分配,但若是清楚地知道数组应该被定义持有的内存大小,才是内存分配最有效的方式。这样,只须要一个内存分配就能够了。 Swift 数组提供了定义和预留容量的能力,并且这样作能够实现较小的性能增益。github
var healthyArray = ["🍉", "🥕"]
healthyArray.reserveCapacity(50)复制代码
运行另外一个测试,再次向一个数组中添加和删除一百万个引用类型,产生如下的结果。该测试是针对连续数组有无预留内存容量的状况。算法
Without Reserved Capacity | With Reserved Capacity |
---|---|
29.7 ms | 27.3 ms |
若是你想访问原始内存来增强数组,你也能够这么作。对于标准的数组操做,它不会提供太多的性能增益。对于非标准的状况,用这种方式访问或修改数据多是有必要的,或者是对性能有益的。swift
var balancedDietArray = ["🥖", "🍩", "🍗"]
balancedDietArray.withUnsafeMutableBufferPointer { arrayPointer in
arrayPointer[1] = "🍇"
}复制代码
若是你想了解更多关于 Swift 数组是如何工做的,能够在这里找到更多的内容:Swift Array Design。后端
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、React、前端、后端、产品、设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。数组