Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Shallow Dip into Kotlin Coroutine
Search
bigbackboom
April 17, 2024
Technology
270
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Shallow Dip into Kotlin Coroutine
bigbackboom
April 17, 2024
More Decks by bigbackboom
See All by bigbackboom
Learn as a Pair
bigbackboom
0
75
Not 2 L8 JKでもわかるMaterial 3
bigbackboom
0
62
JKでもわかるSFace Recognition
bigbackboom
0
82
Androidタブレットアプリ作成_棚から牡丹餅を得るにはまず棚から
bigbackboom
0
70
Proto Datastoreを使う前の心構え
bigbackboom
0
330
Extended A Study in Bitmap: Is NDK the fast Processing method by CPU?
bigbackboom
0
35
Have A Dog in CircleCI
bigbackboom
0
94
Androidエンジニアのお仕事でのショボーン
bigbackboom
0
97
解明!楽しいプレゼンする話すスキル
bigbackboom
0
130
Other Decks in Technology
See All in Technology
AIコード生成×サプライチェーン攻撃 — PHPが直面する“二重の信頼問題
shinyasaita
0
490
AI_Dev_Day_製造業領域でのAI活用から見た活用の罠と成功に導く実践知.pdf
kintotechdev
0
210
発表と総括 / Presentations and Summary
ks91
PRO
0
210
OpenTelemetryにおけるGoのゼロコード・コンパイル時計装について #fukuokago
quiver
0
320
reFACToring
moznion
0
480
WEBフロントエンド研修【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
270
ここは地獄!つらい朝会を体験することで、チームとしてのより良い振る舞いに気づくワークショップ / The stand-up meeting from hell in the game industry
scrummasudar
0
330
Git 研修【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
360
伝票作成AIエージェントを支える、LLMOpsとインフラの選択肢 / AICon2026_takeda
rakus_dev
0
290
文字起こし基盤の信頼性
abnoumaru
0
140
データベース研修【MIXI 26新卒技術研修】
mixi_engineers
PRO
1
290
『モデル + ハーネス』で読み解く AIエージェント入門
oracle4engineer
PRO
2
200
Featured
See All Featured
Information Architects: The Missing Link in Design Systems
soysaucechin
0
1k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.7k
Discover your Explorer Soul
emna__ayadi
2
1.2k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Skip the Path - Find Your Career Trail
mkilby
1
170
A Tale of Four Properties
chriscoyier
163
24k
The Curious Case for Waylosing
cassininazir
1
440
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
The untapped power of vector embeddings
frankvandijk
2
1.8k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
Designing for Performance
lara
611
70k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
67
56k
Transcript
Shallow Dip into Kotlin Coroutine キクチコウダイ
自己紹介 菊池 広大(キクチコウダイ) 2023年6月 株式会社マネーフォワードに入社 埼玉出身、香港育ち、 Iターンで東京から福岡に引越し Github: https://github.com/BigBackBoom
発表の概要
Coroutineとは Coroutineが スレッドの並列処理とどう違うのか、 Kotlinをベースに説明します。
Coroutineとは
Coroutineとは サブルーチンを並列処理させるために 一般化した手法
Coroutineとは • もともとは1963年にCobolのコンパイラ周りで提唱された • 複数のサブルーチンが自分の処理を中断し、プロセス間で リソースの協力をしながら並列処理を実行する。
Coroutineとは
Coroutineとは 普通のサブルーチン(メソッド)とは違うの? a. サブルーチンは呼び出されるたびに、一から処理が開 始される b. Coroutineはサブルーチンで処理を中断して、別の処 理の開始・再開ができる
Coroutineとは スレッド使えば十分じゃない? • スレッドはOS管理されている。そのため、OS毎に実装 を変更・バイナリの再コンパイルする必要がある。 • また、スレッドを複数立ち上げると、ハードウェアリソー スも大量に消費する。
Kotlin Coroutineの使い方
Launch Lauchを呼び出すことでCoroutineの非同期 処理を開始できる fun main(args: Array<String>) { GlobalScope.launch { println("world")
} println("Hello") // 結果 // Hello } Launch
Launch • Launch処理が始まる前にmainが終 わってしまうので変更 • runBlockingは通常コードとCoroutine をブリッジするために使われる • Globalscopeを直接指定するのは、 Warningが出るので注意
fun main(args: Array<String>) { runBlocking { launch { println("Hello") } } println("World") // Hello // World } Launch
Launch • Coroutine内でサブルーチンを呼び出 す • サブルーチンの定義にsuspendをつけ る • サブルーチンの呼び出しで処理の中断 が行われる
suspend fun printWorld() { delay(1000) // 中断 println("world") } fun main(args: Array<String>) { runBlocking { launch { printWorld() // 中断 } println("Hello") } // Hello // 〜1秒休憩〜 // World } } Suspend
Coroutineの実現方法
Coroutineの実現方法 Coroutineの処理はコンパイル時に ステートマシンコードが生成され置き換えられる。 単純にメソッドが実行されるわけではない
ステートマシン 右のコードをJVMバイトコードからデコンパイ ルして、中身を確認しました suspend fun printWorld() { delay(1000) // 中断
println("world") } fun main(args: Array<String>) { runBlocking { launch { printWorld() // 中断 } println("Hello") // Hello // World }
ステートマシン デコンパイルした中身を擬似コード化 1. mainのLaunchの中身が実行される fun printWorld(continue: Continuation) { val cont
= ContinuationImpl() { fun invokeSuspend() { printWorld() } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン デコンパイルした中身を擬似コード化 1. mainのLaunchの中身が実行される 2. 非同期なので、Helloがコンソールに表 示 fun printWorld(continue: Continuation)
{ val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く fun printWorld(continue: Continuation) { val cont
= ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く 4. printWorldでDelayedが走り、 printWorldを再開先として、 ContinuationImplを渡す。 fun printWorld(continue:
Continuation) { val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く 4. printWorldでDelayedが走り、 printWorldを再開先として、 ContinuationImplを渡す。 5. returnされて一旦全体の処理が終了す
る。 fun printWorld(continue: Continuation) { val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く 4. printWorldでDelayedが走り、 printWorldを再開先として、 ContinuationImplを渡す。 5. returnされて一旦全体の処理が終了す
る。 6. 1秒経つと、ContinuationImplの invokeSuspendが実行され、再度 printWorldを実行。 fun printWorld(continue: Continuation) { val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 7. 二度目では、ラベルがマイナスに更新さ れているため、Worldがコンソールに表 示 fun printWorld(continue: Continuation) { val
cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
Coroutineの実現方法 中断の原理はステートマシンだったとして 並列処理はなんでできるの?
Coroutineの実現方法 Coroutineの実行周りは三つのクラスに分かれる • Job:launch, async, flowなどのたびに作成される。 • Worker:スレッドそのもの、Jobを実行する。 • Scheduler:Workerを管理する。リソース管理を行う
Coroutineの実現方法
Coroutineの実現方法 • 並列処理自体は、スレッドにて実現 • 一つのスレッドが複数の処理を実行するので、処理ご とにスレッドを立ち上げるよりオーバーヘッドが少ない • そのため、大量のスレッドを立ち上げるより軽量に動け る
Coroutineの実現方法 • そのほかにも、JobがJobを作成していた場合の親子 関係や、実行できるスレッドのScopeやContextなどの 考えがある
Kotlin/Nativeの謎
Kotlin/Nativeの謎 Native周りのコードにlauchなどが見当たらない。
Kotlin/Nativeの謎 Kotlin → LLVM中間コードの コンパイラが見つからないので、 まさか直に置き換えている?🤔
Kotlin/Nativeの謎 それ以外の、Worker/Jobの概念は一緒。 Objective-C++で書かれているので、 iOS/Linuxなど複数プラットフォームをこれで対応して いる?
まとめ
Coroutineとは • Coroutineは古くからある手法で、プログラミング言語の実 装として実現されている • そのため、少ないリソースで非同期処理を実現している • また、プログラミング言語さえ動けばOS環境は不問 • Kotlinでは、JVMのスレッド処理とステートマシンによって
非同期な処理を実現している。
以上、ありがとうございました!
参考資料 • Asynchronous Programming with coroutines