什么时候我的结构太大了?
When is my struct too large?
我们鼓励在 Swift 中使用 struct
而不是 class
。
这是因为
- 编译器可以做很多优化
- 实例是在堆栈上创建的,这比
malloc
/free
调用 的性能要高得多
struct
变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈。
例如想象一个 4x4 矩阵。必须在每个 assign/return 上复制 16 个浮点值,这在 64 位系统上为 1'024 位。
避免这种情况的一种方法是在将变量传递给函数时使用 inout
,这基本上是 Swift 创建指针的方法。但是我们也不鼓励使用 inout
.
所以对于我的问题:
我应该如何处理 Swift 中的大型不可变数据结构?
我是否需要担心创建一个包含许多成员的大型 struct
?
如果是,我什么时候过线?
来自 Swift 参考文献的 this 页面的最底部:
NOTE
The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.
我希望这能回答你的问题,如果你想确保一个数组不会被复制,你总是可以将参数声明为 inout
,然后用 &array
传递它进入函数。
另外 类 会增加很多开销,只有在确实必须引用同一对象时才应使用。
结构示例:
- 时区
- Latitude/Longitude
- Size/Weight
类的示例:
- 人
- 一景
这个被接受的答案并没有完全回答您的问题:Swift 总是复制结构。 Array/Dictionary/String/etc 的技巧是它们只是 classes(包含实际存储的属性)的包装器。这样 sizeof(Array) 就是指向 class (MemoryLayout<Array<String>>.stride == MemoryLayout<UnsafeRawPointer>.stride
)
的指针的大小
如果您有一个非常大的结构,您可能需要考虑将其存储的属性包装在 class 中以作为参数高效传递,并在变异之前检查 isUniquelyReferenced
以提供 COW 语义。
结构还有其他效率优势:它们不需要引用计数并且可以由优化器分解。
In Swift, values keep a unique copy of their data. There are several
advantages to using value-types, like ensuring that values have
independent state. When we copy values (the effect of assignment,
initialization, and argument passing) the program will create a new
copy of the value. For some large values these copies could be time
consuming and hurt the performance of the program.
https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#the-cost-of-large-swift-values
还有关于容器类型的部分:
Keep in mind that there is a trade-off between using large value types
and using reference types. In certain cases, the overhead of copying
and moving around large value types will outweigh the cost of removing
the bridging and retain/release overhead.
我们鼓励在 Swift 中使用 struct
而不是 class
。
这是因为
- 编译器可以做很多优化
- 实例是在堆栈上创建的,这比
malloc
/free
调用 的性能要高得多
struct
变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈。
例如想象一个 4x4 矩阵。必须在每个 assign/return 上复制 16 个浮点值,这在 64 位系统上为 1'024 位。
避免这种情况的一种方法是在将变量传递给函数时使用 inout
,这基本上是 Swift 创建指针的方法。但是我们也不鼓励使用 inout
.
所以对于我的问题:
我应该如何处理 Swift 中的大型不可变数据结构?
我是否需要担心创建一个包含许多成员的大型 struct
?
如果是,我什么时候过线?
来自 Swift 参考文献的 this 页面的最底部:
NOTE
The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.
我希望这能回答你的问题,如果你想确保一个数组不会被复制,你总是可以将参数声明为 inout
,然后用 &array
传递它进入函数。
另外 类 会增加很多开销,只有在确实必须引用同一对象时才应使用。
结构示例:
- 时区
- Latitude/Longitude
- Size/Weight
类的示例:
- 人
- 一景
这个被接受的答案并没有完全回答您的问题:Swift 总是复制结构。 Array/Dictionary/String/etc 的技巧是它们只是 classes(包含实际存储的属性)的包装器。这样 sizeof(Array) 就是指向 class (MemoryLayout<Array<String>>.stride == MemoryLayout<UnsafeRawPointer>.stride
)
如果您有一个非常大的结构,您可能需要考虑将其存储的属性包装在 class 中以作为参数高效传递,并在变异之前检查 isUniquelyReferenced
以提供 COW 语义。
结构还有其他效率优势:它们不需要引用计数并且可以由优化器分解。
In Swift, values keep a unique copy of their data. There are several advantages to using value-types, like ensuring that values have independent state. When we copy values (the effect of assignment, initialization, and argument passing) the program will create a new copy of the value. For some large values these copies could be time consuming and hurt the performance of the program.
https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#the-cost-of-large-swift-values
还有关于容器类型的部分:
Keep in mind that there is a trade-off between using large value types and using reference types. In certain cases, the overhead of copying and moving around large value types will outweigh the cost of removing the bridging and retain/release overhead.