[swift-users] Are structs really always pessimistically copied when calling funcs?

Slava Pestov spestov at apple.com
Mon Dec 7 12:52:22 CST 2015


> On Dec 7, 2015, at 10:36 AM, Joe Groff via swift-users <swift-users at swift.org> wrote:
> 
>> 
>> On Dec 7, 2015, at 10:27 AM, Karl Pickett <karl.pickett at gmail.com <mailto:karl.pickett at gmail.com>> wrote:
>> 
>> I created https://bugs.swift.org/browse/SR-110 <https://bugs.swift.org/browse/SR-110> for the compiler.  However, I also think that the documentation needs an issue filed.  (Where to do that at?) 
> 
> Thanks!
> 
>> The current docs say structs are always copied (the only exception being inout to memory variable optimization).  That would make programmers worried about speed and stack usage run away screaming, and not give swift a try.
> 
> If weren't already been chased away by 'vars are always allocated on the heap'. The docs generally discuss high-level semantic behavior rather than the real code emitted; in general, users can count on structs being copied whenever necessary to preserve value semantics between different names. How would you suggest rewording the documentation?
> 
> -Joe

Perhaps the docs should instead talk about how the lifetime of the var's value might extend beyond the return from its scope, without explicitly saying anything about stack or heap allocation, which as you note is entirely implementation detail.

> 
>> On Mon, Dec 7, 2015 at 11:53 AM, Joe Groff <jgroff at apple.com <mailto:jgroff at apple.com>> wrote:
>> 
>>> On Dec 6, 2015, at 5:16 PM, Karl Pickett via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>> 
>>> I have a struct and this code:
>>> 
>>> func test() {
>>>     precondition(sizeof(Foo) == 128)
>>> 
>>>     let s = Foo()
>>>     for _ in 0..<100_000_000 {
>>>         doSomething(s)
>>>     }
>>> }
>>> 
>>> The asm (on LInux, with -O) is showing me that s is being re-initialized on every iteration of the loop.  I was hoping that thanks to swift's strict constness rules on structs, it wouldn't have to do this - and just pass the same pointer to doSomething() each time.
>>> 
>>> When I use an inout param, that is 2x as fast and doesn't re-initialize each time.  However I don't see why passing something immutably wouldn't be as fast.
>> 
>> This definitely seems like a place where we ought to be able to peephole the extra copies away. Mind filing a bug?
>> 
>> -Joe
>> 
>>> 
>>> - Karl
>>> 
>>> asm from perf:
>>> 
>>>   2.71 │50:┌─→xorps  %xmm0,%xmm0                                                                                          ▒
>>>   8.06 │   │  movaps %xmm0,-0x20(%rbp)                                                                                    ▒
>>>   2.71 │   │  movaps %xmm0,-0x30(%rbp)                                                                                    ▒
>>>   7.41 │   │  movaps %xmm0,-0x40(%rbp)                                                                                    ▒
>>>  10.59 │   │  movaps %xmm0,-0x50(%rbp)                                                                                    ▒
>>>  10.00 │   │  movaps %xmm0,-0x60(%rbp)                                                                                    ▒
>>>   9.53 │   │  movaps %xmm0,-0x70(%rbp)                                                                                    ▒
>>>  10.65 │   │  movaps %xmm0,-0x80(%rbp)                                                                                    ▒
>>>  11.24 │   │  movaps %xmm0,-0x90(%rbp)                                                                                    ▒
>>>  12.06 │   │  mov    %r14,%rdi                                                                                            ▒
>>>   3.41 │   │→ callq  _TF4main11doSomethingFVS_3FooT_                                                                      ▒
>>>   2.82 │   │  dec    %rbx                                                                                                 ▒
>>>   8.82 │   └──jne    50             
>>> 
>>> main.swift:
>>> 
>>> struct Vec4 {
>>>     var a: Int64 = 0
>>>     var b: Int64 = 0
>>>     var c: Int64 = 0
>>>     var d: Int64 = 0
>>> }
>>> 
>>> struct Foo {
>>>     var x: Vec4 = Vec4()
>>>     var y: Vec4 = Vec4()
>>>     var z: Vec4 = Vec4()
>>>     var u: Vec4 = Vec4()
>>> }
>>> 
>>> func test() {
>>>     precondition(sizeof(Foo) == 128)
>>> 
>>>     let s = Foo()
>>>     for _ in 0..<100_000_000 {
>>>         doSomething(s)
>>>     }
>>> }
>>> 
>>> test()
>>> 
>>> 
>>> lib.swift:
>>> 
>>> func doSomething(s: Foo) {
>>>     precondition(s.x.a != 1)
>>> }
>>>  _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>  _______________________________________________
> swift-users mailing list
> swift-users at swift.org <mailto:swift-users at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20151207/2695cc73/attachment.html>


More information about the swift-users mailing list