Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Swift Performance - Try! Swift 2016

Introduction to Swift Performance - Try! Swift 2016

Danielle Tomlinson

September 01, 2016
Tweet

More Decks by Danielle Tomlinson

Other Decks in Programming

Transcript

  1. An Introduction to
    Swift Performance
    Danielle Tomlinson - @dantoml

    View Slide

  2. What makes code slow?

    View Slide

  3. Allocation

    View Slide

  4. Stack

    View Slide

  5. Heap

    View Slide

  6. Reference Counting

    View Slide

  7. func perform(with object: Object) {
    object.doAThing()
    }

    View Slide

  8. func perform(with object: Object) {
    __swift_retain(object)
    object.doAThing()
    __swift_release(object)
    }

    View Slide

  9. Dispatch

    View Slide

  10. Inline (0ns)

    View Slide

  11. Static (~1ns)

    View Slide

  12. Dynamic (~5ns)

    View Slide

  13. Objects

    View Slide

  14. Classes

    View Slide

  15. p: Index*
    Stack
    class Index {
    let section: Int
    let item: Int
    }
    let i = Index(section: 1,
    item: 1)
    Heap
    section: Int
    item: Int

    View Slide

  16. i: Index*
    Stack
    class Index {
    let section: Int
    let item: Int
    }
    let i = Index(section: 1,
    item: 1)
    let i2 = i
    Heap
    section: Int
    item: Int
    i2: Index*

    View Slide

  17. i: Index*
    Stack
    class Index {
    let section: Int
    let item: Int
    }
    let i = Index(section: 1,
    item: 1)
    __swift_retain(i)
    let i2 = i
    Heap
    section: Int
    item: Int
    i2: Index*

    View Slide

  18. Structs

    View Slide

  19. Stack

    View Slide

  20. section: 1
    item: 1
    Stack
    struct Index {
    let section: Int
    let item: Int
    }
    let i = Index(section: 1, item: 1)

    View Slide

  21. Stack
    struct Index {
    let section: Int
    let item: Int
    }
    let i = Index(section: 1, item: 1)
    let i2 = i
    section: 1
    item: 1
    section: 1
    item: 1

    View Slide

  22. name: StringA*
    id: StringB*
    Stack
    struct User {
    let name: String
    let id: String
    }
    let u = User(name: "Joe", id: "1234")

    View Slide

  23. name: StringA*
    id: StringB*
    Stack
    name: StringA*
    id: StringB*
    struct User {
    let name: String
    let id: String
    }
    let u = User(name: "Joe",
    id: "1234")
    __swift_retain(u.name._textStorage)
    __swift_retain(u.id._textStorage)
    let u2 = u

    View Slide

  24. Abstractions

    View Slide

  25. Example (0.3s)
    :
    struct Circle {
    let radius: Double
    let center: Point
    func draw() {}
    }
    var circles = (1..<100_000_000).map { _ in Circle(...) }
    for circle in circles {
    circle.draw()
    }

    View Slide

  26. Requirements Change

    View Slide

  27. Protocols

    View Slide

  28. Example (4s)
    :
    protocol Drawable {
    func draw()
    }
    struct Circle: Drawable {
    let radius: Double
    let center: Point
    func draw() {}
    }
    let drawables: [Drawable] = (1..<100_000_000).map { _ in Circle(...) }
    for drawable in drawables {
    drawable.draw()
    }

    View Slide

  29. Why?

    View Slide

  30. struct Circle {
    let radius: Double
    let center: Point
    func draw() {}
    }
    var circles = (1..<100_000_000).map { _ in Circle(...) }
    for circle in circles {
    circle.draw()
    }

    View Slide

  31. protocol Drawable {
    func draw()
    }
    struct Circle: Drawable {
    let radius: Double
    let center: Point
    func draw() {}
    }
    var drawables: [Drawable] = (1..<100_000_000).map { _ in return Circle(...) }
    for drawable in drawables {
    drawable.draw()
    }

    View Slide

  32. ProtocolWitnessTable
    draw()
    CircleDrawable
    ...
    draw()
    LineDrawable
    ...

    View Slide

  33. protocol Drawable {
    func draw()
    }
    struct Circle: Drawable {
    let radius: Double
    let center: Point
    func draw() {}
    }
    var drawables: [Drawable] = (1..<100_000_000).map { _ in
    return Circle(...)
    }
    for drawable in drawables {
    drawable.draw()
    }
    draw()
    CircleDrawable
    ...

    View Slide

  34. ExistentialContainer
    ValueBuffer
    ProtocolWitnessTable

    View Slide

  35. ExistentialContainer
    radius
    struct Circle: Drawable {
    let radius: Double
    let center: Point
    func draw() {}
    }
    center

    View Slide

  36. ExistentialContainer
    struct Line: Drawable {
    let origin: Point
    let end: Point
    func draw() {}
    }
    Origin
    End

    View Slide

  37. Example (45s)
    :
    protocol Drawable {
    func draw()
    }
    struct Line: Drawable {
    let origin: Point
    let end: Point
    func draw() {}
    }
    let drawables: [Drawable] = (1..<100_000_000).map { _ in Line(...) }
    for drawable in drawables {
    drawable.draw()
    }

    View Slide

  38. View Slide

  39. ValueWitnessTable
    ValueBuffer
    allocate:
    copy:
    destruct:
    deallocate:

    View Slide

  40. In Practice
    Stack
    origin
    Line
    vwt
    pwt
    end
    LineDrawable
    copy:
    ...
    Heap
    drawable:
    func draw(drawable: Drawable) {
    drawable.draw()
    }
    let value: Drawable = Line()
    draw(local: value)
    // Generates
    func draw(value: ECTDrawable) {
    var drawable: ECTDrawable = ECTDrawable()
    let vwt = value.vwt
    let pwt = value.pwt
    drawable.vwt = value.vwt
    drawable.pwt = value.pwt
    vwt.allocateBuffAndCopyValue(&drawable, value)
    pwt.draw(vwt.projectBuffer(&drawable)
    }

    View Slide

  41. Modelling Your Data

    View Slide

  42. Generics

    View Slide

  43. struct Stack {
    ...
    }

    View Slide

  44. Enumerations

    View Slide

  45. enum AccountStatus: String, RawRepresentable {
    case .banned, .verified, incomplete
    }

    View Slide

  46. Domain Specific Models

    View Slide

  47. Thanks!
    Office Hours: 16:30 in the Atrium. @dantoml

    View Slide