Почему в Swift let _ = this быстрее, чем this!= nil?

Итак, мой вопрос: почему let _ = this быстрее, чем this != nil?

Пример:

Это:

let this : Bool? = true //

let start = DispatchTime.now()
for _ in 0...100000000  {
    guard this != nil else { continue }
}
let end = DispatchTime.now()

let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime)
print("Time \(timeInterval)") 

         // Time 5426559135.0
         // Time 5428084767.0
         // Time 5327325459.0

Медленнее чем:

let this : Bool? = true //

let start = DispatchTime.now()
for _ in 0...100000000  {
    guard let _ = this else { continue }
}
let end = DispatchTime.now()

let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime)
print("Time \(timeInterval)")

          // Time 257045414.0
          // Time 261933863.0
          // Time 263465919.0

person Durdu    schedule 01.08.2017    source источник


Ответы (2)


После ответа Джонатана < /a> Я проверил настоящие дизассемблированные инструкции. Вот результат: Для кода:

let this : Bool? = nil
this != nil

мы получаем:

    0x100001290 <+0>:  pushq  %rbp
    0x100001291 <+1>:  movq   %rsp, %rbp
    0x100001294 <+4>:  subq   $0x30, %rsp
    0x100001298 <+8>:  leaq   0x2c7259(%rip), %rdx      ; type metadata for Swift.Bool
    0x10000129f <+15>: leaq   0x2b66ca(%rip), %rcx      ; protocol witness table for Swift.Bool : Swift.Equatable in Swift
    0x1000012a6 <+22>: leaq   -0x18(%rbp), %rax
    0x1000012aa <+26>: leaq   -0x8(%rbp), %r8
    0x1000012ae <+30>: movb   $0x2, 0x2f940b(%rip)
    0x1000012b5 <+37>: movb   0x2f9404(%rip), %r9b      ; test2.this : Swift.Optional<Swift.Bool>
    0x1000012bc <+44>: movb   %r9b, -0x8(%rbp)
    0x1000012c0 <+48>: movb   $0x2, -0x10(%rbp)
    0x1000012c4 <+52>: movb   -0x10(%rbp), %r9b
    0x1000012c8 <+56>: movb   %r9b, -0x18(%rbp)
    0x1000012cc <+60>: movl   %edi, -0x1c(%rbp)
    0x1000012cf <+63>: movq   %r8, %rdi
    0x1000012d2 <+66>: movq   %rsi, -0x28(%rbp)
    0x1000012d6 <+70>: movq   %rax, %rsi
    0x1000012d9 <+73>: callq  0x10004df10               ; Swift.!= infix <A where A: Swift.Equatable> (Swift.Optional<A>, Swift.Optional<A>) -> Swift.Bool
    0x1000012de <+78>: xorl   %r10d, %r10d
    0x1000012e1 <+81>: movb   %al, -0x29(%rbp)
    0x1000012e4 <+84>: movl   %r10d, %eax
    0x1000012e7 <+87>: addq   $0x30, %rsp
    0x1000012eb <+91>: popq   %rbp
    0x1000012ec <+92>: retq

и для:

let this : Bool? = nil
let _ = this

есть:

    0x1000012d0 <+0>:  pushq  %rbp
    0x1000012d1 <+1>:  movq   %rsp, %rbp
    0x1000012d4 <+4>:  xorl   %eax, %eax
    0x1000012d6 <+6>:  movb   $0x2, 0x2f93e3(%rip)
    0x1000012dd <+13>: movl   %edi, -0x4(%rbp)
    0x1000012e0 <+16>: movq   %rsi, -0x10(%rbp)
    0x1000012e4 <+20>: popq   %rbp
    0x1000012e5 <+21>: retq   

Кроме того, спасибо Code Different за указание на уровень оптимизации.

Изменение значения с [-Onone] на [-O -whole-module-optimisation] приведет к изменению сгенерированного asm следующим образом:

let this : Bool? = nil
let _ = this

имеет

    0x100001490 <+0>:  pushq  %rbp
    0x100001491 <+1>:  movq   %rsp, %rbp
    0x100001494 <+4>:  movb   $0x2, 0x3d9595(%rip)      ; gCRAnnotations + 63
    0x10000149b <+11>: xorl   %eax, %eax
    0x10000149d <+13>: popq   %rbp
    0x10000149e <+14>: retq   

и

let this : Bool? = nil
this != nil

to

    0x100001490 <+0>:  pushq  %rbp
    0x100001491 <+1>:  movq   %rsp, %rbp
    0x100001494 <+4>:  movb   $0x2, 0x3d9595(%rip)      ; gCRAnnotations + 63
    0x10000149b <+11>: xorl   %eax, %eax
    0x10000149d <+13>: popq   %rbp
    0x10000149e <+14>: retq   

Таким образом, полученные инструкции на самом деле одинаковы, и время их выполнения должно быть довольно близким.

person Durdu    schedule 01.08.2017
comment
Интересно. И это говорит о том, что компилятор упускает довольно важную возможность оптимизации. Я предлагаю отправить сообщение об ошибке в проект Swift с открытым исходным кодом. - person rickster; 01.08.2017
comment
Какой уровень оптимизации? - person Code Different; 01.08.2017
comment
Код отличается, я обновил ответ - person Durdu; 01.08.2017

Я бы проверил этот пост . Оба они приводят к одним и тем же базовым инструкциям по сборке. Я предполагаю, что они оба требуют такого небольшого количества времени для компиляции, что разница во времени, которую вы замечаете, может быть связана с другими различными выбросами, влияющими на производительность.

person BlueBear    schedule 01.08.2017
comment
Это маловероятно, потому что я повторил тест несколько раз, используя несколько сценариев. Приведенные выше примеры — это всего лишь несколько кратких примеров кода. - person Durdu; 01.08.2017
comment
Спасибо Джонатан за упоминание сборки. ИДК, где был мой разум... - person Durdu; 01.08.2017