Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
@hanhan1978 PHPでEventLoopを書いて非同期処理を 完全に理解する PHPerKaigi 2022
Slide 2
Slide 2 text
@hanhan1978 同期的なプログラミング言語の目線から非 同期処理を理解する PHPerKaigi 2022 とりあえず改題
Slide 3
Slide 3 text
イベントループは関係なかった 3 すまんな!
Slide 4
Slide 4 text
@hanhan1978 ● 富所 亮 ● 所属 株式会社カオナビ Expert ● 職業 Webアプリケーションエンジニア ● ブログ https://blog.hanhans.net ● Yokohama North AM https://anchor.fm/yokohama-north-am 4
Slide 5
Slide 5 text
前回までのあらすじ 5
Slide 6
Slide 6 text
2021-11-25 PHP 8.1 Release Fibers が導入される 6
Slide 7
Slide 7 text
7 「非同期処理が簡単にかけるようになるらしいぜ?」
Slide 8
Slide 8 text
ここにビジネスチャンスを見出したが.... 非同期沼に突入 分かりにくいプレゼンを行ってしまう 8
Slide 9
Slide 9 text
9 https://speakerdeck.com/hanhan1978/php-async-programming
Slide 10
Slide 10 text
3行でまとめると... - 非同期処理はわからん - Fibers もよくわからん - とりあえず、PHPでPHPを動かせ 10 すまんかった
Slide 11
Slide 11 text
11 リベンジ https://speakerdeck.com/hanhan1978/fiber-and-async-request
Slide 12
Slide 12 text
3行でまとめると... - なぜ Fibers - イベントループってなに? - なぜ 非同期の仕組みがいまさらPHPに入ってくる? 12 自信作だったが、スライドが荒かった
Slide 13
Slide 13 text
本日は合体整理版 13
Slide 14
Slide 14 text
● 非同期処理とは ● 2つの視点 ● イベントループ ● まとめ 目次 14
Slide 15
Slide 15 text
● 非同期処理とは ● 2つの視点 ● イベントループ ● まとめ 目次 15
Slide 16
Slide 16 text
同期的なプログラミング 記述したとおりの順番で動作するようなプログラミングモデル 非同期プログラミング 独立して発生するイベントに対する処理を記述するための並行プログラミン グ手法の総称 16 高野祐輝. (2021). 並行プログラミング入門 5章 (初版.). オライリー・ジャパン.
Slide 17
Slide 17 text
17 PHPアプリケーションは 同期的なBlocking IOが基本
Slide 18
Slide 18 text
18 よくある MVC フレームワークのコード例
Slide 19
Slide 19 text
19 プログラムは書いた順番に順次実行され ていく
Slide 20
Slide 20 text
20 入出力処理が行われると プログラムは結果を待つ
Slide 21
Slide 21 text
21 DB検索の処理シーケンス クエリ結果が返ってくるまで メインの処理は待つ ブロッキングIOと言う
Slide 22
Slide 22 text
22 非同期プログラミングの例
Slide 23
Slide 23 text
23 単純なAPIコールの例
Slide 24
Slide 24 text
24 ここで処理が待たない
Slide 25
Slide 25 text
25 IO処理の結果を待たない メインスレッドは、待ち時間の間 に他の処理を行える ノンブロッキングIO という
Slide 26
Slide 26 text
26 実行順序は直感と反する ① ③ ② 慣れれば分かるんだが ......
Slide 27
Slide 27 text
入出力処理の結果が、いつ返ってくるか分からないの で、結果が戻ってきたときに実行する処理をコール バックで渡しておく 27
Slide 28
Slide 28 text
28 非同期プログラミングの利点
Slide 29
Slide 29 text
29 ブロッキング ノンブロッキング CPUを効率的に利用できる
Slide 30
Slide 30 text
マルチスレッドは難しすぎたが 非同期プログラミングであれば、普通の人間でもギリギリ許 容できそう。 Promise, Async/Await などを使えば、非同期処理も扱いや すくなる。 30
Slide 31
Slide 31 text
世の中の潮流としては、マルチコア -> コアの利用効率を上げることで、プログラムの処理効率 を上げる スループットの向上 31
Slide 32
Slide 32 text
● 非同期処理とは ● 2つの視点 ● イベントループ ● まとめ 目次 32
Slide 33
Slide 33 text
33 非同期処理を考える時の二つの視点
Slide 34
Slide 34 text
34 1リクエスト 複数リクエスト(プロセス)
Slide 35
Slide 35 text
35 1リクエスト単位の視点
Slide 36
Slide 36 text
36
Slide 37
Slide 37 text
37 ToDoリストを検索するバックエンドの処理(例) 非同期処理チャンス
Slide 38
Slide 38 text
38 ToDoリストを検索するバックエンドの処理(例) 2つめのクエリが1つ目のクエリに依存して いる 無邪気に非同期処理を書くと、整合性のある データを取得できない
Slide 39
Slide 39 text
39 コールバックPHPの仮想コード
Slide 40
Slide 40 text
40 コールバックPHPの仮想コード 結果出力時には、検索が終わってなければいけ ない。 非同期処理をしてしまうと、データ取得前に結果 出力するはめになる
Slide 41
Slide 41 text
しょうがないので、全部コールバックにする.... こうして、コールバック地獄が生まれる 41
Slide 42
Slide 42 text
42 コールバックPHPの仮想コード
Slide 43
Slide 43 text
43 コールバックPHPの仮想コード 同期的プログラミングのコードのほうがはるかに 見通しが良い。 処理時間も変わらない......
Slide 44
Slide 44 text
コールバックは、直列に実行され、データが戻ってくるまで待 つことになるので、非同期処理の書き方をしたところで、ス ループットが上がっていない。 ※相互に依存した処理の場合、1リクエスト単位で見ると同 期でも非同期でも処理時間は変わらない 44
Slide 45
Slide 45 text
Fibers が いわゆる PHP アプリケーション制作において役 に立つ機能ではないと言われるのは、この辺。 45
Slide 46
Slide 46 text
とはいえ 1リクエスト単位の視点でも非同期処理が役に立ちそうな ケースはある 46
Slide 47
Slide 47 text
47 例えば、APIリクエストを3回行 う必要がある場合 かつ、それぞれのAPIコールは 相互に依存していない。
Slide 48
Slide 48 text
48 こんな風に処理をまとめ られたら、効率的
Slide 49
Slide 49 text
そういった用途には古来より curl_multi というものがある Fibers は別に使わなくても問題ない... 49
Slide 50
Slide 50 text
しかし、1リクエスト内でIO処理を束ねるようなケースは、そん なに多くない。 レアケースに対して、本気に殴りに行くような改善よりも、もっと 一般的なケースの改善をするほうが意味がある。 50
Slide 51
Slide 51 text
1リクエスト単位で考えた場合 PHPで非同期プログラミングを行うのは、あまり効果的である とは思えない。 51
Slide 52
Slide 52 text
52 余談
Slide 53
Slide 53 text
JavaScript が基本的にノンブロッキングな処理を行う理由は、 ブラウザを操作しているユーザーを待たせないため 53
Slide 54
Slide 54 text
54 JSのローディングイメージ例 https://webdevtrick.com/lazy-load-images/
Slide 55
Slide 55 text
ノンブロッキングを徹底することで、ブラウザ利用者の体験に 寄与している。このへんはプログラミング言語の根本の思想に 関わっている 55
Slide 56
Slide 56 text
56 複数リクエストの視点
Slide 57
Slide 57 text
話を単純化するために、CPUが1コアでウェブサーバーは1リ クエストずつ処理していくものとする。 57
Slide 58
Slide 58 text
58 1リクエストを以下のように図示する ※斜線部分は IO 以外の処理を行っているものとする
Slide 59
Slide 59 text
59 通常の PHP ウェブアプリケーションでは リクエストはそれぞれ独立に直列で処理される
Slide 60
Slide 60 text
60 いわゆる PHP ウェブサーバーの構成
Slide 61
Slide 61 text
今までの普通のPHPウェブアプリケーションでは、IO処理が もったいないと感じても、その間の資源を他に割り当てられな かった。 61
Slide 62
Slide 62 text
62 いわゆる PHP ウェブサーバーの構成 Nginx も PHP-FPM も 個別の PHP プロセスの処理状況を細かく 監視できない
Slide 63
Slide 63 text
もし、リクエストをまたいで非同期処理が行えたら、IO待ちの時 に、他のリクエストを処理することで効率的にリクエストをさばく ことができる。 63
Slide 64
Slide 64 text
64
Slide 65
Slide 65 text
実際に Fibers が利用が想定されているのは、リクエストをま たいだパターンが多そう リクエストをまたいで、処理の停止・実行を行うためには、全て のリクエスト処理が、PHPのメイン処理から実行されている必 要がある 65
Slide 66
Slide 66 text
66 私が、PHP が PHP を実行する必要があると 言っていたのはコレ。
Slide 67
Slide 67 text
この世界観については、すでに Swoole 、 ReactPHP、 AmPHP などで実現されている このように、PHPの主処理が停止せずにリクエストを実行して いくという処理パターンの文脈で イベントループがでてくる 67
Slide 68
Slide 68 text
68 余談
Slide 69
Slide 69 text
69 Mastering Swoole PHP - Bruce Dou Swoole 作者による解説著作 全体の2/3がPHPの処理モデル やIOモデルの説明となっていて、 非同期を取り巻く状況を雑観でき る。
Slide 70
Slide 70 text
● 非同期処理とは ● 2つの視点 ● イベントループ ● まとめ 目次 70
Slide 71
Slide 71 text
71 イベントループとは?
Slide 72
Slide 72 text
72 https://en.wikipedia.org/wiki/Event_loop イベントループの構成要素 Wiki から想像して作図
Slide 73
Slide 73 text
73 イベントループの構成要素 リクエストはQueueで直列化される (DeMultiplex)
Slide 74
Slide 74 text
74 イベントループの構成要素 Event Loop 側はシングルスレッドで処理できる (Reactor Pattern)
Slide 75
Slide 75 text
75 実装はループ処理 例えば、配列にイベントが追加され ループで逐次処理されるのも、立派なイベントループ
Slide 76
Slide 76 text
イベントループで実行されるEvent が Fiber オブジェクトになっ ていれば Suspend Restart をメインスレッドから抽象的に扱うことができる。 76
Slide 77
Slide 77 text
77 一番のポイント
Slide 78
Slide 78 text
フレームワークの利用者側の視点で考えると 同期的プログラミングを継続できる 同期的プログラミングを行ったまま、非同期プログラミングの恩 恵を受けることができる そんな非同期フレームワークを、Fibers を使うことで抽象的に 理解しやすく作れる 78
Slide 79
Slide 79 text
今後、Promise や Async/Await が PHP にもたらされる可能 性はあるが、そもそも同期的であることに意味がある場合が多 そうなので、利用シーンは限られそう 79
Slide 80
Slide 80 text
● 非同期処理とは ● 2つの視点 ● イベントループ ● まとめ 目次 80
Slide 81
Slide 81 text
非同期処理、Fibers、イベントループ この3つのキーワードがセットになって語られることが多いが、 その理由はリクエストをまたいだ非同期処理を行うことが、 PHPウェブアプリケーションにとって、もっとも現実的で徳が多 そうだから 81
Slide 82
Slide 82 text
82 Fibers を使った Event Loop の例 実装方法はたくさんある
Slide 83
Slide 83 text
実際は、ev拡張などを利用すれば、現状でもイベントループを 簡単に書くことは出来る。 Fibers はイベントループから実行された処理スレッドの停止・ 再開判断を抽象的に便利に行える機能と考えると分かりやす い 83
Slide 84
Slide 84 text
84 とはいえ、書いてみないと実感しづらい
Slide 85
Slide 85 text
85 雑なスライドだが実装サンプルを載せた https://speakerdeck.com/hanhan1978/fiber-and-async-request
Slide 86
Slide 86 text
APIリクエストの非同期実行を 生PHP -> Generator -> Fiber と抽象化していくサンプル Fibers は、抽象化の道具なんだね!が実感できる 86
Slide 87
Slide 87 text
@hanhan1978 相談・指摘・その他 下記のTwitterアカウントにどうぞ 87