Swift 什么时候我的结构太大了?
鼓励我们在Swift中使用Swift 什么时候我的结构太大了?,swift,class,struct,heap-memory,stack-memory,Swift,Class,Struct,Heap Memory,Stack Memory,鼓励我们在Swift中使用struct而不是class 这是因为 编译器可以做很多优化 实例是在堆栈上创建的,这比malloc/free调用的性能要好得多 struct变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈 例如,想象一个4x4矩阵。必须在每个赋值/返回上复制16个浮点值,在64位系统上为1'024位 避免这种情况的一种方法是在向函数传递变量时使用inout,这基本上是创建指针的快捷方式。但是我们也不鼓励使用inout 所以我的问题是: 我应该如何在Swif
struct
而不是class
这是因为
malloc
/free
调用的性能要好得多struct
变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈
例如,想象一个4x4矩阵。必须在每个赋值/返回上复制16个浮点值,在64位系统上为1'024位
避免这种情况的一种方法是在向函数传递变量时使用inout
,这基本上是创建指针的快捷方式。但是我们也不鼓励使用inout
所以我的问题是:我应该如何在Swift中处理大型、不可变的数据结构?
我需要担心创建一个包含许多成员的大型
结构吗?
如果是,我什么时候越过这条线?从Swift参考的页面底部开始:
注
上面的描述涉及字符串、数组和字典的“复制”。您在代码中看到的行为将始终像复制发生一样。但是,Swift仅在绝对必要的情况下在幕后执行实际复制。Swift管理所有值复制以确保最佳性能,您不应避免分配以尝试抢占此优化
我希望这能回答您的问题,如果您想确保数组不会被复制,您可以始终将参数声明为inout
,并将其与&array
一起传递到函数中
另外,类会增加很多开销,只有在您确实必须对同一对象进行引用时才应该使用
结构的示例:
- 时区
- 经纬度
- 尺寸/重量
课程示例:
- 人
- 景色
这个公认的答案并没有完全回答您的问题:Swift总是复制结构。Array/Dictionary/String/etc的诀窍在于它们只是类(包含实际存储的属性)的包装器。这样sizeof(Array)就是指向该类(
MemoryLayout)的指针的大小
还有关于容器类型的部分:
请记住,在使用大值类型之间存在权衡
和使用引用类型。在某些情况下,复制的开销
而围绕大价值类型移动将超过移除的成本
桥接和保持/释放开销
“我们受到鼓励”谁提出了这个策略?谁想阻止好的代码?@I我的意思是使用结构很有意义。记住,这个建议主要来自Swift团队,他们当然知道,他们自己编写了优化器。可能在某些情况下,这几秒钟是相关的,但我一般认为结构良好的代码有助于提高性能事件错误,这也会导致更好更快的代码。但这只是我的观点。结构促进不变性,这有助于在许多情况下防止错误。区别不是几秒钟,而是可能非常严重。@NSADECT我认为这是你需要测试的事情。当你的应用程序需要更快时,你会知道这是一个瓶颈,打开探查器(仪器)它清楚地说明了瓶颈是复制。不要放弃大型结构的安全性,直到它受到伤害,否则你只会成为过早优化的另一个受害者。这太棒了!事实上,我在Swift出版时读到了这一点,我完全忘了它。你是对的。但引用计数和堆分配的开销不是破坏了使用结构的性能优势?唯一的好处是牛的语义。这取决于你如何看待它。苹果公司的基础知识告诉他们,字符串、数组等都应该是值。事实上,它们不是ObjuleC中的值类型,意味着你经常需要防御地复制它们来保证YO。u对底层存储有一个唯一的引用。COW是一个巨大的性能胜利,因为它用已知需要的副本替换了这些防御副本(例如,因为两个阵列引用指向同一个备份,而一个阵列引用希望变异)。此外,可调整大小的元素将始终需要堆分配。否则,使用数组或字符串的任何堆栈帧的大小将取决于其长度。我记得在第一个Swift测试版中,“let”-带注释的数组仍然是可变的,只要你不改变它们的长度。也许他们是在尝试类似的东西。人们不喜欢这种系统,抗议,我们得到了COW。这是有道理的。尽管我们很少需要防御性地复制数组之类的东西,因为它们在默认情况下是不可变的。我想最大的优点是nt是可变数组和不可变数组的一种类型。还值得注意的是,iOS 11中的Obj-C已经引入了COW,因此这些防御副本的成本应该不会太高。由于编译时泛型、静态调度和积极的内联,Swift可能会更快。结构与类不应该有太大的影响:st指令没有子类型或虚拟成员,但Swift编译器无论如何都可以在同一模块内对非开放类进行设备化。只是更简单的语义。