【发布时间】:2019-03-19 07:43:49
【问题描述】:
我在 Swift 中处理非常大的 数组,我得出的结论是,在向其中添加元素时这些数组非常慢。
我主要在Dictionary 中使用数组时观察到这些问题。
例如:var array = [String : [String]]
因此,我决定使用 Playground 对一个非常简单的 array 测试进行基准测试,认为问题来自 array 本身:
var arr = [Int]()
for i in 0..<1_000_000 {
arr.append(i)
}
这段代码需要很长时间才能完成。现在,在 C# 中使用真正的 List 编写相同的代码,甚至不需要 秒。
IList list = new List<int>();
for (int i = 0; i < 1000000; i++) {
list.Add(i);
}
我知道 Swift 中的数组不像其他语言中的列表,您可以灵活地选择 ArrayList、LinkedList。 Swift,每次添加新元素时都会重新分配,并且基本上将所有数组放在一些更新的更大空间中。
我们如何解决这个问题?
编辑 1: Hamish 指出,使用 Xcode Playground 环境进行性能跟踪是一个糟糕的主意。他是对的,Swift arrays 在 Playground 中不使用时与 C# 一样快。
编辑 2:arrays 的性能问题不是因为 array 本身,而是仅在使用 arrays 在字典中时出现。请参阅下面的答案。
【问题讨论】:
-
您是否正在使用游乐场?它们在性能方面很糟糕,请尝试使用命令行工具(如果您真的想要速度,请启用优化)。对我来说运行时间为 0.026 秒。
-
“Swift,每次添加新元素时都会重新分配”——这通常不是真的,
Array采用指数增长策略,每次超过它时容量都会翻倍,允许摊销 O (1) 附加。尽管如果数组从未被唯一引用(如上所述),那么您确实会在每次追加时获得重新分配。 -
我刚刚在命令行工具上尝试了您的代码,这是将值附加到数组之前和之后的输出:Time Before in seconds: 1539553031.420601。之后的时间(以秒为单位):1539553031.4601312。所以只用了不到 0.039 秒。
-
这些问题是完全不同的情况。数组问题是由于游乐场(它不断尝试更新调试输出作为@Hamish 注释)。数组字典问题是关于复制的。追加到数组是一个非常快速的动作。
-
我需要做晚饭,但我稍后再看。这个问题实际上是之前回答的一个重复。有很多方法可以做到这一点。 Swift 数组是值类型;这不会让他们变坏。这意味着他们有不同的权衡。但是有很多方法可以构建数据结构来满足您的需求。
标签: arrays swift performance memory-management