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

Fast & Functional (Scala Matsuri, JP)

Fast & Functional (Scala Matsuri, JP)

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.

6f6dc1b13fd3fe35d36db3adafcb0c8e?s=128

Michał Płachta

June 29, 2019
Tweet

Transcript

  1. @miciek AST & UNCTIONAL F F Room A, 14:00 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.
  2. @miciek λ Michał Płachta www.michalplachta.com @miciek AST & UNCTIONAL F

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

    関数型プログラミングの冗談を聴いたことがある
  4. @miciek OK. Why did the chicken cross the road? functional

    programming joke どうしてニワトリは道路路を渡るの?
  5. @miciek cross the road? I don’t know. Why? 分かりません。どうしてでしょう?

  6. @miciek It’s very simple really. I don’t know. Why? それは本当にとても簡単です。

  7. @miciek The best way to understand it comes from the

    idea of contravariant functor. It’s very simple really. 理理解するための最良の⽅方法は、 反変ファンクターの考えから来ています。
  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. ファンクターは圏の構造を保った写像で、 準同型写像とも⾔言われます
  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. さて、私たちが表現したいいくつかの構造はファンクタのように⾒見見えます が、ある意味では「変形を逆転させる」のです。私たちはこれらの反変ファ ンクタと呼びます。
  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… 私たちは反変ファンクターを単に逆圏の共変ファンクターとして定義しなお すことができます。もちろん、これが圏論的なトポロジカルなプリシーフの ⼀一般化に関連していることにすでにお分かりですね (以下延々
  11. @miciek 私は Haskell の冗談を聞きたいです。

  12. @miciek AST & UNCTIONAL F F

  13. @miciek UNCTIONAL F very modular plug & play using functional

    mechanics quickly replacing modules without affecting the logic simple real-world service in Scala モジュール性、プラグアンドプレイ
  14. @miciek F 1st meaning: PERFORMANCE AST Fast の第⼀一義は、実⾏行行速度

  15. @miciek F 2nd meaning: DEV SPEED AST very modular plug

    & play Fast の第⼆二義は、開発速度
  16. @miciek In this talk… AST & UNCTIONAL F F modularity

    (the λ way!) plug & play simple real-world service in Scala
  17. @miciek Influencer Stats インフルエンサーの統計情報

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

    マーケティング
  19. @miciek Remember when… Old Ways Don’t Work …people watched TV

    みんながテレビを⾒見見ていた時代の古いやり⽅方は通⽤用しない
  20. @miciek Influencers 22 237 likes 2302 likes, 70 retweets 201

    232 views, 23987 likes 502 123 views, 2012 likes …and more 今のインフルエンサー
  21. @miciek Influencers items aggregation 1 201 882 views, 423 987

    likes …and more All tweets, youtube videos, etc for one product ⼀一つのプロダクトに関して全てのアイテムを集約
  22. @miciek Influencer Stats service collection of videos how many total

    views how many total likes 動画、PV、like 数など
  23. @miciek Requirement #1 Collections ability to add & update Collections

    of videos … COLLECTION 1 … COLLECTION 2 要件1: 動画のコレクションを作成、更更新できること
  24. @miciek Requirement #2 Fetch YouTube Stats ability to fetch individual

    video stats through YouTube API YouTube API 20 views, 2 likes 要件2: 個々の動画に関して統計を取得できること
  25. @miciek Requirement #3 Calculate Stats ability to calculate & return

    Collection statistics … 1 201 882 views, 423 987 likes 要件3: コレクション全体の統計情報を集計できること
  26. @miciek Non-functional requirements ✓HTTP Web Server ✓HTTP Client ✓Collection Storage

    ✓Logging ⾮非機能要件
  27. @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 副作⽤用はテストしづらい
  28. @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 とは⾔言っても機能の多くは副作⽤用を伴う
  29. @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 できる限り多くの機能を pure 側へと移⾏行行させる
  30. @miciek ULTIMATE GOAL move as much as we can to

    the PURE side できる限り多くの機能を pure 側へと移⾏行行させる
  31. @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) 隔離された単体でテストしたり、論理理的に振る舞いを分析したり、 コンポーネントを差し替えるのが容易易な状態になるのが究極の⽬目標
  32. @miciek What happens next… intro code Java code performance tests

    t we are here
  33. @miciek Modular programming using algebras 代数を利利⽤用したモジュラープログラミング

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

    の実装を考える
  35. @miciek Pure logic f video #1 stats video #2 stats

    aggregated stats 純粋なロジック
  36. @miciek Pure logic

  37. @miciek Pure logic

  38. @miciek Pure logic … 1 201 882 views, 423 987

    likes easy to test easy to reason about PURE WIN!
  39. @miciek Can it be as easy as this? f input

    value output value NOPE では次のような関数は?
  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 pure calculate function (and log some things in between) f input value output value f input value output value いくつか問題があります。
  41. @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 副作⽤用があるからです。
  42. @miciek Side-effect’y stuff

  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
  44. @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
  45. @miciek Specific effect type 特定の作⽤用を表す型が使われています。

  46. @miciek Too powerful effect type :( 作⽤用型が強すぎます。

  47. @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 モナドの F とだけ弱く指定します。
  48. @miciek synchronous asynchronous IO effect type F[_]

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

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

    the user
  51. @miciek We can’t constrain ourselves What we have What we

    want F doesn’t do anything F is chosen by the user 制限を後付けすることはできません。
  52. @miciek Constraints Liberate F doesn’t do anything F is chosen

    by the user Constraints Liberate Liberties Constrain 制限は解放し、⾃自由は制限する
  53. @miciek Get collection collectionId

  54. @miciek Get collection collectionId just an algebra

  55. @miciek Get videoIds from it

  56. @miciek For each videoId call YouTube API

  57. @miciek For each videoId call YouTube API

  58. @miciek Call our pure calculate function

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

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

  61. @miciek Signature is enough

  62. @miciek

  63. @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
  64. @miciek algebras ✓Collections interpreter ✓HTTP Client interpreter ✓Collection storage interpreter

    ✓Logging interpreter interpreters ✓Collections algebra ✓HTTP Client algebra ✓Logging algebra 代数 | インタプリタ
  65. @miciek algebra interpreter

  66. @miciek What happens next… intro code Java code performance tests

    t we are here
  67. @miciek algebra interpreters - AkkaHttp - Hammock (Apache) - Http4s

    - InMem LinkedList - InMem TrieMap - Log All - Max 1k/sec (dropping rest) plug & play 代数 | インタプリタ
  68. @miciek Make it fast ⾼高速化

  69. @miciek @miciek Warning Do not perform any of the following

    stunts on PRODUCTION. 注意! プロダクションで⾏行行ってはいけません
  70. @miciek wrk -t1 -c16 -d30s --latency URL We will use

    wrk 1 thread 16 connections 30 sec duration ベンチマークツール: wrk
  71. @miciek We will use async-profiler jps cd async-profiler ./profiler.sh -d

    10 -f <FILE> <PID> https://github.com/jvm-profiling-tools/async-profiler プロファイラ: async-profiler
  72. @miciek We will use flame graphs http://www.brendangregg.com/flamegraphs.html read from bottom

  73. @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
  74. @miciek Version 1 Results # requests 99% latency avg latency

    req/s Version 1 8510 82.41ms 56.47ms 283.12
  75. @miciek Version 1 Flame Graph

  76. @miciek -don’t change the logic -just change the Logger interpreter

    -dropping logs if the rate is > 1k per second Version 2: Dropping logs
  77. @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
  78. @miciek Version 2 Flame Graph

  79. @miciek -don’t change the logic -change the VideoClient type class

    instance Version 3: Change the Video Client クライアントを代えてみる
  80. @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)
  81. @miciek Version 3 Flame Graph

  82. @miciek -don’t change the logic -cache results and call logic

    in separate thread Version 4: Statistics Caching
  83. @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
  84. @miciek Version 4 Flame Graph

  85. @miciek Version 4 Flame Graph

  86. @miciek -don’t change the logic -change the underlying server from

    Akka HTTP to Http4s Version 5: Change the Server サーバーを代えてみる
  87. @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
  88. @miciek Version 5 Flame Graph

  89. @miciek Inventions That Already Exist 既にあるものを発明する

  90. @miciek Introducing…

  91. @miciek

  92. @miciek Introducing… Cheaper taxi that drives on fixed routes! 固定ルートの格安タクシーがあったら...

  93. @miciek This is a BUS. You invented a BUS. Cheaper

    taxi that drives on fixed routes! それはバスです。あなたはバスを発⾒見見したのです。
  94. @miciek Introducing… Algebras & Interpreters

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

    an INTERFACE.
  96. @miciek Scala FP

  97. @miciek Java

  98. @miciek Interfaces

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

  100. @miciek Return type difference: we need to choose the effect

    type which is very powerful
  101. @miciek Algebras

  102. @miciek Constrained effect type

  103. @miciek Dependencies

  104. @miciek Dependencies

  105. @miciek Algebras & Interpreters Not an INTERFACE. major difference: we

    can abstract over the effect type and constrain ourselves using F instead of CompletableFuture…
  106. @miciek Conclusions 結論

  107. @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 インフラの詳細を変えましたが、コアロジックは変えていません!
  108. @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! コアロジックを変えることなく実装の差し替えに成功しました
  109. @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, …
  110. @miciek Interpreters integration test https://www.testcontainers.org/

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

  112. @miciek You learned… AST & UNCTIONAL F F modularity (the

    λ way!) plug & play simple real-world service in Scala モジュール性とプラグアンドプレイ
  113. @miciek Learn More https://github.com/miciek/influencer-stats

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

    F Thanks!