コルティンは複雑で複雑ではありませんが、難しいことでも難しいことでもありません。1つの文を要約すると、並行性は向上しますが、タスクを高速化できません。同期コードは非同期IOを実装し、非同期の非ブロッキングコードブロックを実装します。
コルーチンは特別な機能であり、一時停止して、一時停止したところから実行を再開することができます。スレッド内の複数のコルーチンは、CPU処理プロセスと同様にシリアル化されます。実行する他のコルチンに制御が与えられていない限り、コルチンはスレッド上で実行できます。コルーチンはマルチコアCPUを使用できないため、コルーチンは同時実行の問題のみを解決でき、タスクの処理速度の問題は解決できません。コルーチンは、大きなタスクを小さなフラグメントに分割し、プロセスの機能をカプセル化することです。コルーチンの1つをIOでブロックする必要がある場合、現在のコルーチンをアクティブに一時停止し、制御を他のコルーチンに移して実行します。
プロセスとスレッドはオペレーティングシステムによってスケジュールされていることがわかっています。いつ実行するかは、オペレーティングシステムがプロセスまたはスレッドにCPU時間を与えるタイミングと、ユーザーが制御を放棄するタイミングによって異なります。プロセスとスレッドはカーネルモードに属し、コルティンはユーザーモードスレッドに属します。
コルーチンはユーザーモードの軽量スレッドであり、コルーチンのスケジューリングはユーザーによって完全に制御されます。コルーチンには、独自のレジスタコンテキストとスタックがあります。コルーチンの切り替えがスケジュールされている場合は、レジスタコンテキストとスタックを他の場所に保存します。元に戻す場合は、以前に保存したレジスタコンテキストとスタックを復元します。スタックを直接操作しても、基本的にコア切り替えのオーバーヘッドはなく、ロックせずにグローバル変数にアクセスできます。 、したがって、コンテキストの切り替えは非常に高速です。
私のペンギンは一緒に交換します
日常の機能
-
ユーザーモードスレッドは、IOに遭遇すると、積極的に制御を放棄します
-
複数のcoroutineコードはまだシリアルであり、ロックする必要はありません
-
オーバーヘッドが低く、メモリのみを占有し、プロセスとスレッドの切り替えのオーバーヘッドはありません
-
大量の同時実行、単一のプロセスで50wのコロナを開くことができます
-
いつでも、どこでも、同時進行したい限り、goを呼び出してcooutineを作成します
スレッドは軽量プロセスであることがわかっているため、コロチンは軽量スレッドです。コルチンはスレッド上で実行され、スレッドは複数のコルチンを持つことができます。
プロセスがブロックされた場合、プロセス内で切り替えるためにもう1つのスレッドが開かれ、毎回プロセスが切り替わらないようにします。これにより、CPUによってこのプロセスに割り当てられた利用可能な時間をより積極的に使用できます。コルーチンとスレッドおよびプロセスの関係は、コルーチンがスレッドと直接関係していることを除いて、非常に似ています。
上の図は複数のスレッド間の切り替えの概略図です。スレッドがIO操作(ネットワークまたはファイル)を待機しているだけの場合、スレッドがプロセスを再利用するように、なぜこのスレッドを再利用するのでしょうか。IOを削除して、このグラフがどのように表示されるかを見てみましょう。
操作のIO部分を削除すると、基本的にこの同時要求アプリケーションコードは単一のスレッドで実行でき、ルーチンはスレッドがIOを待機する時間を最大限に活用するため、プログラムはIOを待機しながら他のビジネスコードを実行できます。
スレッドの実行フローのように見えますか?これがコルチンの魅力です。コルチンが降伏すると、スレッド上で実行されるため、中断され、スレッド内の他のコルチンに制御が移ります。スイッチングなので、オーバーヘッドはプロセスやスレッドよりもはるかに低くなります。
プログラムがcoroutineを呼び出した後、現在のcoroutineは、処理のために同じスレッド内の他のcoroutineにアクティブに制御を放棄します。図に示すように、開発者がコードでIOを使用する必要がある場合、coroutineの制御を積極的に放棄します。他のcoroutinesによって使用されます。
IO部分を削除し、コルルーチンの処理を確認します。直接実行されるのはビジネスロジックだけで、IOによってスレッドが待機状態に切り替わるのを回避し、CPUによってこのスレッドに割り当てられた実行時間を最大限に活用します。
注:このコルーチンはタスクを高速化するのではなく、より多くのタスクを実行することしかできません。
コルーチンはスレッド上に構築されているため、CPUマルチコアの利点を利用する方法はありません。コルーチンはIOを多用するコンピューティングシナリオに適しています。
コルティンの役割は何ですか?
ルーチンは、CPU使用率を増やし、スレッドがブロックされたときに多数のスレッドコンテキストの切り替えを回避することです。
echo "1-start\n";
sleep(1);
echo "1-end\n";
echo "2-start\n";
sleep(1);
echo "2-end\n";
echo "3-start\n";
sleep(1);
echo "3-end\n";
echo "4-start\n";
sleep(1);
echo "4-end\n";
上記のコードのCPU使用率はわずか1%です
Swoole\Runtime::enableCoroutine(true);
go(function () {
echo "go1-start\n";
sleep(1);
echo "go1-end\n";
});
go(function () {
echo "go2-start\n";
sleep(1);
echo "go2-end\n";
});
go(function () {
echo "go3-start\n";
sleep(1);
echo "go3-end\n";
});
go(function () {
echo "go4-start\n";
sleep(1);
echo "go4-end\n";
});
コルーチンを使用すると、CPU使用率が4%に正常に増加したため、CPUはIOブロッキングのためにアイドル状態で実行したり、コンテキスト切り替えを実行したりする必要がありません。コルティンは加速できないと言っていませんか?ここでコルーチンを使用した後、前のコードとは異なり、なぜ1秒以上で実行されるのですか?ここで取得される時間は、最後のコルーチンの実行が終了する時間によって異なります。
コルティンの実行順序
Swoole\Runtime::enableCoroutine(true);
go(function(){
sleep(2);
echo "go1\n";
});
go(function(){
sleep(1);
echo "go2\n";
});
echo "main\n";
最初の出力:main-> go2-> go1
コルティン間のコミュニケーション
複数のコルチン間の通信はチャネルによって実現され、複数のコルチンは一般的なタスクの完了を支援します。
Swoole\Runtime::enableCoroutine(true);
$chan = new Swoole\Coroutine\Channel();
go(function () use ($chan){
sleep(1);
$chan->push(['name'=>'sunny']);
});
go(function() use ($chan){
$data = $chan->pop();
print_r($data);
});
echo "结束\n";
実際の戦闘:waitGroup関数を実現する
Swooleが提供するチャネルを使用してwaitGroupを実装します。主な機能は、すべてのコルーチンの完了を待つことです。
<?php
class WaitGroup{
private $count;
private $chan;
public function __construct()
{
$this->chan = new Swoole\Coroutine\Channel();
}
public function add(){
$this->count++;
}
public function done(){
$this->chan->push(true);
}
public function wait(){
for($i=0;$i<$this->count;$i++){
$this->chan->pop();
}
}
}
<?php
include 'waitgroup.php';
Swoole\Runtime::enableCoroutine(true);
echo "start".PHP_EOL;
$t = microtime(true);
go(function() use ($t){
$wg = new WaitGroup();
$wg->add();
go(function() use ($t,&$wg){
echo file_get_contents("https://www.sunnyos.com/swoole.php");
echo "协程1:".(microtime(true)-$t).PHP_EOL;
$wg->done();
});
$wg->add();
go(function() use ($t,&$wg){
echo file_get_contents("https://www.sunnyos.com/swoole.php");
echo "协程2:".(microtime(true)-$t).PHP_EOL;
$wg->done();
});
$wg->add();
go(function() use ($t,&$wg){
echo file_get_contents("https://www.sunnyos.com/swoole.php");
echo "协程3:".(microtime(true)-$t).PHP_EOL;
$wg->done();
});
$wg->wait();
echo '全部结束:'.(microtime(true)-$t).PHP_EOL;
});
echo "end".PHP_EOL;
echo microtime(true)-$t.PHP_EOL;
コード内:https://www.sunnyos.com/swoole.phpswoole.phpコード
<?php
sleep(1);
echo "My name is Sunny\n";
休止ワクチンシミュレーションネットワークリクエストに時間がかかる
ネットワークリクエストに使用される3つのゴルーチンを見てみましょう。各リクエストには1秒かかりますが、ここで3つのリクエストを実行すると、1.2秒しかかかりませんが、CPU使用率は6です。 %、これは、coroutineがcpuを完全に使用していることを示しています。
注意してください、迷子にならないでください
さて、みなさん、上記はこの記事の全内容です。ここで見ることができるのはすべて才能です。さっきも言ったように、PHPには技術的なポイントがたくさんあります。多すぎるので、書くのは本当に不可能で、書いた後はあまり読まないので、必要に応じてここでPDFとドキュメントに整理します。できる
クリックしてシークレットコードを入力してください:PHP +「プラットフォーム」
学習内容の詳細については、[Comparative Standard Factory]の優れたPHPアーキテクトチュートリアルカタログをご覧ください。給与が確実に上がるように読むことができます(継続的な更新)
上記のコンテンツは、すべての人に役立つことを願っています。多くのPHP担当者は、上級者になると常に問題やボトルネックに直面します。ビジネスコードを書きすぎると、方向性がわかりません。どこから改善を始めればよいかわかりません。これに関する情報をまとめました。ただし、これらに限定されません。分散アーキテクチャ、高スケーラビリティ、高パフォーマンス、高同時実行性、サーバーパフォーマンスチューニング、TP6、laravel、YII2、Redis、Swoole、Swoft、Kafka、Mysql最適化、シェルスクリプト、Docker、マイクロサービス、Nginxなど。多くの知識ポイント、高度な高度な乾物は、誰とでも無料で共有でき、必要な人は私のPHPテクノロジー交換グループに参加できます