所以我决定创建一个简单的测试来看看发生了什么.
final class SomeClass {}struct SomeStruct {}let classes = [ SomeClass(),SomeClass(),]let structs = [ SomeStruct(),SomeStruct(),]
func test1() { for i in 0...10000000 { for s in classes {} }}func test2() { for i in 0...10000000 { for s in structs {} }}
Test1需要15.4722579717636 s而Test2仅需0.276068031787872 s.通过结构阵列连续迭代的速度提高了56倍.所以我的问题是,这是为什么?我正在寻找一个详细的答案.如果我不得不猜测,我会说结构本身按顺序存储在内存中,而类只存储为地址.所以他们每次都需要被解除引用.但话说回来,每次都不需要复制结构吗?
旁注:两个数组都很小,但我不断迭代它们.如果我将代码更改为迭代一次但是使数组非常大,如下所示:
for i in 0...10000000 { structs.append(SomeStruct()) classes.append(SomeClass())}func test1() { for s in classes {}}func test2() { for s in structs {}}
然后我得到以下结果:Test1需要0.841085016727448 s而Test2需要0.00960797071456909 s.结构需要快88倍.
我正在使用OS X发布版本,优化级别设置为最快,最小[-Os]
编辑
根据要求,我编辑了这个问题,以包含一个测试,其中结构和类不再是空的.它们使用我在游戏中使用的相同属性.仍然没有什么区别.结构仍然快得多,我不知道为什么.希望有人能提供答案.
import Foundationfinal class StructTest { let surfaceFrames = [ SurfaceFrame(a: SurfacePoint(x: 0,y: 410),b: SurfacePoint(x: 0,y: 400),c: SurfacePoint(x: 875,surfaceID: 0,dynamic:false),SurfaceFrame(a: SurfacePoint(x: 880,y: 304),b: SurfacePoint(x: 880,y: 294),c: SurfacePoint(x: 962,surfaceID: 1,SurfaceFrame(a: SurfacePoint(x: 787,y: 138),b: SurfacePoint(x: 791,y: 129),c: SurfacePoint(x: 1031,y: 248),surfaceID: 2,SurfaceFrame(a: SurfacePoint(x: 523,b: SurfacePoint(x: 523,y: 128),c: SurfacePoint(x: 806,y: 144),surfaceID: 3,SurfaceFrame(a: SurfacePoint(x: 1020,y: 243),b: SurfacePoint(x: 1020,y: 233),c: SurfacePoint(x: 1607,y: 241),surfaceID: 4,SurfaceFrame(a: SurfacePoint(x: 1649,b: SurfacePoint(x: 1649,c: SurfacePoint(x: 1731,y: 305),surfaceID: 5,SurfaceFrame(a: SurfacePoint(x: 1599,y: 240),b: SurfacePoint(x: 1595,y: 231),c: SurfacePoint(x: 1852,surfaceID: 6,SurfaceFrame(a: SurfacePoint(x: 1807,y: 141),b: SurfacePoint(x: 1807,y: 131),c: SurfacePoint(x: 2082,surfaceID: 7,SurfaceFrame(a: SurfacePoint(x: 976,y: 413),b: SurfacePoint(x: 976,y: 403),c: SurfacePoint(x: 1643,y: 411),surfaceID: 8,SurfaceFrame(a: SurfacePoint(x: 1732,b: SurfacePoint(x: 1732,c: SurfacePoint(x: 2557,surfaceID: 9,SurfaceFrame(a: SurfacePoint(x: 2130,y: 490),b: SurfacePoint(x: 2138,y: 498),c: SurfacePoint(x: 2109,y: 512),surfaceID: 10,SurfaceFrame(a: SurfacePoint(x: 1598,y: 828),b: SurfacePoint(x: 1597,y: 818),c: SurfacePoint(x: 1826,y: 823),surfaceID: 11,SurfaceFrame(a: SurfacePoint(x: 715,y: 826),b: SurfacePoint(x: 715,y: 816),c: SurfacePoint(x: 953,surfaceID: 12,SurfaceFrame(a: SurfacePoint(x: 840,y: 943),b: SurfacePoint(x: 840,y: 933),c: SurfacePoint(x: 920,surfaceID: 13,SurfaceFrame(a: SurfacePoint(x: 1005,y: 1011),b: SurfacePoint(x: 1005,y: 1001),c: SurfacePoint(x: 1558,surfaceID: 14,SurfaceFrame(a: SurfacePoint(x: 1639,b: SurfacePoint(x: 1639,c: SurfacePoint(x: 1722,y: 942),surfaceID: 15,SurfaceFrame(a: SurfacePoint(x: 1589,y: 825),b: SurfacePoint(x: 1589,y: 815),c: SurfacePoint(x: 1829,surfaceID: 16,SurfaceFrame(a: SurfacePoint(x: 0,y: 0),b: SurfacePoint(x: 1,y: 1),c: SurfacePoint(x: 2,y: 2),surfaceID: 17,dynamic:true) ] func run() { let startTime = CFabsoluteTimeGetCurrent() for i in 0 ... 10000000 { for s in surfaceFrames { } } let timeElapsed = CFabsoluteTimeGetCurrent() - startTime println("Time elapsed \(timeElapsed) s") }}struct SurfacePoint { var x,y: Int}struct SurfaceFrame { let a,b,c :SurfacePoint let surfaceID: Int let dynamic: Bool}
import Foundationfinal class Classtest { let surfaceFrames = [ SurfaceFrame(a: SurfacePoint(x: 0,y: Int}final class SurfaceFrame { let a,c :SurfacePoint let surfaceID: Int let dynamic: Bool init(a: SurfacePoint,b: SurfacePoint,c: SurfacePoint,surfaceID: Int,dynamic: Bool) { self.a = a self.b = b self.c = c self.surfaceID = surfaceID self.dynamic = dynamic }}
在此测试中,类使用了14.5261079668999 s,而使用结构的测试仅花费了0.310304999351501 s.结构快了47倍.
解决方法 正如Martin R推荐的那样,我描述了两个测试,实际上,保留/释放调用使得遍历类数组比迭代结构数组要慢得多.为了清楚起见,这是我跑的测试.import Foundationfinal class SomeClass {}struct SomeStruct {}var classes = [ SomeClass(),]var structs = [ SomeStruct(),]let startTime = CFabsoluteTimeGetCurrent()/*structtest()classtest()*/let timeElapsed = CFabsoluteTimeGetCurrent() - startTimeprintln("Time elapsed \(timeElapsed) s")
func structtest() { for i in 0 ... 1000000 { for e in structs {} }}
func classtest() { for i in 0 ... 1000000 { for e in classes {} }}
以下是使用仪器进行两种测试分析的图片.您可以通过将每次迭代期间Classes测试几乎所有时间花在保留/释放上的运行时间加起来来看.我有兴趣看看Swift 2.0如何处理这个问题.
结构
类
所以出于好奇,我想如果我可以通过直接在数组上执行指针算法来绕过retain / release调用会发生什么(旁注:我建议你永远不要在真正的应用程序中这样做).所以我创建了最后一个测试.但是在这个测试中,我不是多次迭代数组,而是创建一个大型数组并迭代一次,因为这是大多数开销发生的地方.我还决定在此测试中访问属性以减少优化中的模糊性.
所以这是最终测试的结果:
>对大型Struct阵列进行一次迭代:1.00037097930908 s
>对大型类阵列的一次迭代:11.3165299892426 s
>使用指针对大型Struct数组进行一次迭代
算术:0.773443996906281 s
>使用指针对大型Class数组进行一次迭代
算术:2.81995397806168 s
以下是测试代码.
final class SomeClass { var a: Int init(a: Int) { self.a = a }}struct SomeStruct { var a: Int init(a: Int) { self.a = a }}var classes: [SomeClass] = []var structs: [SomeStruct] = []var total: Int = 0for i in 0 ... 100000000 { classes.append(SomeClass(a:i)) structs.append(SomeStruct(a:i))}let startTime = CFabsoluteTimeGetCurrent()/*structtest()classtest()structTestPointer()classtestPointer()*/let timeElapsed = CFabsoluteTimeGetCurrent() - startTimeprintln("Time elapsed \(timeElapsed) s")func structtest() { for someStruct in structs { let a = someStruct.a total = total &+ a }}func structTestPointer() { var pointer = UnsafePointer<SomeStruct>(structs) for j in 0 ..< structs.count { let someStruct = pointer.memory let a = someStruct.a total = total &+ a pointer++ }}func classtest() { for someClass in classes { let a = someClass.a total = total &+ a }}func classtestPointer() { var pointer = UnsafePointer<SomeClass>(classes) for j in 0 ..< classes.count { let someClass = pointer.memory let a = someClass.a total = total &+ a pointer++ }}总结
以上是内存溢出为你收集整理的数组 – 为什么连续遍历一个Structs数组比一个Classes数组更快?全部内容,希望文章能够帮你解决数组 – 为什么连续遍历一个Structs数组比一个Classes数组更快?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)