是否对所有结构进行写入时的快速复制? [英] Does swift copy on write for all structs?

查看:23
本文介绍了是否对所有结构进行写入时的快速复制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 swift 会优化以在写入时复制数组,但它会为所有结构执行此操作吗?例如:

I know that swift will optimize to copy on write for arrays but will it do this for all structs? For example:

struct Point {
   var x:Float = 0
}

var p1 = Point()
var p2 = p1 //p1 and p2 share the same data under the hood
p2.x += 1 //p2 now has its own copy of the data

推荐答案

Array 以写时复制行为实现 – 无论任何情况,您都会得到它编译器优化(当然,优化可以减少需要复制的情况).

Array is implemented with copy-on-write behaviour – you'll get it regardless of any compiler optimisations (although of course, optimisations can decrease the number of cases where a copy needs to happen).

在基本层面上,Array 只是一个结构,它保存对包含元素的堆分配缓冲区的引用——因此多个 Array 实例可以引用 相同缓冲区.当您对给定的数组实例进行变异时,实现将检查缓冲区是否被唯一引用,如果是,则直接对其进行变异.否则,数组将执行底层缓冲区的副本以保留值语义.

At a basic level, Array is just a structure that holds a reference to a heap-allocated buffer containing the elements – therefore multiple Array instances can reference the same buffer. When you come to mutate a given array instance, the implementation will check if the buffer is uniquely referenced, and if so, mutate it directly. Otherwise, the array will perform a copy of the underlying buffer in order to preserve value semantics.

但是,使用您的 Point 结构 – 您并没有在语言级别实现写时复制.当然,正如 @Alexander 所说,这不会不阻止编译器执行各种优化以最小化复制整个结构的成本.不过,这些优化不需要遵循写时复制的确切行为——只要程序按照语言规范运行,编译器就可以自由地做任何它希望的事情.

However, with your Point structure – you're not implementing copy-on-write at a language level. Of course, as @Alexander says, this doesn't stop the compiler from performing all sorts of optimisations to minimise the cost of copying whole structures about. These optimisations needn't follow the exact behaviour of copy-on-write though – the compiler is simply free to do whatever it wishes, as long as the program runs according to the language specification.

在您的具体示例中,p1p2 都是全局的,因此编译器需要使它们不同的实例,因为同一模块中的其他 .swift 文件可以访问给他们(尽管这可能会通过整个模块优化来优化).然而,编译器仍然不需要复制实例——它可以只在编译时评估浮点加法 并用 0.0 初始化一个全局变量,另一个用 1.0 初始化.

In your specific example, both p1 and p2 are global, therefore the compiler needs to make them distinct instances, as other .swift files in the same module have access to them (although this could potentially be optimised away with whole-module optimisation). However, the compiler still doesn't need to copy the instances – it can just evaluate the floating-point addition at compile-time and initialise one of the globals with 0.0, and the other with 1.0.

如果它们是函数中的局部变量,例如:

And if they were local variables in a function, for example:

struct Point {
    var x: Float = 0
}

func foo() {
    var p1 = Point()
    var p2 = p1
    p2.x += 1
    print(p2.x)
}

foo()

编译器甚至不必创建两个 Point 实例开始 - 它只需创建一个初始化为 1.0 的浮点局部变量,然后打印

The compiler doesn't even have to create two Point instances to begin with – it can just create a single floating-point local variable initialised to 1.0, and print that.

将值类型作为函数参数传递,对于足够大的类型和(在结构的情况下)利用足够多属性的函数,编译器 可以通过引用而不是复制来传递它们.然后,被调用者可以仅在需要时复制它们,例如需要使用可变副本时.

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.

在其他按值传递结构的情况下,编译器也可以专门化函数,以便只复制函数需要的属性.

In other cases where structures are passed by value, it's also possible for the compiler to specialise functions in order to only copy across the properties that the function needs.

对于以下代码:

struct Point {
    var x: Float = 0
    var y: Float = 1
}

func foo(p: Point) {
    print(p.x)
}

var p1 = Point()
foo(p: p1)

假设 foo(p:) 没有被编译器内联(在这个例子中它会内联,但是一旦它的实现达到一定的大小,编译器就不会认为它值得) –编译器可以将函数特化为:

Assuming foo(p:) isn't inlined by the compiler (it will in this example, but once its implementation reaches a certain size, the compiler won't think it worth it) – the compiler can specialise the function as:

func foo(px: Float) {
    print(px)
}

foo(px: 0)

它只将Pointx属性的值传递给函数,从而节省了复制y属性的成本.

It only passes the value of Point's x property into the function, thereby saving the cost of copying the y property.

所以编译器会尽其所能减少值类型的复制.但是在不同情况下有如此多的各种优化,您不能简单地将任意值类型的优化行为归结为写时复制.

So the compiler will do whatever it can in order to reduce the copying of value types. But with so many various optimisations in different circumstances, you cannot simply boil the optimised behaviour of arbitrary value types down to just copy-on-write.

这篇关于是否对所有结构进行写入时的快速复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