こんにちは。よっしーです(^^)
今日は、PHPのFibers(ファイバー)についてご紹介します。
背景
PHP8.2を利用したAPIを開発しているときにFibers(ファイバー)を利用したので、そのときの調査内容を備忘としてのこしました。
こちらのサイトを参考にしています。
概要
Fibers(ファイバ)は、PHP 8.1.0以降で導入された全体のスタックを表す中断可能な関数です。Fibersはコールスタック内のどこからでも一時停止し、ファイバが後で再開されるまでファイバ内の実行を一時停止します。
Fibersは実行スタック全体を一時停止させるため、関数の直接の呼び出し元は関数の呼び出し方を変更する必要はありません。
Fiber::suspend() を使用してコールスタック内のどこからでも実行を中断できます(つまり、Fiber::suspend() の呼び出しは深くネストされた関数内にあるか、存在しない場合でも可能です)。
スタックレスジェネレータとは異なり、各Fiberには独自のコールスタックがあり、深くネストされた関数呼び出しの中で一時停止できます。中断ポイントを宣言する関数(つまり、Fiber::suspend() を呼び出す関数)は、Generatorインスタンスを返す必要はありません。これは yield を使用する関数とは異なります。
Fibersは、PHP VM内からも含む、任意の関数呼び出しで一時停止できます。例えば、array_map() に提供された関数やIteratorオブジェクト上でforeachによって呼び出されるメソッドなどです。
一度中断されたら、Fiber::resume() を使用して任意の値でファイバの実行を再開したり、Fiber::throw() を使用して例外をファイバにスローしたりできます。値はFiber::suspend() から返され(または例外がスローされ)ます。
注意:現在の制約により、オブジェクトのデストラクタ内でファイバを切り替えることはできません。
サンプルコード
<?php
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('fiber');
echo "Value used to resume fiber: ", $value, PHP_EOL;
});
$value = $fiber->start();
echo "Value from fiber suspending: ", $value, PHP_EOL;
$fiber->resume('test');
このコードは、Fiber(ファイバ)を使用した例です。Fiberは、コルーチンとしても知られ、非同期処理やスレッドのように動作し、実行を一時停止し、再開することができる軽量なプロセスです。以下はこのコードの解説です。
$fiber = new Fiber(function (): void { ... })
: 新しいFiberオブジェクトを作成します。Fiberのコンストラクタは、Fiber内で実行されるクロージャ(無名関数)を引数として受け取ります。このクロージャ内で、Fiberの実行が定義されます。$value = Fiber::suspend('fiber')
: Fiber内の実行が進行する中で、Fiber::suspend()
メソッドを呼び出してFiberの実行を一時停止します。このメソッドは引数を受け取り、その引数はFiberの外部コードに返されます。この行では、’fiber’という文字列をFiberの外部に返しています。この行を実行すると、Fiberの実行が停止し、外部のコードが再度制御を取得します。$value = $fiber->start()
: ここで、Fiberを開始します。$fiber->start()
メソッドを呼び出して、Fiberの実行を開始し、その結果としてFiber内の最初のコードブロックが実行されます。この行では、’fiber’という文字列が返され、それが$value
に代入されます。echo "Value from fiber suspending: ", $value, PHP_EOL;
: Fiber内のコードが実行された結果、’fiber’という文字列が$value
に代入されているため、この行でそれを出力します。$fiber->resume('test')
: Fiberの実行を再開します。$fiber->resume()
メソッドを呼び出して、Fiberの実行を再開します。このとき、引数として’test’という文字列を渡しています。Fiberの実行が再開され、Fiber内のコードが再度実行されます。echo "Value used to resume fiber: ", $value, PHP_EOL;
: Fiberの再開時に引数として渡した’test’が、Fiber内のコードで$value
に代入されています。この行で、’test’という文字列を出力します。
要するに、このコードはFiberを使用して、Fiber内の実行を中断し、外部から再開する方法を示しています。Fiberは一時停止して外部にデータを返し、後で再開することができ、外部コードとFiberの間でデータの受け渡しを行える強力な非同期プログラミングツールです。
このサンプルコードの実行結果は下記のようになります。
Value from fiber suspending: fiber
Value used to resume fiber: test
活用場面
Fiberは非同期プログラミングに非常に有用であり、以下はさらに有用な活用例です:
- マルチタスク処理: Fiberを使用して、複数のタスクを同時に実行できます。例えば、Webサーバーのリクエスト処理、データベースクエリ、ネットワーク通信など、複数のタスクを同時に実行することができます。
- 非同期I/O操作: ファイル操作、データベースクエリ、API呼び出しなどのI/O操作を非同期に実行できます。これにより、プログラムがI/O待機中に他のタスクを実行できます。
- エラーハンドリング: Fiberを使用して非同期コード内でエラーハンドリングを行うことができます。非同期関数内で例外をキャッチし、エラーメッセージをログに記録するなどの処理を行えます。
- 非同期タイマー: Fiberを使用して非同期のタイマー処理を実装できます。一定の時間が経過した後に特定の処理を実行するために利用できます。
- リアルタイム通信: WebSocketなどのリアルタイム通信プロトコルをサポートするためにFiberを使用できます。これにより、クライアントとサーバー間の非同期通信を簡単に実装できます。
- 非同期データ処理: 大量のデータを非同期に処理する場合、Fiberは各データセットの処理を分散し、パフォーマンスを向上させるのに役立ちます。
- コンカレンシー制御: 複数のFiberを使用して、同時実行されるタスクの数を制御し、過度な負荷を回避できます。
- プログラムの応答性向上: ユーザーインターフェースの応答性を向上させるために、Fiberを使用して長時間実行されるタスクを非同期に処理できます。
Fiberは非同期処理や非同期イベント駆動型のアプリケーションで非常に強力なツールであり、多くのアプリケーションで有用な方法で活用できます。
おわりに
今日は、PHPのFibers(ファイバー)についてご紹介しました。
何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント