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

Fast & Functional

Fast & Functional

In this talk we are going to create a functional and blazingly fast microservice. We will use functional programming abstractions to quickly mix & match different HTTP libraries, state implementations and concurrency configurations. Each step will be followed by a performance analysis using different tools from JVM toolbox. This talk is for you if you want to see how cats IO monad, async-profiler, flame graphs and wrk are used together to create microseconds-fast Scala service for YouTube videos statistics.

Michał Płachta

February 22, 2019
Tweet

More Decks by Michał Płachta

Other Decks in Programming

Transcript

  1. @miciek
    AST &
    UNCTIONAL
    F
    F
    In this talk we are going to create
    a functional and blazingly fast
    microservice in Scala. We will use
    f u n c t i o n a l p r o g r a m m i n g
    abstractions to quickly mix &
    match different HTTP libraries,
    state implementations and
    concurrency configurations. Each
    step will be followed by a
    performance analysis using
    different tools from JVM toolbox.

    View full-size slide

  2. @miciek
    λ
    Michał Płachta
    www.michalplachta.com
    @miciek
    AST &
    UNCTIONAL
    F
    F

    View full-size slide

  3. @miciek
    Hello, I’d like to hear a
    functional programming joke

    View full-size slide

  4. @miciek
    OK. Why did the chicken
    cross the road?
    functional programming joke

    View full-size slide

  5. @miciek
    cross the road?
    I don’t know. Why?

    View full-size slide

  6. @miciek
    It’s very simple really.
    I don’t know. Why?

    View full-size slide

  7. @miciek
    The best way to understand
    it comes from the idea of
    contravariant functor.
    It’s very simple really.

    View full-size slide

  8. @miciek
    As you probably know, a functor is just a
    mapping between categories that respects the
    category structure; a homomorphism, if you
    will.
    contravariant functor.

    View full-size slide

  9. @miciek
    Now, some constructions that we want to
    express look like functors but in some sense
    “turn morphisms around”. We call these
    contravariant functors.
    will.

    View full-size slide

  10. @miciek
    As you have probably noticed, we can indeed define a
    contravariant functor as simply a covariant functor on opposite
    categories, invoking the obvious correspondence. Of course you
    have already noticed the obvious connection this has with the
    category theoretic generalization of topological presheaves — a
    presheaf on a topology is just a contravariant functor from the…

    View full-size slide

  11. @miciek
    AST &
    UNCTIONAL
    F
    F

    View full-size slide

  12. @miciek
    UNCTIONAL
    F
    very modular
    plug & play
    using functional mechanics
    quickly replacing modules
    without affecting the logic
    simple real-world
    service in Scala

    View full-size slide

  13. @miciek
    F
    1st meaning:
    PERFORMANCE
    AST

    View full-size slide

  14. @miciek
    F
    2nd meaning:
    DEV SPEED
    AST
    very modular
    plug & play

    View full-size slide

  15. @miciek
    In this talk…
    AST &
    UNCTIONAL
    F
    F
    modularity (the λ way!)
    plug & play
    simple real-world
    service in Scala

    View full-size slide

  16. @miciek
    Influencer Stats

    View full-size slide

  17. @miciek
    We need a marketing strategy
    for our product!
    Marketing

    View full-size slide

  18. @miciek
    Remember when…
    Old Ways Don’t Work
    …people watched TV

    View full-size slide

  19. @miciek
    Influencers
    22 237 likes 2302 likes, 70 retweets
    201 232 views, 23987 likes 502 123 views, 2012 likes
    …and more

    View full-size slide

  20. @miciek
    Influencers items aggregation
    1 201 882 views, 423 987 likes
    …and more
    All tweets, youtube videos, etc for one product

    View full-size slide

  21. @miciek
    Influencer Stats service
    collection of videos
    how many total views
    how many total likes

    View full-size slide

  22. @miciek
    Requirement #1
    Collections
    ability to
    add & update
    Collections of videos

    COLLECTION 1

    COLLECTION 2

    View full-size slide

  23. @miciek
    Requirement #2
    Fetch YouTube Stats
    ability to
    fetch individual video
    stats through
    YouTube API
    YouTube
    API
    20 views, 2 likes

    View full-size slide

  24. @miciek
    Requirement #3
    Calculate Stats
    ability to
    calculate & return
    Collection statistics

    1 201 882 views, 423 987 likes

    View full-size slide

  25. @miciek
    Non-functional
    requirements
    ✓HTTP Web Server
    ✓HTTP Client
    ✓Collection Storage
    ✓Logging

    View full-size slide

  26. @miciek
    PURE Side-effect’y
    f
    input value output value
    f
    input value


    hard to keep separate
    hard to test
    easy to keep separate
    easy to test

    View full-size slide

  27. @miciek
    PURE
    ✓Save & Load Collections
    ✓Fetch YouTube Stats
    ✓HTTP Web Server
    ✓HTTP Client
    ✓Collection storage
    ✓Logging
    Side-effect’y
    ✓Calculate Stats
    f
    video #1 stats
    video #2 stats
    aggregated stats

    View full-size slide

  28. @miciek
    PURE
    ✓Save & Load Collections
    ✓Fetch YouTube Stats
    ✓HTTP Web Server
    ✓HTTP Client
    ✓Collection storage
    ✓Logging
    Side-effect’y
    ✓Calculate Stats
    ULTIMATE GOAL
    move as much as we
    can to the PURE side

    View full-size slide

  29. @miciek
    ULTIMATE GOAL
    move as much as we
    can to the PURE side

    View full-size slide

  30. @miciek
    ULTIMATE GOAL
    move as much as we
    can to the PURE side
    to test in isolation
    to reason in isolation
    to easily swap components
    (because they are isolated)

    View full-size slide

  31. @miciek
    What happens next…
    intro
    code
    Java code
    performance
    tests
    t
    we are
    here

    View full-size slide

  32. @miciek
    Modular programming
    using algebras

    View full-size slide

  33. @miciek
    Model
    e.g.
    -a YouTube video
    -instagram post
    -tweet

    View full-size slide

  34. @miciek
    Pure logic
    f
    video #1 stats
    video #2 stats
    aggregated stats

    View full-size slide

  35. @miciek
    Pure logic

    View full-size slide

  36. @miciek
    Pure logic

    View full-size slide

  37. @miciek
    Pure logic

    1 201 882 views, 423 987 likes
    easy to test
    easy to reason about
    PURE WIN!

    View full-size slide

  38. @miciek
    Can it be as easy as this?
    f
    input value output value
    NOPE

    View full-size slide

  39. @miciek
    Can it be as easy as this?
    1. get collection collectionId
    2. get videoIds from it
    3. for each videoId, call YouTube API
    4.call our pure calculate function
    (and log some things in between)



    f
    input value output value
    f
    input value output value

    View full-size slide

  40. @miciek
    Can it be as easy as this?
    1. get collection collectionId
    2. get videoIds from it
    3. for each videoId, call YouTube API
    4. call our calculate function
    NOPE
    because side effects




    View full-size slide

  41. @miciek
    Side-effect’y stuff

    View full-size slide

  42. @miciek
    Side-effect’y stuff
    1. get collection collectionId
    2. get videoIds from it
    3. for each videoId, call YouTube API
    4. call our pure calculate function

    View full-size slide

  43. @miciek
    Side-effect’y stuff
    1. get collection collectionId
    2. get videoIds from it
    3. for each videoId, call YouTube API
    4. call our pure calculate function

    View full-size slide

  44. @miciek
    Specific effect type

    View full-size slide

  45. @miciek
    Too powerful effect type :(

    View full-size slide

  46. @miciek
    Side-effect’y stuff
    1. get collection collectionId
    2. get videoIds from it
    3. for each videoId, call YouTube API
    4. call our pure calculate function
    F doesn’t do anything
    F is chosen by the user

    View full-size slide

  47. @miciek
    synchronous
    asynchronous
    IO effect type
    F[_]

    View full-size slide

  48. @miciek
    Constrained?
    A doesn’t do anything
    A is chosen by the user

    View full-size slide

  49. @miciek
    Constrained?
    A doesn’t do anything
    A is chosen by the user

    View full-size slide

  50. @miciek
    We can’t constrain ourselves
    What we have
    What we want
    F doesn’t do anything
    F is chosen by the user

    View full-size slide

  51. @miciek
    Constraints Liberate
    F doesn’t do anything
    F is chosen by the user
    Constraints Liberate
    Liberties Constrain

    View full-size slide

  52. @miciek
    Get collection collectionId

    View full-size slide

  53. @miciek
    Get collection collectionId
    just an algebra

    View full-size slide

  54. @miciek
    Get videoIds from it

    View full-size slide

  55. @miciek
    For each videoId call YouTube API

    View full-size slide

  56. @miciek
    For each videoId call YouTube API

    View full-size slide

  57. @miciek
    Call our pure calculate function

    View full-size slide

  58. @miciek
    (and log some things in between)

    View full-size slide

  59. @miciek
    (and log some things in between)

    View full-size slide

  60. @miciek
    Signature is enough

    View full-size slide

  61. @miciek
    PURE
    ✓Collections interpreter
    ✓HTTP Web Server
    ✓HTTP Client interpreter
    ✓Collection storage interpreter
    ✓Logging interpreter
    Side-effect’y
    ✓Calculate Stats
    ✓Collections algebra
    ✓HTTP Client algebra
    ✓Logging algebra
    ✓getStats algorithm on F

    View full-size slide

  62. @miciek
    algebras
    ✓Collections interpreter
    ✓HTTP Client interpreter
    ✓Collection storage interpreter
    ✓Logging interpreter
    interpreters
    ✓Collections algebra
    ✓HTTP Client algebra
    ✓Logging algebra

    View full-size slide

  63. @miciek
    algebra
    interpreter

    View full-size slide

  64. @miciek
    What happens next…
    intro
    code
    Java code
    performance
    tests
    t
    we are
    here

    View full-size slide

  65. @miciek
    algebra interpreters
    - AkkaHttp
    - Hammock (Apache)
    - Http4s
    - InMem LinkedList
    - InMem TrieMap
    - Log All
    - Max 1k/sec (dropping rest)
    plug & play

    View full-size slide

  66. @miciek
    Make it fast

    View full-size slide

  67. @miciek
    @miciek
    Warning
    Do not perform any of the following stunts
    on PRODUCTION.

    View full-size slide

  68. @miciek
    wrk -t1 -c16 -d30s --latency URL
    We will use wrk
    1 thread
    16
    connections
    30 sec
    duration

    View full-size slide

  69. @miciek
    We will use async-profiler
    jps
    cd async-profiler
    ./profiler.sh -d 10 -f
    https://github.com/jvm-profiling-tools/async-profiler

    View full-size slide

  70. @miciek
    We will use flame graphs
    http://www.brendangregg.com/flamegraphs.html
    read
    from
    bottom

    View full-size slide

  71. @miciek
    Version 1
    # requests
    99%
    latency
    avg
    latency
    req/s
    Version 1 ? ?ms ?ms ?
    -akka-http (client + server)
    -log all things
    -in mem linked list state

    View full-size slide

  72. @miciek
    Version 1 Results
    # requests
    99%
    latency
    avg
    latency
    req/s
    Version 1 8510 82.41ms 56.47ms 283.12

    View full-size slide

  73. @miciek
    Version 1 Flame Graph

    View full-size slide

  74. @miciek
    -don’t change the logic
    -just change the Logger interpreter
    -dropping logs if the rate is > 1k per second
    Version 2: Dropping logs

    View full-size slide

  75. @miciek
    Version 2 Results
    # requests
    99%
    latency
    avg
    latency
    req/s
    Version 1 8510 82.41ms 56.47ms 283.12
    Version 2 89 757 62.53ms 6.94ms 2986.26
    DroppingLogger

    View full-size slide

  76. @miciek
    Version 2 Flame Graph

    View full-size slide

  77. @miciek
    -don’t change the logic
    -change the VideoClient type class instance
    Version 3: Change the Video Client

    View full-size slide

  78. @miciek
    Version 3 Results
    # requests
    99%
    latency
    avg
    latency
    req/s
    Version 1 8510 82.41ms 56.47ms 283.12
    Version 2 89 757 62.53ms 6.94ms 2986.26
    Version 3 96 564 13.05ms 5.06ms 3218.48
    DroppingLogger
    Hammock (Apache)

    View full-size slide

  79. @miciek
    Version 3 Flame Graph

    View full-size slide

  80. @miciek
    -don’t change the logic
    -cache results and call logic in separate thread
    Version 4: Statistics Caching

    View full-size slide

  81. @miciek
    Version 4 Results
    # requests
    99%
    latency
    avg
    latency
    req/s
    Version 1 8510 82.41ms 56.47ms 283.12
    Version 2 89 757 62.53ms 6.94ms 2986.26
    Version 3 96 564 13.05ms 5.06ms 3218.48
    Version 4 933 303 62.86ms 2.87ms 31 081.82
    DroppingLogger
    Hammock (Apache)
    Stats Caching

    View full-size slide

  82. @miciek
    Version 4 Flame Graph

    View full-size slide

  83. @miciek
    Version 4 Flame Graph

    View full-size slide

  84. @miciek
    -don’t change the logic
    -change the underlying server from Akka HTTP
    to Http4s
    Version 5: Change the Server

    View full-size slide

  85. @miciek
    Version 5 Results
    # requests
    99%
    latency
    avg
    latency
    req/s
    Version 1 8510 82.41ms 56.47ms 283.12
    Version 2 89 757 62.53ms 6.94ms 2986.26
    Version 3 96 564 13.05ms 5.06ms 3218.48
    Version 4 933 303 62.86ms 2.87ms 31 081.82
    Version 5 1 158 664 9.05ms 555.80µs 38 596.24
    DroppingLogger
    Hammock (Apache)
    Stats Caching
    Http4s Server

    View full-size slide

  86. @miciek
    Version 5 Flame Graph

    View full-size slide

  87. @miciek
    Inventions That
    Already Exist

    View full-size slide

  88. @miciek
    Introducing…

    View full-size slide

  89. @miciek
    Introducing…
    Cheaper taxi that drives on fixed routes!

    View full-size slide

  90. @miciek
    This is a BUS. You invented a BUS.
    Cheaper taxi that drives on fixed routes!

    View full-size slide

  91. @miciek
    Introducing…
    Algebras & Interpreters

    View full-size slide

  92. @miciek
    Algebras & Interpreters
    This is an INTERFACE. You invented an INTERFACE.

    View full-size slide

  93. @miciek
    Scala FP

    View full-size slide

  94. @miciek
    Interfaces

    View full-size slide

  95. @miciek
    Interfaces
    difference:
    we need to choose the effect type

    View full-size slide

  96. @miciek
    Return type
    difference:
    we need to choose the effect type
    which is very powerful

    View full-size slide

  97. @miciek
    Algebras

    View full-size slide

  98. @miciek
    Constrained effect type

    View full-size slide

  99. @miciek
    Dependencies

    View full-size slide

  100. @miciek
    Dependencies

    View full-size slide

  101. @miciek
    Algebras & Interpreters
    Not an INTERFACE.
    major difference:
    we can abstract over the effect type
    and constrain ourselves
    using F instead of CompletableFuture…

    View full-size slide

  102. @miciek
    Conclusions

    View full-size slide

  103. @miciek
    -changed infrastructure details
    -…but our core logic (and tests) didn’t need to
    change!
    What have we done?
    plug & play
    quickly replacing non-core-logic modules

    View full-size slide

  104. @miciek
    Modularity / Separation of concerns
    if we can..
    replace the server implementation
    replace the state implementation
    replace the logging implementation
    replace the video client implementation
    add caching
    without
    changing the core logic (& tests)
    PURE WIN!

    View full-size slide

  105. @miciek
    PURE
    ✓Collections interpreter
    ✓HTTP Web Server
    ✓HTTP Client interpreter
    ✓Collection storage interpreter
    ✓Logging interpreter
    Side-effect’y
    ✓Calculate Stats
    ✓Collections algebra
    ✓HTTP Client algebra
    ✓Logging algebra
    ✓getStats algorithm on F
    unit-tested integration-tested
    very constrained
    just F[_]
    no constraints
    Future, IO, …

    View full-size slide

  106. @miciek
    Interpreters integration test
    https://www.testcontainers.org/

    View full-size slide

  107. @miciek
    Interpreters integration test
    interpreter
    response
    https://www.testcontainers.org/

    View full-size slide

  108. @miciek
    You learned…
    AST &
    UNCTIONAL
    F
    F
    modularity (the λ way!)
    plug & play
    simple real-world
    service in Scala

    View full-size slide

  109. @miciek
    Learn More
    https://github.com/miciek/influencer-stats

    View full-size slide

  110. @miciek
    λ
    Michał Płachta
    www.michalplachta.com
    @miciek
    AST &
    UNCTIONAL
    F
    F
    Thanks!

    View full-size slide