我在大数组(图像)上做循环,通过 Instruments 我发现主要瓶颈是 Array.subscript.nativePinningMutableAddressor
,所以我做了这个单元测试来比较,
// average: 0.461 seconds (iPhone6 iOS 10.2) ~5.8 times slower than native arrays
func testArrayPerformance() {
self.measure {
var array = [Float](repeating: 1, count: 2048 * 2048)
for i in 0..<array.count {
array[(i+1)%array.count] = Float(i)
}
}
}
// average: 0.079 seconds
func testNativeArrayPerformance() {
self.measure {
let count = 2048 * 2048
let array = UnsafeMutablePointer<Float>.allocate(capacity: count)
for i in 0..<count {
array[(i+1)%count] = Float(i)
}
array.deallocate(capacity: count)
}
}
如您所见,原生数组要快得多。有没有其他方法可以更快地访问数组? “不安全”听起来并不“安全”,但在这种情况下你们会怎么做?是否有任何其他类型的数组可以包装原生数组?
更复杂的例子,你可以看这篇文章的评论:Rendering Text in Metal with Signed-Distance Fields 我用 Swift 重新实现了那个例子,原来的实现需要 52 秒才能启动,https://github.com/endavid/VidEngine/tree/textprimitive-fail
切换到原生数组后,我下降到 10 秒,https://github.com/endavid/VidEngine/tree/fontatlas-array-optimization
在 Xcode 8.3.3 上测试。
编辑1: 此测试的时间在调试配置中,但符号距离字段示例的时间在发布配置中。感谢评论中单元测试的微优化(计数、初始化),但在现实世界的示例中这些微优化可以忽略不计,内存缓冲区解决方案在 iOS 上仍然快 5 倍。
编辑2: 以下是带符号距离场示例中最昂贵函数的计时(iPhone6 上的 Instruments session ),
Edit3:除了性能问题,我在使用 Swift 数组时遇到了严重的内存问题。 NSKeyedArchiver
会耗尽内存并导致应用程序崩溃。我不得不改用字节缓冲区,并将其存储在 NSData
中。引用提交:https://github.com/endavid/VidEngine/commit/6c1822523a2b18759f294def3188755eaaf98b41
所以我想我的问题的答案是:对于大数组的数字数据(例如图像),最好使用内存缓冲区。
最佳答案
关于ios - Swift 数组访问器比原生数组慢 5 倍——哪些是推荐的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45045811/