首页 > 解决方案 > Swift 庞大的数组字典,非常慢

问题描述

我正在使用 Swift 开发一个项目dictionary

这本词典属于[String : [Posting]]. 我有大约 20 万个不同的“术语”(键)要插入其中,对于每个术语,我有大约 500 到 1000 个对象要附加到列表中。我知道这是一种奇怪的做法,但我别无选择,我必须处理所有这些因素。

问题是这非常慢,因为字典变得越来越大。我尝试切换到 a NSMutableDictionary,没有运气。

addTerm每次我需要插入一个元素时都会调用我的函数:

   func addTerm(_ term: String, withId id: Int, atPosition position: Int) {

        if self.map[term] == nil {
            self.map[term] = [Posting]()
        }

        if self.map[term]!.last?.documentId == id {
            self.map[term]!.last?.addPosition(position)
        }
        else {
            self.map[term]!.append(Posting(withId: id, atPosition: position, forTerm: term))
        }
    }

编辑:我意识到它不是导致所有这些滞后的字典,而是它实际上包含的数组。添加新元素时,数组重新分配的方式太多,我能做的最好的就是用ContiguousArray.

标签: arraysswiftperformancedictionarynsdictionary

解决方案


当您的代码太慢时,一般的方法是在 Instruments 中对其进行分析,以确定哪些行实际上花费的时间最长并从那里开始。其他地方可能存在瓶颈,等等。直接从 Xcode 中运行您的应用程序也会创建一个调试版本,这会牺牲可调试性的性能。发布版本可能会执行得更好。

此外,如果您的程序占用大量内存,系统可能难以让这些内存可供您的应用程序使用。在非 iOS 平台上,这将导致将内存换出到磁盘,这将显着影响您的应用程序的性能,因为系统无法预测接下来将访问字典的哪些元素。

如果内存要求不是导致速度下降的原因,那么我会尝试以下几种方法:

  • 如果您可以估计要插入字典的项目数,则可以使用dictionary.reserveCapacity(numberOfItems). 随着字典的增长,它可能需要调整大小,这可能需要重建字典类型内部使用的哈希表。这种方法也适用于数组。

  • Swift 提供了使用公共键自动将项目分组到字典中的方法:Dictionary(grouping: collection, by: { item in item.property }). 这种方法在计算上可能更有效,因为所有东西都可以批量处理。

  • 另一种方法可能是使用不需要频繁重新分配的其他数据类型,例如树形图。然而 Swift 并没有在标准库中提供这样的类型。


推荐阅读