Upgrade to Pro — share decks privately, control downloads, hide ads and more …

EventLoopの実装から考えるFiberの位置付けについて/Fiber and Async Request

EventLoopの実装から考えるFiberの位置付けについて/Fiber and Async Request

非同期処理によるAPIリクエストのサンプル実装を通して、Fiberが求められてきた背景を説明します。最終的に、それがEventLoopにつながっていきます。

Ryo Tomidokoro

December 22, 2021
Tweet

More Decks by Ryo Tomidokoro

Other Decks in Technology

Transcript

  1. EventLoop
    の実装から考えるFiber
    PHPerKaigi petit - PHP8.1
    リリース祝賀会
    2021-12-21
    @hanhan1978

    View Slide

  2. 自己紹介

    View Slide

  3. こんなのを PHP
    カンファレンス2021
    でやった。
    https://speakerdeck.com/hanhan1978/php-async-programming

    View Slide

  4. ペチコンの内容を3行でまとめると...
    非同期処理はわからん
    Fiber
    よくわからん
    とりあえず、PHP
    でPHP
    を動かせ
    全体的に、分かってるやつしか分からん構成になってしまって反省し
    ている。

    View Slide

  5. 8.1
    リリース祝賀会バージョンでは...
    Fiber
    完全に理解している
    非同期処理を完全に理解している
    わかりやすく説明できる自信がある

    View Slide

  6. Fiber
    を理解する必要はあるか?
    よくある解説
    これがイヤな場合
    -> Fiber
    を理解しないといかん。
    これでOK
    な場合
    -> Fiber
    を実行基盤にもつフレームワークが登場した時に詰む
    ->
    つまり、Fiber
    を理解しないといかん。
    なんとなく非同期処理ができるっぽいやつ。ライブラリ作成者の
    為の機能、一般開発者は気にしなくて良い。


    View Slide

  7. まじめな話
    PHP
    ファンデーションとかもできたし、実装の詳細から逃げ回ってい
    るだけでは駄目。
    みんなで知見をため、公表しあって、日本からもコミッターが出るよ
    うに盛り上げていかないとイカン。
    今日一番まじめな話、終わり。

    View Slide

  8. 今日のゴール
    Fiber
    をみんなが完全に理解すること

    View Slide

  9. 物語の開始地点
    なぜ、Fiber
    が求められているのか?
    なぜ、それがPHP
    に入ってくるのか?
    この物語のWHY
    が解決しないと、以降の議論は全て薄くなる。
    非同期処理が2021
    年現在、非同期処理から遠い位置にいるPHP
    にまで
    言語機能として入ってこようとしているのはなぜ?

    View Slide

  10. 半導体の話
    ムーアの法則が、頭打ちしつつある。電気的に、熱的に、集積度を上
    げにくくなってる。
    ->
    コアの性能アップは難しい
    ->
    だから、マルチコアで並行処理をすることで、スループットを上げ
    よう。
    ここが開始地点。
    パタヘネを読もう。

    View Slide

  11. 並行処理の話
    これまでは、我々が気にする必要がなかった。

    ->
    アプリケーションレイヤーの話ではなく、ハードウェアやOS
    の役

    我々は同期処理パラダイスで生きていけた。

    View Slide

  12. もったいない
    HTTP
    リクエストの応答待ち、DB
    クエリの応答待ち。この間、CPU

    遊んでる。
    厳密には、遊んでるわけではないが、PHP
    のスクリプトは同期的処理
    を行うため、きっちり応答をまつ。
    結果として、CPU
    はその性能を全て引き出されていない状態になる。

    View Slide

  13. もったいない

    View Slide

  14. もったいなくない

    View Slide

  15. もったいないサンプル
    dummy API (
    リクエストにきっちり1
    秒かかる)

    View Slide

  16. 古き良きPHP
    スクリプト (API
    を5
    回叩く)

    View Slide

  17. 同期的HTTP
    リクエストの結果

    View Slide

  18. なぜ、5
    秒かかるのか?
    1 + 1 + 1 + 1 + 1 = 5
    だから。
    PHP
    の組み込み関数はブロッキング。つまり、処理をブロックする
    HTTP Request ->
    応答待ちで1
    秒待つ
    解消するためには、応答を待たずに次のLoop
    に入らないといけない。
    HTTP Request ->
    応答を待たずにLoop ->
    結果が帰ってきたら出力

    View Slide

  19. じゃあどうすればいい?
    file_get_contents
    は処理をブロックする... curl
    でも一緒...
    どうすれば、処理をブロックしないのか?誰がブロックするのか?

    View Slide

  20. ブロックしていたのは誰?
    Socket
    ブロッキング、ノンブロッキングのモードを持つ。つまり、ノンブロ
    ッキングモードのSocket
    を使う file_get_contents
    を作ればいい。

    View Slide

  21. ブロックしない file_get_contents

    View Slide

  22. PHP
    によるブロックしないAPI
    コール

    View Slide

  23. PHP
    によるブロックしないAPI
    コール結果
    ブロックしない、非同期プログミングが完了。

    View Slide

  24. NonBlocking
    化による実行スレッドの流れ
    夢は達成された。Generator
    も Fiber
    もいらなかったんや...

    View Slide

  25. 本当か?
    それを確かめるために、調査隊はさきほどのソースコードを
    Generator
    を使って書き直してみた。

    View Slide

  26. 非同期関数のGenerator

    View Slide

  27. PHP
    によるブロックしないAPI
    コール(Generator
    版)

    View Slide

  28. 通信結果を受け取る関数(Generator
    版)
    ※まじで酷いコードだが、検証用なので許して。

    View Slide

  29. Generator
    版の実行結果
    きっちり1
    秒で5
    リクエスト

    View Slide

  30. Generator
    にしたことで何が起きた?
    結果を受け取る処理が、g->current()
    に置き換わった。
    Generator
    で停止したスレッドの再開 という形で抽象化された。

    View Slide

  31. Generator
    前のコード
    Socket
    から結果を受け取るという具象コードを書いている。
    Generator
    を使うと 停止・再開 という文脈を活かした抽象化が出来
    る。

    View Slide

  32. Generator
    化による実行スレッドの流れ
    夢は達成された。 Fiber
    はいらなかったんや...

    View Slide

  33. 本当か?
    それを確かめるために、調査隊はさきほどのソースコードをFiber
    を使
    って書き直してみた。

    View Slide

  34. PHP
    によるブロックしないAPI
    コール(Fiber
    版)

    View Slide

  35. 通信結果を受け取る関数(Fiber
    版)
    ※Generator
    を返す必要が無くなった

    View Slide

  36. 通信結果を受け取る関数2(Fiber
    版)

    View Slide

  37. Fiber
    版の実行結果
    きっちり1
    秒で5
    リクエスト

    View Slide

  38. Fiber
    にしたことで何が起きた?
    停止スレッドは Fiber
    オブジェクトに抽象化
    Fiber
    オブジェクトの処理内部では、どこからでも自分を停止でき
    る。
    Generator
    と違って、 yield
    して主スレッドに戻す必要がない。

    View Slide

  39. Fiber
    化による実行スレッドの流れ
    ここまでのまとめ

    View Slide

  40. 個人的にポイントになると思うところ
    非同期プログミングにおいては、主スレッドと分岐スレッドという考
    え方を常に持つ必要がある。
    今回の例だと、HTTP
    リクエストを投げているのは分岐スレッド
    分岐スレッドがレスポンスが受け取ったことを検査して、分岐スレッ
    ドの停止・再開を行うのは主スレッド
    非同期プログミングは、分岐スレッドを管理する主スレッドが必要

    View Slide

  41. EventLoop
    とは?
    Swoole, ReactPHP, AmPHP
    などは、それぞれ EventLoop
    を実装し
    ている。
    なぜ、彼らは EventLoop
    を実装する?
    EventLoop
    とは??
    並行処理をするのに、何故 EventLoop
    が必要なのか?

    View Slide

  42. EventLoop
    語弊を恐れずにいうと、ただのLoop
    さっきのサンプルのFiber
    版では、Fiber
    オブジェクトを生成してLoop
    で回して処理をしていた。
    これも広義のEventLoop
    といえる(はず)

    View Slide

  43. EventLoop
    の構成要素
    EventProvider
    処理を Queue
    に追加
    EventLoop
    スケジューラーに従って Event
    を 処理
    EventHandler Event
    を実行する

    View Slide

  44. EventLoop
    の構成要素
    EventLoop
    はシングルスレッドでいい
    リクエストは Queue
    で一直線にされる (DeMultiplex)
    Reactor Pattern
    という

    View Slide

  45. EventLoop
    と Fiber
    の関係
    Fiber
    により、停止・再開が抽象化されると、処理が抽象的に、簡潔
    にかけるようになる。
    これが、Fiber
    の本当の意味。

    View Slide

  46. Fiber
    の中身
    ucontext
    というライブラリが使われている。このシステムコールは、
    ユーザーコンテキストの作成・切替をサポートする。boost_context
    というやつもある。
    Swoole
    は、boost_context
    を使って、Fiber
    っぽいことをやってい
    る。

    View Slide

  47. この先の展開
    Fiber
    で実装された EventLoop
    を持つフレームワークが出てくる。
    (間違いない)
    Fiber
    が拡張され、スケジューラーやPromise, Async/Await
    が PHP

    提供される (8.3? 9.0?)

    View Slide

  48. hanhan1978
    の予定
    Fiber
    で EventLoop
    を実装し、分かりやすいサンプルを書く。

    EventLoop
    の構成要素を、分かりやすいサンプルで書く。
    分かりやすい図で、下の概念を説明する。
    スケジューラー
    non-preemptive
    非同期、並行、このあたりはOS
    周りの実装で出てくる。

    OS
    実装の本とかに参考になる記述が散見される。

    View Slide

  49. PHPerkaigi
    にプロポーザル投げるの
    で、みんな星つけてね!

    View Slide