问题
Swift中的结构体是值类型,在方法中作为参数传递的时候,通常会拷贝一份,那么如果这个结构体很大或者方法调用次数很多,是否会存在性能问题呢。实际上这种情况比较极端,很难发生
值类型的传参优化
- Swift内置基本类型使用COW(写时复制);对于你自定义的结构体,其中必然包含基本的值类型,其元素也会采用COW,这样就不用过于担心struct拷贝的开销
In practice, this is rarely an issue, because we’re frequently using native “extensible” Swift properties, such as String, Array, Set, Dictionary, Data, etc., and those have “copy on write” (COW) behavior.
-
值类型的对象在栈中分配空间,通过移动esp寄存器直接分配空间;对于值类型而言,分配空间不需要经过堆内存的申请分配释放操作,性能会提高很多。
-
编译器的优化,对于struct作为只读参数的传递,方法内部仅仅读取struct的变量的时候,编译器可能会优化参数的形式,不传递结构体,只传递需要的参数,参看
Regarding passing value types as function arguments, for large enough types and (in the case of structures) functions that utilise enough of their properties, the compiler can pass them by reference rather than copying. The callee can then make a copy of them only if needed, such as when needing to work with a mutable copy.
结论
- 值传递和引用传递是一个平衡,对于小结构体而言,值传递明显优于引用传递,相当于用空间换取了时间
- 值中如果包含大量的连续内存,系统也会将大对象放在堆中,这样避免对栈分配的冲击
- 值传递和引用传递核心是对内存分配方式的控制,二者结合发挥最大的性能优势
参考
- https://stackoverflow.com/questions/54865785/will-struct-in-swift-cause-memory-issue-if-passed-around-a-lot
- https://stackoverflow.com/questions/43486408/does-swift-copy-on-write-for-all-structs?noredirect=1&lq=1