Reputation: 261
I want to know if there is any performance cost associated with optionals in Swift e.g if we had to work with optionals repeatedly. Consider the following two code snippets
First approach
var f: Foo?
// foo returns an optional
if let anotherF = foo() {
f = anotherF
}
else {
f = Foo()
}
f?.doSomething()
f?.doSomethingElse()
f?.doAnotherThing()
// and so on
Second approach
var f = Foo()
if let anotherF = foo() {
f = anotherF
}
f.doSomething()
f.doAnotherThing()
f.doAnotherThing()
// and so on
Is there any performance benefit of second approach as compared with first one
Upvotes: 1
Views: 600
Reputation: 17060
This:
func bar(foo: Foo) {
foo.doSomething()
}
generates the following assembly:
bar`bar(foo:):
0x100001370 <+0>: pushq %rbp
0x100001371 <+1>: movq %rsp, %rbp
0x100001374 <+4>: pushq %r13
0x100001376 <+6>: subq $0x18, %rsp
0x10000137a <+10>: movq %rdi, -0x10(%rbp)
0x10000137e <+14>: movq (%rdi), %rax
0x100001381 <+17>: movq 0x50(%rax), %rax
0x100001385 <+21>: movq %rdi, %r13
0x100001388 <+24>: movq %rdi, -0x18(%rbp)
0x10000138c <+28>: callq *%rax
0x10000138e <+30>: movq -0x18(%rbp), %rdi
0x100001392 <+34>: callq 0x1000013f0 ; swift_rt_swift_release
0x100001397 <+39>: addq $0x18, %rsp
0x10000139b <+43>: popq %r13
0x10000139d <+45>: popq %rbp
0x10000139e <+46>: retq
However this:
func bar(foo: Foo?) {
foo?.doSomething()
}
generates the following:
bar`bar(foo:):
0x100001340 <+0>: pushq %rbp
0x100001341 <+1>: movq %rsp, %rbp
0x100001344 <+4>: pushq %r13
0x100001346 <+6>: subq $0x18, %rsp
0x10000134a <+10>: movq %rdi, -0x10(%rbp)
0x10000134e <+14>: movq %rdi, -0x18(%rbp)
0x100001352 <+18>: callq 0x1000013f0 ; swift_rt_swift_retain
0x100001357 <+23>: movq -0x18(%rbp), %rdi
0x10000135b <+27>: cmpq $0x0, %rdi
0x10000135f <+31>: sete %al
0x100001362 <+34>: xorb $-0x1, %al
0x100001364 <+36>: testb $0x1, %al
0x100001366 <+38>: jne 0x100001373 ; <+51> at main.swift:16
0x100001368 <+40>: movq -0x18(%rbp), %rdi
0x10000136c <+44>: callq 0x100001400 ; swift_rt_swift_release
0x100001371 <+49>: jmp 0x10000139a ; <+90> at main.swift:16
0x100001373 <+51>: movq -0x18(%rbp), %rax
0x100001377 <+55>: movq (%rax), %rcx
0x10000137a <+58>: movq %rax, %r13
0x10000137d <+61>: callq *0x50(%rcx)
0x100001380 <+64>: movq -0x18(%rbp), %rdi
0x100001384 <+68>: callq 0x100001400 ; swift_rt_swift_release
0x100001389 <+73>: movq -0x18(%rbp), %rdi
0x10000138d <+77>: callq 0x100001400 ; swift_rt_swift_release
0x100001392 <+82>: addq $0x18, %rsp
0x100001396 <+86>: popq %r13
0x100001398 <+88>: popq %rbp
0x100001399 <+89>: retq
0x10000139a <+90>: jmp 0x100001389 ; <+73> at main.swift:17
As you can see, the optional version generates a few more instructions, so there would seem to be some overhead involved. My expectation is that it would be small, though.
Upvotes: 6