Slow Swift

Slow Swift

Exploring Swift runtime performance. Singapore 2017. http://iOSConf.sg

Video: https://www.youtube.com/watch?v=G88qaR9R0v0

7b2fdba8077c8495b3caa6f36d0928da?s=128

Marcin Krzyzanowski

October 20, 2017
Tweet

Transcript

  1. 3.
  2. 4.
  3. 5.

    –Waldi Ravens “A Objective- (red.) C program is like a

    fast dance on a newly waxed dance floor by people carrying razors.” Why Swift?
  4. 6.

    –Waldi Ravens “A Objective- (red.) C program is like a

    fast dance on a newly waxed dance floor by people carrying razors.” Why Swift?
  5. 10.

    Compiled Swift • Optimized builds • Build times ;-( let

    arr: [Int] = [1] + [2] + [3] + [4] + [5] + [6]
  6. 11.

    Compiled Swift • Optimized builds • Build times ;-( let

    arr: [Int] = [1] + [2] + [3] + [4] + [5] + [6] Expression is too complex to be solved in reasonable time
  7. 18.

    Compilation GCC_GENERATE_DEBUGGING_SYMBOLS The shortcuts taken by optimized code may occasionally

    produce surprising results: some variables you declared may not exist at all
  8. 19.

    Source Optimization • &+ and &- and &* but +

    and - and * • discarding any overflow (~~SWIFT_DISABLE_SAFETY_CHECKS) • init(truncatingIfNeeded:) • init(truncatingBitPattern:) no longer public ;-) • private init(_truncatingBits:) uses Builtin.truncOrBitCast
  9. 20.

    Source Optimization In-Out Parameters –Swift Programming Language “An inout parameter

    has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.” func core(block: inout Array<UInt8>)
  10. 21.

    Source Optimization • Can be optimized to pass-by-value • Pointers

    are useful for performance In-Out Parameters
  11. 26.

    Source Optimization • for-loop over map • for-loop over reduce

    • transformation over the dictionary with reduce may end up with O(n2)
  12. 32.

    Source Optimization Inlining • Automatic inlining (SIL, LLVM) • Inline

    all the things with @inline(__always) • Force inlining with @_transparent
  13. 33.

    Source Optimization Inlining • Automatic inlining (SIL, LLVM) • Inline

    all the things with @inline(__always) • Force inlining with @_transparent • Public interface @_inlineable
  14. 34.

    Source Optimization Inlining • Automatic inlining (SIL, LLVM) • Inline

    all the things with @inline(__always) • Force inlining with @_transparent • Public interface @_inlineable • Be careful with ABI and public API
  15. 35.
  16. 36.
  17. 37.

    Memory • What if…. raw chunk of memory (Unmanaged) •

    allocate buffer • deallocate buffer • no ARC, no COW, nothing
  18. 38.
  19. 39.

    Array<UInt8>() turns out to be nearly 10% slower compared to

    UnsafeMutablePointer<UInt8>.allocate(capacity:) Memory
  20. 42.

    Memory Stack free space Heap Static data Literals Instructions •

    Stack allocation - fast (%rsp) • Heap allocation - slow (slower) (syscalls)
  21. 43.

    Memory Stack free space Heap Static data Literals Instructions •

    Stack allocation - fast (%rsp) • Heap allocation - slow (slower) (syscalls) • Preallocation
  22. 44.

    Memory Stack free space Heap Static data Literals Instructions •

    Stack allocation - fast (%rsp) • Heap allocation - slow (slower) (syscalls) • Preallocation • array.reserveCapacity(1024)
  23. 45.
  24. 47.

    Allocation Stack free space Heap Static data Literals Instructions (lldb)

    register read rsp rsp = 0x00007fff5fbff630 (lldb) frame variable -L 0x00007fff5fbff658: ([Int]) array = 3 values { 0x00007fa5391de610: [0] = 0 0x00007fa53e6bf3f0: [1] = -1 0x00007fa53e6a91d0: [2] = 1 }
  25. 49.

    Allocation Stack free space Heap Static data Literals Instructions (lldb)

    register read rsp rsp = 0x000070000ec06c00 (lldb) fr variable -L 0x000070000ec06c18: (@lvalue [Int]) array = 0x0000000100d002b0: { 0x0000000100d002b0: &array = 2 values { 0x00007fd7df41ae10: [0] = 0 0x00007fd7df485c90: [1] = -1 0x00007fd7df4829b0: [2] = 1 }
  26. 51.

    Allocation Stack free space Heap Static data Literals Instructions (lldb)

    register read rsp rsp = 0x000070000ec06c00 (lldb) fr variable -L 0x00007fff5fbff680: (@lvalue MyStruct) s = 0x0000000100f06820: { 0x0000000100f06820: &s = { 0x0000000100f06820: value = "test" } }
  27. 52.
  28. 53.

    –who knows “Generic code enables you to write flexible, reusable

    functions and types that can work with any type, subject to requirements that you define.”
  29. 54.
  30. 55.
  31. 57.
  32. 59.
  33. 60.
  34. 61.
  35. 64.

    Generics & Optimization • Automatic specialization • in the same

    module • otherwise use @_specialize(exported: true, where T == Int)
  36. 65.

    Generics & Optimization • Automatic specialization • in the same

    module • otherwise use @_specialize(exported: true, where T == Int) • Whole Module Optimization won’t help
  37. 66.

    Generics & Optimization • Automatic specialization • in the same

    module • otherwise use @_specialize(exported: true, where T == Int) • Whole Module Optimization won’t help • Sometimes it won’t optimize for the same module
  38. 67.

    Generics & Optimization • Automatic specialization • in the same

    module • otherwise use @_specialize(exported: true, where T == Int) • Whole Module Optimization won’t help • Sometimes it won’t optimize for the same module • Avoid generics in public API