我正在尝试在Swift中构建一个数据结构,将一个整数映射到一个对象数组(一个以int为键、数组为值的字典)。这些对象非常小,它们只包装了一个UIColor和一个Int。我有两个实现,一个使用Swift数组作为字典的值类型,而另一个使用NSMutableArray作为值类型。我的Objective-C代码运行速度非常快,但我的Swift代码运行速度非常慢。理想情况下,我不想使用NSMutableArray,而是希望将其保留为Swift数组。原因是我正在编写一个算法和性能很重要,我注意到objC_msgSend有一些开销。有人能帮我优化我的Swift代码吗?我做错了什么还是这只是swift将数组视为值类型的副产品?如果是,我想了解为什么值类型在这种情况下表现如此缓慢,我的选择是什么,以及这种情况如何扩展?下面我发布了一个代码片段和由此产生的基准测试:
Swift数组代码:
let numColors = colorCount(filter: filter, colorInfoCount: colorInfo.count)
var colorCountsArray: [Int] = [Int]()
var countToColorMap: [Int:[CountedColor]] = [Int:[CountedColor]](minimumCapacity: capacity)
var topColors = [CountedColor]()
var startTime = CACurrentMediaTime()
for (color, colorCount) in colorInfo {
colorCountsArray.append(colorCount)
if countToColorMap[colorCount] != nil {
countToColorMap[colorCount]?.append(CountedColor(color: color, colorCount: colorCount))
} else {
countToColorMap[colorCount] = [CountedColor(color: color, colorCount: colorCount)]
}
}
var endTime = CACurrentMediaTime()
print("Time after mapping: \(endTime - startTime)")
Swift性能:
Time after mapping: 45.0881789259997
NSMutableArray代码:
let numColors = colorCount(filter: filter, colorInfoCount: colorInfo.count)
var colorCountsArray: [Int] = [Int]()
var countToColorMap: [Int:NSMutableArray] = [Int:NSMutableArray](minimumCapacity: capacity)
var topColors = [CountedColor]()
var startTime = CACurrentMediaTime()
for (color, colorCount) in colorInfo {
colorCountsArray.append(colorCount)
if countToColorMap[colorCount] != nil {
countToColorMap[colorCount]?.add(CountedColor(color: color, colorCount: colorCount))
} else {
countToColorMap[colorCount] = NSMutableArray(object: CountedColor(color: color, colorCount: colorCount))
}
}
var endTime = CACurrentMediaTime()
print("Time after mapping: \(endTime - startTime)")
NSMutableArray性能:
Time after mapping: 0.367132211999888
colyInfo对象是将UIColor对象映射到表示计数的整数值的字典。代码本质上是反向映射,将整数映射到UIColor数组(它是一个数组,因为多个颜色可以具有相同的计数)。colyInfo内部有60,000个UIColor、Int键值对。
在swift 4.2出现之前我有一些工作要做
var countToColorMap = [Int: [CountedColor]]()
for (color, colorCount) in colorInfo {
countToColorMap[colorCount, default: [CountedColor]()].append(CountedColor(color: color as! UIColor, colorCount: colorCount))
}
它速度快,可读性强
写时复制是一件棘手的事情,您需要仔细考虑有多少东西共享您试图修改的结构。罪魁祸首在这里。
countToColorMap[colorCount]?.append(CountedColor(color: color as! UIColor, colorCount: colorCount))
这将生成一个临时值,该值将被修改并放回字典中。由于两个“东西”正在查看相同的底层数据结构(字典和append),因此它强制写入副本。
解决这个问题的秘诀是确保修改时只有一个副本。怎么做?把它从字典中拿出来。替换这个:
if countToColorMap[colorCount] != nil {
countToColorMap[colorCount]?.append(CountedColor(color: color as! UIColor, colorCount: colorCount))
} else {
countToColorMap[colorCount] = [CountedColor(color: color as! UIColor, colorCount: colorCount)]
}
其运行时为:
Elapsed Time: 74.2517465990022
53217
有了这个:
var countForColor = countToColorMap.removeValue(forKey: colorCount) ?? []
countForColor.append(CountedColor(color: color as! UIColor, colorCount: colorCount))
countToColorMap[colorCount] = countForColor
其运行时为:
Elapsed Time: 0.370953808000195
53217
问题内容: 我正在尝试在Swift中构建一个数据结构,该数据结构将一个Integer映射到一个对象数组(一个以int为键,而array为值的字典)。这些对象非常小,它们只包装了一个UIColor和一个Int。我有两种实现,一种使用Swift数组作为Dictionary的值类型,而另一种使用NSMutableArray作为值类型。我的Objective- C代码执行得非常快,但是我的Swift代码却
问题内容: 下面的代码将简单的值持有者映射为布尔值,在Java中的运行速度比Swift 2快20倍-XCode 7 beta3,“最快,积极的优化[-Ofast]”和“最快,完整的模块优化”处于打开状态。在Java中,每秒可以进行2.8亿次以上的查询,但是在Swift中,只能达到1000万次。 当我在Instruments中查看它时,我看到大多数时间都在进行与映射查找相关的一对保留/释放调用。关于
问题内容: 我有一本字典,其中包含用枚举值散列的对象: 我希望能够提取此字典包含的所有颜色(值)的数组。我以为我可以使用该属性,就像遍历字典值()一样,但这会返回错误: 似乎该方法返回了一个更抽象的集合类型,而不是返回值的an 。有没有一种方法可以获取包含字典值的而不循环提取它们的值? 问题答案: 从Swift 2.0开始,的属性现在返回而不是。该类型知道如何使用此抽象集合类型进行初始化: Swi
下面的代码将简单的值持有者映射到布尔值,它在Java中的运行速度比Swift2-xCode7Beta3快20倍以上,“最快的、积极的优化[-ofast]”和“快速的、整个模块的优化”已经开启。我在Java中每秒可以得到超过2.8亿次查找,但在Swift中只能得到大约1000万次查找。 当我在Instruments中查看它时,我看到大部分时间都是进入一对与映射查找相关联的retrain/releas
问题内容: 我在Swift中使用可选字典发现了一些令人惊讶的行为。 我已经做了很多事情,试图找出我可能会缺少的东西,但是除了使字典不是可选的以外,似乎没有什么能使此代码正常工作。我想念什么? 我能得到的最接近的是以下内容,但它当然是荒谬的。 问题答案: 灯泡时刻是您意识到可选词典不是词典的时候。可选的东西不是那个东西!这是一个可选的!仅此而已。可选本身是一种类型。Optional只是一个枚举,包装
问题内容: 例如: 字典将包含以下内容: 在Swift中有可能吗? 我是否可以访问像字典这样的类,例如可能使用: 或类似的东西? 谢谢。 问题答案: 您只需将计算属性添加到您的属性中即可返回带有您的值的。请注意,Swift本机字典类型没有任何称为的方法。您需要将您强制转换为: 您还可以按照@ColGraff发布的链接答案中的建议扩展协议,以使其对所有结构通用: