【问题标题】:Swift arrays extremely slow (when used in Dictionaries)Swift 数组非常慢(在字典中使用时)
【发布时间】: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 中的数组不像其他语言中的列表,您可以灵活地选择 ArrayListLinkedList。 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


【解决方案1】:

这个问题主要是因为.append函数必须创建位置然后填充它,

如果你知道数组的大小,你可以稍微加快速度 尝试这段代码给了我一个稍微快一点的结果。

var arr = [Int].init(repeating: 0, count: 1_000_000)

for i in 0..<1_000_000 {
    arr[i] = i
}

这是在使用 Playground,但与 command-line 工具或实际项目相比,Playground 的性能非常慢, 但是这个代码在操场上稍微快一点。

【讨论】:

    猜你喜欢
    • 2019-03-09
    • 2016-08-29
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    相关资源
    最近更新 更多