我正在尝试在Swift中构建一个数据结构,该数据结构将一个Integer映射到一个对象数组(一个以int为键,而array为值的字典)。这些对象非常小,它们只包装了一个UIColor和一个Int。我有两种实现,一种使用Swift数组作为Dictionary的值类型,而另一种使用NSMutableArray作为值类型。我的Objective-
C代码执行得非常快,但是我的Swift代码却运行缓慢。理想情况下,我不想使用NSMutableArray,而是希望将其保留为Swift数组。这样做的原因是我正在编写算法,并且性能很重要,我注意到objC_msgSend有一些开销。谁能帮助我优化我的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)")
快速性能:
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
colorInfo对象是将UIColor对象映射到表示计数的Integer值的字典。代码本质上是反向映射,将整数映射到UIColor数组(将其映射为数组,因为多个Color可以具有相同的计数)。colorInfo内部有60,000个UIColor和Int键值对。
写时复制是一件棘手的事情,您需要仔细考虑有多少东西共享您要修改的结构。罪魁祸首在这里。
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中构建一个数据结构,将一个整数映射到一个对象数组(一个以int为键、数组为值的字典)。这些对象非常小,它们只包装了一个UIColor和一个Int。我有两个实现,一个使用Swift数组作为字典的值类型,而另一个使用NSMutableArray作为值类型。我的Objective-C代码运行速度非常快,但我的Swift代码运行速度非常慢。理想情况下,我不想使用NSMutableAr
问题内容: 我已经开发了一个用户批量上传模块。有两种情况,当数据库有零条记录时,我批量上传了20000条记录。大约需要5个小时。但是,当数据库已经有大约30 000条记录时,上传速度将非常缓慢。上载2万条记录大约需要11个小时。我只是通过fgetcsv方法读取CSV文件。 下面是运行的查询。(我正在使用Yii框架) 如果存在,请更新用户: 如果用户不存在,请插入新记录。 表引擎类型为MYISAM。
问题内容: MySQL文档说: 假设B树索引,表的大小会减慢日志N的索引插入速度。 这是否意味着对于每个新行的插入,插入速度将降低log N倍,其中N是行数?即使我只在一个查询中插入所有行?即: 其中n为〜70,000 我目前在一个表格中约有147万行,其结构如下: 当我以上述方式插入事务时,提交时间约为275秒。我该如何优化这一点,因为每天都会添加新数据,并且插入时间只会继续变慢。 此外,除了查
在我编写的一个应用程序中,我有一个从Core-Data解析大量数据并将其显示到图形中的过程。在进行此处理时,我最终还将数据写入CSV文件。我创建了一个名为CSVLine的单独类,它有助于创建CSV文件。 对于我的140k测试用例,记录了我的Objective-C代码需要大约12秒才能运行。将类“迁移”到swift后,现在需要280-360秒才能运行。显然我做了一些可怕的事情。 使用仪器,我能够识别
将单元格出列需要0.5-1.0秒,这意味着我的UITableView需要2-3秒才能加载,即使它只有4行。 前面和后面的NSLog()语句显示出队列从07.47到08.38。 2017-07-25 22:07:07.471898-0700 myapp[10209:4507471]出列前[0,0] 2017-07-25 22:07:07.679715-0700myapp[10209:4507471]
问题内容: 下面的代码将简单的值持有者映射为布尔值,在Java中的运行速度比Swift 2快20倍-XCode 7 beta3,“最快,积极的优化[-Ofast]”和“最快,完整的模块优化”处于打开状态。在Java中,每秒可以进行2.8亿次以上的查询,但是在Swift中,只能达到1000万次。 当我在Instruments中查看它时,我看到大多数时间都在进行与映射查找相关的一对保留/释放调用。关于