我的结构什么时候太大了?

时间:2015-05-31 17:11:54

标签: swift class struct stack heap

我们鼓励在Swift中使用struct而不是class

这是因为

  1. 编译器可以进行大量优化
  2. 在堆栈上创建的实例比malloc / free调用
  3. 的性能更高

    struct变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈。

    E.g。想象一个4x4矩阵。 16每个分配/返回都必须复制16个浮点值,这些值在64位系统上为1� 024位。

    可以避免这种情况的一种方法是在将变量传递给函数时使用inout,这基本上是Swifts创建指针的方法。但是,我们也不鼓励使用inout

    所以对我的问题:
    我应该如何处理Swift中的大型不可变数据结构? 我是否需要担心创建一个有很多成员的大struct? 如果是的话,我什么时候越线?

2 个答案:

答案 0 :(得分:3)

来自Swift Reference的this页面的最底部:

  

请注意

     

上面的描述是指字符串,数组和字典的“复制”。您在代码中看到的行为将始终如同副本一样。但是,当绝对必要时,Swift仅在幕后执行实际复制。 Swift管理所有值复制以确保最佳性能,您不应该避免分配以尝试抢占此优化。

我希望这能回答你的问题,如果你想确保数组不被复制,你总是可以将参数声明为inout,并将&array传递给功能

同样,类会增加很多开销,只有在你真的必须引用同一个对象时才应该使用它。

结构的例子:

  • 时区
  • 纬度/经度
  • 大小/重量

课程示例:

  • A View

答案 1 :(得分:2)

这个接受的答案并不能完全回答你的问题:Swift总是复制结构。 Array / Dictionary / String / etc的作用是它们只是类的包装(包含实际存储的属性)。这样,sizeof(Array)就是指向该类(MemoryLayout<Array<String>>.stride == MemoryLayout<UnsafeRawPointer>.stride

的指针的大小

如果你有一个非常大的结构,你可能想要考虑将它的存储属性包装在一个类中,以便有效地作为参数传递,并在变异之前检查isUniquelyReferenced以给出COW语义。

结构具有其他效率优势:它们不需要引用计数,并且可以由优化器进行分解。

  

在Swift中,值保留其数据的唯一副本。有几个   使用值类型的优点,例如确保值具有   独立国家。当我们复制值(赋值的效果,   初始化和参数传递)程序将创建一个新的   价值的副本。对于一些大的值,这些副本可能是时间   消耗和伤害程序的性能。

https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#the-cost-of-large-swift-values

关于容器类型的部分:

  

请记住,在使用大值类型之间需要权衡   并使用引用类型。在某些情况下,复制的开销   并且移动大值类型将超过删除的成本   桥接和保留/释放开销。