Swift上的高性能数组

连续的数组

Array 不是 Swift 唯一提供的数组类型。你可能已经注意到 ArraySlice 类型,它能在不复制数组的情况下,展示出数组的局部片段。另外还有 ContiguousArray 类型。和名字所暗示的不同,它其实是 Swift 中最简单的数组类型。相比标准的数组,它可以有更好的性能表现,而即便没有,也至少可以提供与 Array 相同性能水平的表现。同时也暴露出相同的接口。所以,为什么不用 ContiguousArray 去替代 Array 呢?

let deliciousArray = ContiguousArray<String>(arrayLiteral: "🌮", "🥞", "🥖")

好吧,因为 Objective-C 的兼容性,Array 能无缝对接成一个 NSArray。在底层,一个 Array 实例只要它的元素类型是 class 或是遵循了 Objective-C 兼容协议的类型,就会将数组数据存储在 NSArray 中。只要不是这种情况(例如数组元素为值类型的数组),这个数组就不会被存储在 NSArray 中,并且性能变得和 ContiguousArray 相当。

为了比较性能,我们运行了这样一个测试,向每个数组的实例中添加一百万个单独的引用类型,然后删除。这些引用类型会在开始计时前进行预构建,而结果为超过 100 次的运行后得到的平均值。下面的值是在设置了编译器优化的情况下获得的。总的来说,你可以看到,如果数组性能是瓶颈的话,在数组元素为引用类型或 @objc 类型的前提下,切换为 ContiguousArray 的使用大约能获得 2 倍性能的提升。

Array ContiguousArray
58.9 ms 30.3 ms

数组容量

看起来 Swift 数组分配的内存与它的长度成正比。如果是这种情况,添加或删除一个元素将需要分配或释放内存,并对数组长度的每一个变化都造成性能损失。相反,提前分配最少的内存空间是更有意义的,这样就可以在不引起内存管理性能损失的情况下进行接下来的几个新增操作。这实际上是 Swift 所做的:以一种智能的方式进行内存分配,来让分配性能消耗保持在最低的水平。

尽管有智能内存分配,但如果清楚地知道数组应该被定义持有的内存大小,才是内存分配最有效的方式。这样,只需要一个内存分配就可以了。 Swift 数组提供了定义和预留容量的能力,而且这样做可以实现较小的性能增益。

var healthyArray = ["🍉", "🥕"]
healthyArray.reserveCapacity(50)

运行另一个测试,再次向一个数组中添加和删除一百万个引用类型,产生以下的结果。该测试是针对连续数组有无预留内存容量的情况。

Without Reserved Capacity With Reserved Capacity
29.7 ms 27.3 ms

C 类型数组

如果你想访问原始内存来加强数组,你也可以这么做。对于标准的数组操作,它不会提供太多的性能增益。对于非标准的情况,用这种方式访问或修改数据可能是有必要的,或者是对性能有益的。

var balancedDietArray = ["🥖", "🍩", "🍗"]
balancedDietArray.withUnsafeMutableBufferPointer { arrayPointer in
    arrayPointer[1] = "🍇"
}

译文原贴:https://juejin.im/post/59e84129f265da43128005ed
英文原贴:http://jordansmith.io/on-performant-arrays-in-swift/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,293评论 8 265
  • 集合类型: Swift,和其他现代编程语言一样,有内置的集合类型数组(Array)和字典(Dictionary),...
    小松树先生阅读 1,090评论 0 2
  • ————情不知所起,一往而深 不知从什么时候起, 我的生活变得一塌糊涂。 什么都乱,什么...
    潇湘雨默阅读 465评论 5 8
  • 丰疯子 林丰【中国平安财产保险股份有限公司厦门分公司】 【日精进打卡第69天】 【知~学习】 《六项精进》背诵1遍...
    丰疯子阅读 163评论 0 1
  • O:早上呢还是按照昨天的方法,把昨天学的知识巩固了回又实操了下,都记住了,还是那句话,虽然基础,但实用,至少以后有...
    云飞扬8866阅读 89评论 2 0