MAD · NOV 23-24 · 2018 Going Async with Kotlin José María Muñoz Rey Software Engineer at Tuenti MAD · NOV 23-24 · 2018
MAD · NOV 23-24 · 2018 Where should we start? Simplified problem: multiple IO request Index ■ Understand why asynchrony abstractions matters. ■ Asynchrony abstractions. ∘ Callbacks. ∘ Futures (CompletableFutures). ∘ Observables (Reactive Streams/RxJava). ∘ Coroutines.
MAD · NOV 23-24 · 2018 Writing synchronous code Why asynchrony abstraction matters
MAD · NOV 23-24 · 2018 Problem description Simple IO problem: multiple requests to a service. Client: ■ Standard Kotlin, sequential code. ■ Without async abstractions. Server: ■ Ktor. ■ Just responds with a text and waits a custom delay.
MAD · NOV 23-24 · 2018 Our example
MAD · NOV 23-24 · 2018 Simple Synchronous code Request: Session, 500 miliseconds ... Request: Photos, 500 miliseconds Request: News, 500 miliseconds Time required to process this block: 2626 Requests Response
MAD · NOV 23-24 · 2018 Simple Synchronous code What happened? Requests still made sequentially: ■ Main thread blocked: in each request. ■ No parallelism: this code can be benefit from it.
MAD · NOV 23-24 · 2018 What do we need? ■ Last 3 request should run in parallel ■ Abstractions to: ∘ Create them. ∘ Get status, cancel… ∘ Get computed value. We need to call these methods asynchronously.
MAD · NOV 23-24 · 2018 Managing Asynchrony
MAD · NOV 23-24 · 2018 Let’s create Threads for IO !! They help us by letting other code run in parallel, but: ■ They have an high costs (Context switching). ■ They are highly limited. ■ They are hard to manage. ∘ Create/reuse/idle/close. ∘ Cancel work. ∘ Thread pool (computation, IO). ∘ Share info. We need some abstractions.
MAD · NOV 23-24 · 2018 Promises CompletableFuture Futures Deferred Task Asynctask Observable Callbacks Async abstractions!!!! Coroutines/Suspending function
MAD · NOV 23-24 · 2018 What we are going to see today: Main abstractions used in the JVM ■ Callbacks. ■ Futures: CompletableFutures. ■ Observables: Reactive streams (Publisher/subscriber/Observable...). ■ Coroutines.
MAD · NOV 23-24 · 2018 Callbacks
MAD · NOV 23-24 · 2018 Callbacks
MAD · NOV 23-24 · 2018 Callbacks
MAD · NOV 23-24 · 2018 Callbacks ■ Just if necessary. ■ Not enough for Kotlin to handle asynchrony ■ Problems to chain calls (Callbacks hell). ■ Problems to share computed values. ■ Problems to handle errors. Javascript experience: people is moving away. DON’T USE THEM
MAD · NOV 23-24 · 2018 CompetableFutures And well, the others ‘Futures’
MAD · NOV 23-24 · 2018 Promises vs Futures vs CompletableFuture vs Deferred vs Task vs ... “They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.” en.wikipedia.org/wiki/Futures_and_promises
MAD · NOV 23-24 · 2018 Promises vs Futures vs CompletableFuture vs Deferred vs Task vs ... They are (practically) the same thing, but named differently in different languages: ■ Futures: practically everywhere. ■ CompletableFutures: JVM (Java, Kotlin...). ■ Promises: Javascript. ■ Task: C# / Android APIs. ■ Deferred: Koltin. ■ ...
MAD · NOV 23-24 · 2018 CompletableFutures ■ Introduced in Java 8. ■ Improves the actual interface of existing Futures. ■ Compositional programming with chained calls. (Sequential and parallel). ■ Default: Threads from the CommonPool. API: ■ Create: .supplyAsync() ■ Chain: .thenCompose(), .thenApply() or .thenAccept(). ■ Compose: .anyOf(...), .allOf(...). ■ Get value: .get() or .join(). ■ More functionality: .exceptionally(...), .orTimeout().
MAD · NOV 23-24 · 2018 CompletableFutures - Our use case ■ getUserInfo(): CompletableFuture<...>. ■ getPhotos(): CompletableFuture<...>. ■ getFriends(): CompletableFuture<...>. ■ getNews(): CompletableFuture<...>.
MAD · NOV 23-24 · 2018 CompletableFutures - Our use case: Version 1 Request: Session, ... Request: UserInfo, ... Request: Friends, ... Request: Photos, ... Request: News,... Page for ... Time required ...2626 Final line reached
MAD · NOV 23-24 · 2018 CompletableFutures - Our use case: Version 2 Request: Session, ... Request: UserInfo, ... Request: Friends, ... Request: Photos, ... Request: News, ... Page for ... Time required: 1632 Final line reached
MAD · NOV 23-24 · 2018 CompletableFutures - Our use case: Version 3 Final line reached Request: Session ... Request: UserInfo ... Request: Friends ... Request: Photos ... Request: News, ... Page for ... Time required: 1640
MAD · NOV 23-24 · 2018 CompletableFutures - Our use case: Version 4 Final line reached Time required: 17 Request: Session … Request: UserInfo … Request: Photos … Request: Friends … Request: News … Page for …
MAD · NOV 23-24 · 2018 CompletableFutures - Exceptions & Timeouts Final line reached Time required: 26 Request: Session ... Empty page
MAD · NOV 23-24 · 2018 CompletableFutures - Conclusions Good things: ■ A lot of facilidades to manage async operations. ■ Code looks ‘synchronous’. ■ Easy to compose complex async operations. But: ■ Still some sense of callbacks. ■ Still blocks the caller thread in some point. ■ Remember to manage your Thread Pools.
MAD · NOV 23-24 · 2018 Reactive Streams
MAD · NOV 23-24 · 2018 Observable “Everything is a stream, and it's observable.” kotlinlang.org/docs/tutorials/coroutines/async-programming.html
MAD · NOV 23-24 · 2018 Observables ■ Publishers notifies subscriptions about new data. RxJava ■ Implements the Observable pattern and extends it. ■ Creation of flows looks like a Builder. ■ Operators. ■ Backpresure. ■ Schedulers (Default, IO, Compute). ■ RxJava & RxKotlin (and other ~16 languages). Read lines Split by spaces Remove some words Print
MAD · NOV 23-24 · 2018 Observables 1º Publisher ■ Observable<...> / Flowable<...> ∘ Others: Single<...>, Maybe<...>, Completable<...>... 2º Operators ■ Optionals, between 72 and ~500. ■ Transformations: flatMap(), map() ... ■ Mathematical: count(), max(), min()... ■ Filtering: first(), find(), filter()... 3º Subscription ■ Run the flow. ■ Will run the steps in different schedulers: subscribeOn(...) observeOn(...)... Default: Local Thread. ■ Obtain the final value: subscription(...), blockingFirst(...)... Read lines Split by spaces Remove some words Print
MAD · NOV 23-24 · 2018 Observable - Create
MAD · NOV 23-24 · 2018 Observable - Just a try Request: Session ... println ... Request: Session ... println ... Request: Session ... println ... Time required: 1743
MAD · NOV 23-24 · 2018 Observable - Scheduler IO Time required: 190 Request: Session ... Request: Session ... Request: Session ... println … println … println …
MAD · NOV 23-24 · 2018 Observable - Blocking Request: Session … println ... Time required: 771
MAD · NOV 23-24 · 2018 Observable - Our use case 233 ms 1654 ms
MAD · NOV 23-24 · 2018 Reactive Streams A lot of useful diagrams to understand operators: ■ Marbles diagrams - rxmarbles.com
MAD · NOV 23-24 · 2018 Reactive Streams / RxJava - Conclusions Good things: ■ A lot of facilidades to manage async flows. ■ Managed schedulers. ■ A lot of operators. But: ■ Too complex for individual tasks. ■ Has a very big API. ■ Easy to make mistakes (sync, operators…).
MAD · NOV 23-24 · 2018 Coroutines
MAD · NOV 23-24 · 2018 Coroutines “The idea that a function can suspend its execution at some point and resume later on.” kotlinlang.org/docs/tutorials/coroutines/async-programming.html
MAD · NOV 23-24 · 2018 Suspending functions - Coroutines Suspending Functions (our code): ■ Async code written Synchronous, that can run asynchronously. Sync by default. ■ Async/await in Javacript, C#, Python. Coroutines (runners): ■ ‘Light-weight’ Threads BUT Coroutines != Threads. ∘ Coroutines run in threads (1.000.000s). ∘ A SUSPENDED coroutine: · Does not consume a thread. · Is not bound to a thread.
MAD · NOV 23-24 · 2018 Default context (Thread Pool) in Kotlin Scope Coroutine Coroutine Coroutine IO context Scope Coroutine Main Thread Scope Coroutine
MAD · NOV 23-24 · 2018 Coroutines - Creation in IO IO context Scope Coroutine Scope Coroutine
MAD · NOV 23-24 · 2018 Coroutines in Kotlin Request: Session ... Request: UserInfo ... Request: Friends … Request: Photos … Request: News ... Page for … Time required: 2676
MAD · NOV 23-24 · 2018 Coroutines in Kotlin Request: Session ... Request: UserInfo ... Request: Friends … Request: Photos … Request: News ... Page for … Time required: 1653
MAD · NOV 23-24 · 2018 Coroutines in Kotlin Kotlin release: ■ API stable in Kotlin 1.3 ■ Implementation version (kotlinx-coroutines-core): 1.0.1 More functionality: ■ Parent-child & Jobs -> cancellables. ■ Try/Catch & Stacktraces. ■ Channels (fan-in, fan-out, pipelines…). ■ Actors. ■ Multi-platform: JS, Native, Reactive, Android.
MAD · NOV 23-24 · 2018 Coroutines - Conclusions Good things: ■ Strong primitives to build async software. ■ Sometimes it feels just synchronous (Try catch). ■ For our use case ~efficiency than CompletableFuture. But: ■ Scopes and contexts are a little bit messy. ■ Partial ‘non-blocking’. You still need to take care of Threads. ■ Could be too low level.
MAD · NOV 23-24 · 2018 General - Conclusions ■ Concurrency/parallelism is hard. ■ UnitTest and measure (!) your implementations. ■ Coroutines improved readability and efficiency, but: ∘ Final version just released. ∘ Community support just started. ∘ Take care of threads. ∘ Use the conversions with other abstractions. ■ Look for the better abstraction for your use case. ∘ CompletableFuture: Simple and efficient over single jobs. ∘ Coroutines: Abstractions over single jobs and other primitives. ∘ Reactive Streams: Abstractions over an stream of jobs.
MAD · NOV 23-24 · 2018 Resources ■ Slides & Code: @Koletzilla ■ Kotlin proposal (KEEP) ∘ https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md ■ Kotlin/kotlinx.coroutines ∘ https://github.com/Kotlin/kotlinx.coroutines ■ Introduction to Coroutines @ KotlinConf 2017 - by Roman Elizarov ∘ https://www.youtube.com/watch?v=_hfBv0a09Jc ∘ https://www.slideshare.net/elizarov/introduction-to-coroutines-kotlinconf-2017 ■ Kotlin Coroutines in Practice @ KotlinConf 2018 - by Roman Elizarov ∘ https://www.youtube.com/watch?v=a3agLJQ6vt8 ∘ https://www.slideshare.net/elizarov/kotlin-coroutines-in-practice-kotlinconf-2018
MAD · NOV 23-24 · 2018 Thank you!! Questions? @Koletzilla
CommitConf 2018 - Going Async With Kotlin

