Pro Yearly is on sale from $80 to $50! »

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. 2017 Slow Swift

  2. Marcin Krzyżanowski @krzyzanowskim PDFViewer.io pspdfkit.com github.com/krzyzanowskim CryptoSwift ObjectivePGP Natalie krzyzanowskim.com

  3. None
  4. 1.4x

  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?
  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?
  7. Script Swift? #!/usr/bin/env xcrun -sdk macosx swift print(“iOSConf.sg Rocks!”)

  8. Script Swift? #!/usr/bin/env xcrun -sdk macosx swift print(“iOSConf.sg Rocks!”) -Onone

    500x to 1000x slower than default optimized build
  9. Compiled Swift • Optimized builds • Build times ;-(

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

    arr: [Int] = [1] + [2] + [3] + [4] + [5] + [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
  12. Compiled Swift “Speedup AES.encrypt() compilation time from 68230.37ms to 678.34ms”

  13. Source → Binary as seen…

  14. Compilation SWIFT_OPTIMIZATION_LEVEL -Onone -O -O -whole-module-optimization

  15. Compilation SWIFT_OPTIMIZATION_LEVEL -Onone -O -O -whole-module-optimization

  16. Compilation SWIFT_DISABLE_SAFETY_CHECKS Disable runtime safety checks when optimizing.

  17. Compilation SWIFT_ENFORCE_EXCLUSIVE_ACCESS full compile-time none (SE-0176)

  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
  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
  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>)
  21. Source Optimization • Can be optimized to pass-by-value • Pointers

    are useful for performance In-Out Parameters
  22. Source Optimization Obvious • struct over class • final class

    • private final class
  23. Source Optimization non-Obvious 2.7s

  24. Source Optimization non-Obvious

  25. Source Optimization non-Obvious 1.2s 2.7s

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

    • transformation over the dictionary with reduce may end up with O(n2)
  27. Source Optimization 0.9s

  28. Source Optimization 0.8s

  29. Source Optimization Inlining

  30. Source Optimization Inlining • Automatic inlining (SIL, LLVM)

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

    all the things with @inline(__always)
  32. Source Optimization Inlining • Automatic inlining (SIL, LLVM) • Inline

    all the things with @inline(__always) • Force inlining with @_transparent
  33. Source Optimization Inlining • Automatic inlining (SIL, LLVM) • Inline

    all the things with @inline(__always) • Force inlining with @_transparent • Public interface @_inlineable
  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
  35. Memory

  36. Memory

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

    allocate buffer • deallocate buffer • no ARC, no COW, nothing
  38. Memory

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

    UnsafeMutablePointer<UInt8>.allocate(capacity:) Memory
  40. Memory Stack free space Heap Static data Literals Instructions 0x000000

    0xFFFFFF
  41. Memory Stack free space Heap Static data Literals Instructions •

    Stack allocation - fast (%rsp)
  42. Memory Stack free space Heap Static data Literals Instructions •

    Stack allocation - fast (%rsp) • Heap allocation - slow (slower) (syscalls)
  43. Memory Stack free space Heap Static data Literals Instructions •

    Stack allocation - fast (%rsp) • Heap allocation - slow (slower) (syscalls) • Preallocation
  44. Memory Stack free space Heap Static data Literals Instructions •

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

  46. Allocation Stack free space Heap Static data Literals Instructions

  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 }
  48. Allocation Stack free space Heap Static data Literals Instructions

  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 }
  50. Allocation Stack free space Heap Static data Literals Instructions

  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" } }
  52. Generics

  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.”
  54. None
  55. Generics

  56. Generics 0.20s

  57. Generics

  58. Generics 0.06s 0.20s

  59. Generics

  60. Generics

  61. Generics

  62. Generics & Optimization • Automatic specialization

  63. Generics & Optimization • Automatic specialization • in the same

    module
  64. Generics & Optimization • Automatic specialization • in the same

    module • otherwise use @_specialize(exported: true, where T == Int)
  65. Generics & Optimization • Automatic specialization • in the same

    module • otherwise use @_specialize(exported: true, where T == Int) • Whole Module Optimization won’t help
  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
  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
  68. Let's Recap…

  69. Let's Recap… Debug is slow

  70. Pre-allocate memory Let's Recap…

  71. Let's Recap… Stack vs Heap

  72. Let's Recap…Copy is bad

  73. Let's Recap… Use carefully

  74. Let's Recap… Less Swift is faster Swift

  75. @krzyzanowskim krzyzanowskim.com Thank you!