Slide 1

Slide 1 text

@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.

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

@miciek Hello, I’d like to hear a functional programming joke 関数型プログラミングの冗談を聴いたことがある

Slide 4

Slide 4 text

@miciek OK. Why did the chicken cross the road? functional programming joke どうしてニワトリは道路路を渡るの?

Slide 5

Slide 5 text

@miciek cross the road? I don’t know. Why? 分かりません。どうしてでしょう?

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

@miciek The best way to understand it comes from the idea of contravariant functor. It’s very simple really. 理理解するための最良の⽅方法は、 反変ファンクターの考えから来ています。

Slide 8

Slide 8 text

@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. ファンクターは圏の構造を保った写像で、 準同型写像とも⾔言われます

Slide 9

Slide 9 text

@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. さて、私たちが表現したいいくつかの構造はファンクタのように⾒見見えます が、ある意味では「変形を逆転させる」のです。私たちはこれらの反変ファ ンクタと呼びます。

Slide 10

Slide 10 text

@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… 私たちは反変ファンクターを単に逆圏の共変ファンクターとして定義しなお すことができます。もちろん、これが圏論的なトポロジカルなプリシーフの ⼀一般化に関連していることにすでにお分かりですね (以下延々

Slide 11

Slide 11 text

@miciek 私は Haskell の冗談を聞きたいです。

Slide 12

Slide 12 text

@miciek AST & UNCTIONAL F F

Slide 13

Slide 13 text

@miciek UNCTIONAL F very modular plug & play using functional mechanics quickly replacing modules without affecting the logic simple real-world service in Scala モジュール性、プラグアンドプレイ

Slide 14

Slide 14 text

@miciek F 1st meaning: PERFORMANCE AST Fast の第⼀一義は、実⾏行行速度

Slide 15

Slide 15 text

@miciek F 2nd meaning: DEV SPEED AST very modular plug & play Fast の第⼆二義は、開発速度

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

@miciek Influencer Stats インフルエンサーの統計情報

Slide 18

Slide 18 text

@miciek We need a marketing strategy for our product! Marketing マーケティング

Slide 19

Slide 19 text

@miciek Remember when… Old Ways Don’t Work …people watched TV みんながテレビを⾒見見ていた時代の古いやり⽅方は通⽤用しない

Slide 20

Slide 20 text

@miciek Influencers 22 237 likes 2302 likes, 70 retweets 201 232 views, 23987 likes 502 123 views, 2012 likes …and more 今のインフルエンサー

Slide 21

Slide 21 text

@miciek Influencers items aggregation 1 201 882 views, 423 987 likes …and more All tweets, youtube videos, etc for one product ⼀一つのプロダクトに関して全てのアイテムを集約

Slide 22

Slide 22 text

@miciek Influencer Stats service collection of videos how many total views how many total likes 動画、PV、like 数など

Slide 23

Slide 23 text

@miciek Requirement #1 Collections ability to add & update Collections of videos … COLLECTION 1 … COLLECTION 2 要件1: 動画のコレクションを作成、更更新できること

Slide 24

Slide 24 text

@miciek Requirement #2 Fetch YouTube Stats ability to fetch individual video stats through YouTube API YouTube API 20 views, 2 likes 要件2: 個々の動画に関して統計を取得できること

Slide 25

Slide 25 text

@miciek Requirement #3 Calculate Stats ability to calculate & return Collection statistics … 1 201 882 views, 423 987 likes 要件3: コレクション全体の統計情報を集計できること

Slide 26

Slide 26 text

@miciek Non-functional requirements ✓HTTP Web Server ✓HTTP Client ✓Collection Storage ✓Logging ⾮非機能要件

Slide 27

Slide 27 text

@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 副作⽤用はテストしづらい

Slide 28

Slide 28 text

@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 とは⾔言っても機能の多くは副作⽤用を伴う

Slide 29

Slide 29 text

@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 側へと移⾏行行させる

Slide 30

Slide 30 text

@miciek ULTIMATE GOAL move as much as we can to the PURE side できる限り多くの機能を pure 側へと移⾏行行させる

Slide 31

Slide 31 text

@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) 隔離された単体でテストしたり、論理理的に振る舞いを分析したり、 コンポーネントを差し替えるのが容易易な状態になるのが究極の⽬目標

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

@miciek Model e.g. -a YouTube video -instagram post -tweet Model の実装を考える

Slide 35

Slide 35 text

@miciek Pure logic f video #1 stats video #2 stats aggregated stats 純粋なロジック

Slide 36

Slide 36 text

@miciek Pure logic

Slide 37

Slide 37 text

@miciek Pure logic

Slide 38

Slide 38 text

@miciek Pure logic … 1 201 882 views, 423 987 likes easy to test easy to reason about PURE WIN!

Slide 39

Slide 39 text

@miciek Can it be as easy as this? f input value output value NOPE では次のような関数は?