CommitConf 2018 - Going Async With Kotlin

  • 1.
    MAD · NOV23-24 · 2018 Going Async with Kotlin José María Muñoz Rey Software Engineer at Tuenti MAD · NOV 23-24 · 2018
  • 2.
    MAD · NOV23-24 · 2018 Where should we start? Simplified problem: multiple IO request Index ■ Understand why asynchrony abstractions matters. ■ Asynchrony abstractions. ∘ Callbacks. ∘ Futures (CompletableFutures). ∘ Observables (Reactive Streams/RxJava). ∘ Coroutines.
  • 3.
    MAD · NOV23-24 · 2018 Writing synchronous code Why asynchrony abstraction matters
  • 4.
    MAD · NOV23-24 · 2018 Problem description Simple IO problem: multiple requests to a service. Client: ■ Standard Kotlin, sequential code. ■ Without async abstractions. Server: ■ Ktor. ■ Just responds with a text and waits a custom delay.
  • 5.
    MAD · NOV23-24 · 2018 Our example
  • 6.
    MAD · NOV23-24 · 2018 Simple Synchronous code Request: Session, 500 miliseconds ... Request: Photos, 500 miliseconds Request: News, 500 miliseconds Time required to process this block: 2626 Requests Response
  • 7.
    MAD · NOV23-24 · 2018 Simple Synchronous code What happened? Requests still made sequentially: ■ Main thread blocked: in each request. ■ No parallelism: this code can be benefit from it.
  • 8.
    MAD · NOV23-24 · 2018 What do we need? ■ Last 3 request should run in parallel ■ Abstractions to: ∘ Create them. ∘ Get status, cancel… ∘ Get computed value. We need to call these methods asynchronously.
  • 9.
    MAD · NOV23-24 · 2018 Managing Asynchrony
  • 10.
    MAD · NOV23-24 · 2018 Let’s create Threads for IO !! They help us by letting other code run in parallel, but: ■ They have an high costs (Context switching). ■ They are highly limited. ■ They are hard to manage. ∘ Create/reuse/idle/close. ∘ Cancel work. ∘ Thread pool (computation, IO). ∘ Share info. We need some abstractions.
  • 11.
    MAD · NOV23-24 · 2018 Promises CompletableFuture Futures Deferred Task Asynctask Observable Callbacks Async abstractions!!!! Coroutines/Suspending function
  • 12.
    MAD · NOV23-24 · 2018 What we are going to see today: Main abstractions used in the JVM ■ Callbacks. ■ Futures: CompletableFutures. ■ Observables: Reactive streams (Publisher/subscriber/Observable...). ■ Coroutines.
  • 13.
    MAD · NOV23-24 · 2018 Callbacks
  • 14.
    MAD · NOV23-24 · 2018 Callbacks
  • 15.
    MAD · NOV23-24 · 2018 Callbacks
  • 16.
    MAD · NOV23-24 · 2018 Callbacks ■ Just if necessary. ■ Not enough for Kotlin to handle asynchrony ■ Problems to chain calls (Callbacks hell). ■ Problems to share computed values. ■ Problems to handle errors. Javascript experience: people is moving away. DON’T USE THEM
  • 17.
    MAD · NOV23-24 · 2018 CompetableFutures And well, the others ‘Futures’
  • 18.
    MAD · NOV23-24 · 2018 Promises vs Futures vs CompletableFuture vs Deferred vs Task vs ... “They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.” en.wikipedia.org/wiki/Futures_and_promises
  • 19.
    MAD · NOV23-24 · 2018 Promises vs Futures vs CompletableFuture vs Deferred vs Task vs ... They are (practically) the same thing, but named differently in different languages: ■ Futures: practically everywhere. ■ CompletableFutures: JVM (Java, Kotlin...). ■ Promises: Javascript. ■ Task: C# / Android APIs. ■ Deferred: Koltin. ■ ...
  • 20.
    MAD · NOV23-24 · 2018 CompletableFutures ■ Introduced in Java 8. ■ Improves the actual interface of existing Futures. ■ Compositional programming with chained calls. (Sequential and parallel). ■ Default: Threads from the CommonPool. API: ■ Create: .supplyAsync() ■ Chain: .thenCompose(), .thenApply() or .thenAccept(). ■ Compose: .anyOf(...), .allOf(...). ■ Get value: .get() or .join(). ■ More functionality: .exceptionally(...), .orTimeout().
  • 21.
    MAD · NOV23-24 · 2018 CompletableFutures - Our use case ■ getUserInfo(): CompletableFuture<...>. ■ getPhotos(): CompletableFuture<...>. ■ getFriends(): CompletableFuture<...>. ■ getNews(): CompletableFuture<...>.
  • 22.
    MAD · NOV23-24 · 2018 CompletableFutures - Our use case: Version 1 Request: Session, ... Request: UserInfo, ... Request: Friends, ... Request: Photos, ... Request: News,... Page for ... Time required ...2626 Final line reached
  • 23.
    MAD · NOV23-24 · 2018 CompletableFutures - Our use case: Version 2 Request: Session, ... Request: UserInfo, ... Request: Friends, ... Request: Photos, ... Request: News, ... Page for ... Time required: 1632 Final line reached
  • 24.
    MAD · NOV23-24 · 2018 CompletableFutures - Our use case: Version 3 Final line reached Request: Session ... Request: UserInfo ... Request: Friends ... Request: Photos ... Request: News, ... Page for ... Time required: 1640
  • 25.
    MAD · NOV23-24 · 2018 CompletableFutures - Our use case: Version 4 Final line reached Time required: 17 Request: Session … Request: UserInfo … Request: Photos … Request: Friends … Request: News … Page for …
  • 26.
    MAD · NOV23-24 · 2018 CompletableFutures - Exceptions & Timeouts Final line reached Time required: 26 Request: Session ... Empty page
  • 27.
    MAD · NOV23-24 · 2018 CompletableFutures - Conclusions Good things: ■ A lot of facilidades to manage async operations. ■ Code looks ‘synchronous’. ■ Easy to compose complex async operations. But: ■ Still some sense of callbacks. ■ Still blocks the caller thread in some point. ■ Remember to manage your Thread Pools.
  • 28.
    MAD · NOV23-24 · 2018 Reactive Streams
  • 29.
    MAD · NOV23-24 · 2018 Observable “Everything is a stream, and it's observable.” kotlinlang.org/docs/tutorials/coroutines/async-programming.html
  • 30.
    MAD · NOV23-24 · 2018 Observables ■ Publishers notifies subscriptions about new data. RxJava ■ Implements the Observable pattern and extends it. ■ Creation of flows looks like a Builder. ■ Operators. ■ Backpresure. ■ Schedulers (Default, IO, Compute). ■ RxJava & RxKotlin (and other ~16 languages). Read lines Split by spaces Remove some words Print
  • 31.
    MAD · NOV23-24 · 2018 Observables 1º Publisher ■ Observable<...> / Flowable<...> ∘ Others: Single<...>, Maybe<...>, Completable<...>... 2º Operators ■ Optionals, between 72 and ~500. ■ Transformations: flatMap(), map() ... ■ Mathematical: count(), max(), min()... ■ Filtering: first(), find(), filter()... 3º Subscription ■ Run the flow. ■ Will run the steps in different schedulers: subscribeOn(...) observeOn(...)... Default: Local Thread. ■ Obtain the final value: subscription(...), blockingFirst(...)... Read lines Split by spaces Remove some words Print
  • 32.
    MAD · NOV23-24 · 2018 Observable - Create
  • 33.
    MAD · NOV23-24 · 2018 Observable - Just a try Request: Session ... println ... Request: Session ... println ... Request: Session ... println ... Time required: 1743
  • 34.
    MAD · NOV23-24 · 2018 Observable - Scheduler IO Time required: 190 Request: Session ... Request: Session ... Request: Session ... println … println … println …
  • 35.
    MAD · NOV23-24 · 2018 Observable - Blocking Request: Session … println ... Time required: 771
  • 36.
    MAD · NOV23-24 · 2018 Observable - Our use case 233 ms 1654 ms
  • 37.
    MAD · NOV23-24 · 2018 Reactive Streams A lot of useful diagrams to understand operators: ■ Marbles diagrams - rxmarbles.com
  • 38.
    MAD · NOV23-24 · 2018 Reactive Streams / RxJava - Conclusions Good things: ■ A lot of facilidades to manage async flows. ■ Managed schedulers. ■ A lot of operators. But: ■ Too complex for individual tasks. ■ Has a very big API. ■ Easy to make mistakes (sync, operators…).
  • 39.
    MAD · NOV23-24 · 2018 Coroutines
  • 40.
    MAD · NOV23-24 · 2018 Coroutines “The idea that a function can suspend its execution at some point and resume later on.” kotlinlang.org/docs/tutorials/coroutines/async-programming.html
  • 41.
    MAD · NOV23-24 · 2018 Suspending functions - Coroutines Suspending Functions (our code): ■ Async code written Synchronous, that can run asynchronously. Sync by default. ■ Async/await in Javacript, C#, Python. Coroutines (runners): ■ ‘Light-weight’ Threads BUT Coroutines != Threads. ∘ Coroutines run in threads (1.000.000s). ∘ A SUSPENDED coroutine: · Does not consume a thread. · Is not bound to a thread.
  • 42.
    MAD · NOV23-24 · 2018 Default context (Thread Pool) in Kotlin Scope Coroutine Coroutine Coroutine IO context Scope Coroutine Main Thread Scope Coroutine
  • 43.
    MAD · NOV23-24 · 2018 Coroutines - Creation in IO IO context Scope Coroutine Scope Coroutine
  • 44.
    MAD · NOV23-24 · 2018 Coroutines in Kotlin Request: Session ... Request: UserInfo ... Request: Friends … Request: Photos … Request: News ... Page for … Time required: 2676
  • 45.
    MAD · NOV23-24 · 2018 Coroutines in Kotlin Request: Session ... Request: UserInfo ... Request: Friends … Request: Photos … Request: News ... Page for … Time required: 1653
  • 46.
    MAD · NOV23-24 · 2018 Coroutines in Kotlin Kotlin release: ■ API stable in Kotlin 1.3 ■ Implementation version (kotlinx-coroutines-core): 1.0.1 More functionality: ■ Parent-child & Jobs -> cancellables. ■ Try/Catch & Stacktraces. ■ Channels (fan-in, fan-out, pipelines…). ■ Actors. ■ Multi-platform: JS, Native, Reactive, Android.
  • 47.
    MAD · NOV23-24 · 2018 Coroutines - Conclusions Good things: ■ Strong primitives to build async software. ■ Sometimes it feels just synchronous (Try catch). ■ For our use case ~efficiency than CompletableFuture. But: ■ Scopes and contexts are a little bit messy. ■ Partial ‘non-blocking’. You still need to take care of Threads. ■ Could be too low level.
  • 48.
    MAD · NOV23-24 · 2018 General - Conclusions ■ Concurrency/parallelism is hard. ■ UnitTest and measure (!) your implementations. ■ Coroutines improved readability and efficiency, but: ∘ Final version just released. ∘ Community support just started. ∘ Take care of threads. ∘ Use the conversions with other abstractions. ■ Look for the better abstraction for your use case. ∘ CompletableFuture: Simple and efficient over single jobs. ∘ Coroutines: Abstractions over single jobs and other primitives. ∘ Reactive Streams: Abstractions over an stream of jobs.
  • 49.
    MAD · NOV23-24 · 2018 Resources ■ Slides & Code: @Koletzilla ■ Kotlin proposal (KEEP) ∘ https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md ■ Kotlin/kotlinx.coroutines ∘ https://github.com/Kotlin/kotlinx.coroutines ■ Introduction to Coroutines @ KotlinConf 2017 - by Roman Elizarov ∘ https://www.youtube.com/watch?v=_hfBv0a09Jc ∘ https://www.slideshare.net/elizarov/introduction-to-coroutines-kotlinconf-2017 ■ Kotlin Coroutines in Practice @ KotlinConf 2018 - by Roman Elizarov ∘ https://www.youtube.com/watch?v=a3agLJQ6vt8 ∘ https://www.slideshare.net/elizarov/kotlin-coroutines-in-practice-kotlinconf-2018
  • 50.
    MAD · NOV23-24 · 2018 Thank you!! Questions? @Koletzilla