Slide 40

Slide 40 text

@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 いくつか問題があります。

Slide 41

Slide 41 text

@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 副作⽤用があるからです。

Slide 42

Slide 42 text

@miciek Side-effect’y stuff

Slide 43

Slide 43 text

@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

Slide 44

Slide 44 text

@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

Slide 45

Slide 45 text

@miciek Specific effect type 特定の作⽤用を表す型が使われています。

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

@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 とだけ弱く指定します。

Slide 48

Slide 48 text

@miciek synchronous asynchronous IO effect type F[_]

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

@miciek We can’t constrain ourselves What we have What we want F doesn’t do anything F is chosen by the user 制限を後付けすることはできません。

Slide 52

Slide 52 text

@miciek Constraints Liberate F doesn’t do anything F is chosen by the user Constraints Liberate Liberties Constrain 制限は解放し、⾃自由は制限する

Slide 53

Slide 53 text

@miciek Get collection collectionId

Slide 54

Slide 54 text

@miciek Get collection collectionId just an algebra

Slide 55

Slide 55 text

@miciek Get videoIds from it

Slide 56

Slide 56 text

@miciek For each videoId call YouTube API

Slide 57

Slide 57 text

@miciek For each videoId call YouTube API

Slide 58

Slide 58 text

@miciek Call our pure calculate function

Slide 59

Slide 59 text

@miciek (and log some things in between)

Slide 60

Slide 60 text

@miciek (and log some things in between)

Slide 61

Slide 61 text

@miciek Signature is enough

Slide 62

Slide 62 text

@miciek

Slide 63

Slide 63 text

@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

Slide 64

Slide 64 text

@miciek algebras ✓Collections interpreter ✓HTTP Client interpreter ✓Collection storage interpreter ✓Logging interpreter interpreters ✓Collections algebra ✓HTTP Client algebra ✓Logging algebra 代数 | インタプリタ

Slide 65

Slide 65 text

@miciek algebra interpreter

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

@miciek algebra interpreters - AkkaHttp - Hammock (Apache) - Http4s - InMem LinkedList - InMem TrieMap - Log All - Max 1k/sec (dropping rest) plug & play 代数 | インタプリタ

Slide 68

Slide 68 text

@miciek Make it fast ⾼高速化

Slide 69

Slide 69 text

@miciek @miciek Warning Do not perform any of the following stunts on PRODUCTION. 注意! プロダクションで⾏行行ってはいけません

Slide 70

Slide 70 text

@miciek wrk -t1 -c16 -d30s --latency URL We will use wrk 1 thread 16 connections 30 sec duration ベンチマークツール: wrk

Slide 71

Slide 71 text

@miciek We will use async-profiler jps cd async-profiler ./profiler.sh -d 10 -f https://github.com/jvm-profiling-tools/async-profiler プロファイラ: async-profiler

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

@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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

@miciek Version 1 Flame Graph

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

@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

Slide 78

Slide 78 text

@miciek Version 2 Flame Graph

Slide 79

Slide 79 text

@miciek -don’t change the logic -change the VideoClient type class instance Version 3: Change the Video Client クライアントを代えてみる

Slide 80

Slide 80 text

@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)

Slide 81

Slide 81 text

@miciek Version 3 Flame Graph

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

@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

Slide 84

Slide 84 text

@miciek Version 4 Flame Graph

Slide 85

Slide 85 text

@miciek Version 4 Flame Graph

Slide 86

Slide 86 text

@miciek -don’t change the logic -change the underlying server from Akka HTTP to Http4s Version 5: Change the Server サーバーを代えてみる

Slide 87

Slide 87 text

@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

Slide 88

Slide 88 text

@miciek Version 5 Flame Graph

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

@miciek Introducing…

Slide 91

Slide 91 text

@miciek

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

@miciek This is a BUS. You invented a BUS. Cheaper taxi that drives on fixed routes! それはバスです。あなたはバスを発⾒見見したのです。

Slide 94

Slide 94 text

@miciek Introducing… Algebras & Interpreters

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

@miciek Scala FP

Slide 97

Slide 97 text

@miciek Java

Slide 98

Slide 98 text

@miciek Interfaces

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

@miciek Algebras

Slide 102

Slide 102 text

@miciek Constrained effect type

Slide 103

Slide 103 text

@miciek Dependencies

Slide 104

Slide 104 text

@miciek Dependencies

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

@miciek Conclusions 結論

Slide 107

Slide 107 text

@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 インフラの詳細を変えましたが、コアロジックは変えていません!

Slide 108

Slide 108 text

@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! コアロジックを変えることなく実装の差し替えに成功しました

Slide 109

Slide 109 text

@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, …

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

@miciek You learned… AST & UNCTIONAL F F modularity (the λ way!) plug & play simple real-world service in Scala モジュール性とプラグアンドプレイ

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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