Table des matières
Qu'est-ce qu'un processus ?
Qu'est-ce qu'un fil de discussion ?
Qu'est-ce qu'une coroutine ?
Le principe de la coroutine Swoole
Processus d'exécution de la coroutine de Swoole
La séquence d'exécution du. coroutine
协程快在哪? 减少IO阻塞导致的性能损失
swoole 协程和 go 协程对比: 单进程 vs 多线程
Maison cadre php Swoole Lorsque la coroutine swoole m'a demandé à trois reprises, j'ai failli pleurer !

Lorsque la coroutine swoole m'a demandé à trois reprises, j'ai failli pleurer !

Dec 03, 2020 pm 05:46 PM

tutoriel swooleIntroduction aux questions d'entretien liées aux coroutinesLorsque la coroutine swoole m'a demandé à trois reprises, j'ai failli pleurer !

Recommandé (gratuit) : Tutoriel swoole

Qu'est-ce qu'un processus ?

Un processus est l'instance de démarrage d'une application. Ressources de fichiers indépendantes, ressources de données et espace mémoire.

Qu'est-ce qu'un fil de discussion ?

Les threads appartiennent aux processus et sont les exécuteurs des programmes. Un processus contient au moins un thread principal et peut également avoir plusieurs threads enfants. Les threads ont deux stratégies de planification, l’une est la planification en temps partagé et l’autre est la planification préemptive.

Mon groupe Penguin officiel

Qu'est-ce qu'une coroutine ?

Les coroutines sont des threads légers, les coroutines appartiennent également aux threads et les coroutines sont exécutées dans les threads. La planification des coroutines est modifiée manuellement par l'utilisateur, elle est donc également appelée thread de l'espace utilisateur. La création, la commutation, la suspension et la destruction de coroutines sont toutes des opérations mémoire et la consommation est très faible. La stratégie de planification des coroutines est la suivante : planification collaborative.

Le principe de la coroutine Swoole

  • Puisque Swoole4 est monothread et multi-processus, il n'y aura qu'une seule coroutine exécutée dans le même processus en même temps.

  • Le serveur Swoole reçoit des données et déclenche le rappel onReceive dans le processus de travail pour générer un Ctrip. Swoole crée un Ctrip correspondant pour chaque requête. Des sous-coroutines peuvent également être créées dans des coroutines.

  • L'implémentation sous-jacente de la coroutine est monothread, il n'y a donc qu'une seule coroutine travaillant en même temps, et l'exécution de la coroutine est en série.

  • Par conséquent, lorsque le multitâche et le multi-coroutine sont exécutés, lorsqu'une coroutine est en cours d'exécution, les autres coroutines cesseront de fonctionner. La coroutine actuelle se bloquera lors de l'exécution d'opérations d'E/S bloquantes et le planificateur sous-jacent entrera dans la boucle d'événements. Lorsqu'il y a un événement de fin d'E/S, le planificateur sous-jacent reprend l'exécution de la coroutine correspondant à l'événement. . Par conséquent, les coroutines n'ont pas de consommation de temps d'E/S et sont très adaptées aux scénarios d'E/S à haute concurrence. (Comme le montre l'image ci-dessous)

Lorsque la coroutine swoole ma demandé à trois reprises, jai failli pleurer !

Processus d'exécution de la coroutine de Swoole

  • La coroutine n'a pas d'E/S et attend une exécution normale, le code PHP ne provoquera pas de changement de flux d'exécution

  • Lorsque la coroutine rencontre une IO, elle changera immédiatement de contrôle. Une fois l'IO terminée, le flux d'exécution sera commuté. revenez à la coroutine d'origine. Cliquez sur

  • coroutine et coroutine parallèle pour exécuter en séquence, la même logique que le processus d'exécution imbriqué de coroutine

  • précédent. est entré couche par couche de l'extérieur vers l'intérieur jusqu'à ce que l'IO se produise, puis passe à la coroutine externe. La coroutine parent n'attendra pas la fin de la coroutine enfant

La séquence d'exécution du. coroutine

Jetons d'abord un coup d'œil aux bases Exemple :

go(function () {
    echo "hello go1 \n";});echo "hello main \n";go(function () {
    echo "hello go2 \n";});
Copier après la connexion

go() est l'abréviation de Co::create(), utilisée pour créer une coroutine qui accepte le rappel comme paramètre Le code dans. le rappel sera exécuté dans cette coroutine nouvellement créée.

Remarques : SwooleCoroutine peut être abrégé en Co

Le résultat de l'exécution du code ci-dessus :

root@b98940b00a9b /v/w/c/p/swoole# php co.phphello go1
hello main
hello go2
Copier après la connexion

Le résultat de l'exécution ne semble pas différent de l'ordre dans lequel nous écrivons habituellement le code. Le processus d'exécution réel :

  • Exécutez ce code, le système démarre un nouveau processus

  • rencontre

    , et une coroutine est générée dans le processus en cours. Le processus génère go(), la coroutine quitte heelo go1

  • et le processus continue d'exécuter le code vers le bas. , et le processus génère

    hello main

  • puis génère une coroutine , sortie

    dans la coroutine, quittez la coroutine heelo go2

. Exécutez ce code, le système démarre un nouveau processus. Si vous ne comprenez pas cette phrase, vous pouvez utiliser le code suivant :

// co.php<?phpsleep (100);
Copier après la connexion
Exécuter et utiliser

pour afficher les processus dans le système :ps aux

root@b98940b00a9b /v/w/c/p/swoole# php co.php &⏎
root@b98940b00a9b /v/w/c/p/swoole# ps auxPID   USER     TIME   COMMAND
    1 root       0:00 php -a   10 root       0:00 sh   19 root       0:01 fish  749 root       0:00 php co.php  760 root       0:00 ps aux
⏎
Copier après la connexion
Faisons un léger changement et expérimentons la planification des coroutines :

use Co;go(function () {
    Co::sleep(1); // 只新增了一行代码
    echo "hello go1 \n";});echo "hello main \n";go(function () {
    echo "hello go2 \n";});
Copier après la connexion

Fonctions de fonction et Co::sleep() Presque, mais cela simule l'attente d'IO (IO sera discuté en détail plus tard). Les résultats de l'exécution sont les suivants : sleep()

root@b98940b00a9b /v/w/c/p/swoole# php co.phphello main
hello go2
hello go1
Copier après la connexion
Pourquoi n'est-il pas exécuté séquentiellement ? Le processus d'exécution réel :

    Exécutez ce code, le système démarre un nouveau processus
  • rencontre
  • et génère une coroutine dans le processus en cours go()
  • rencontre un blocage d'E/S dans la coroutine (voici
  • attente d'E/S simulée), la coroutine abandonne le contrôle, entre dans la file d'attente de planification de la coroutine Co::sleep()
  • et le processus continue de s'exécuter vers le bas, sort
  • hello main
  • et exécute la coroutine suivante, sort
  • hello go2
  • La coroutine précédente est prête, continue l'exécution et sort
  • hello go1
À ce stade, vous pouvez déjà voir la relation entre la coroutine et le processus dans swoole, ainsi que la planification de la coroutine, changeons le programme tout à l'heure :

go(function () {
    Co::sleep(1);
    echo "hello go1 \n";});echo "hello main \n";go(function () {
    Co::sleep(1);
    echo "hello go2 \n";});
Copier après la connexion
Je pense que vous savez déjà à quoi ressemble le résultat :

root@b98940b00a9b /v/w/c/p/swoole# php co.phphello main
hello go1
hello go2
⏎
Copier après la connexion

协程快在哪? 减少IO阻塞导致的性能损失

大家可能听到使用协程的最多的理由, 可能就是 协程快. 那看起来和平时写得差不多的代码, 为什么就要快一些呢? 一个常见的理由是, 可以创建很多个协程来执行任务, 所以快. 这种说法是对的, 不过还停留在表面.

首先, 一般的计算机任务分为 2 种:

  • CPU密集型, 比如加减乘除等科学计算
  • IO 密集型, 比如网络请求, 文件读写等

其次, 高性能相关的 2 个概念:

  • 并行: 同一个时刻, 同一个 CPU 只能执行同一个任务, 要同时执行多个任务, 就需要有多个 CPU 才行
  • 并发: 由于 CPU 切换任务非常快, 快到人类可以感知的极限, 就会有很多任务 同时执行 的错觉

了解了这些, 我们再来看协程, 协程适合的是 IO 密集型 应用, 因为协程在 IO阻塞 时会自动调度, 减少IO阻塞导致的时间损失.

我们可以对比下面三段代码:

  • 普通版: 执行 4 个任务
$n = 4;for ($i = 0; $i <pre class="brush:php;toolbar:false">root@b98940b00a9b /v/w/c/p/swoole# time php co.php1528965075.4608: hello 01528965076.461: hello 11528965077.4613: hello 21528965078.4616: hello 3hello main
real    0m 4.02s
user    0m 0.01s
sys     0m 0.00s
⏎
Copier après la connexion
  • 单个协程版:
$n = 4;go(function () use ($n) {
    for ($i = 0; $i <pre class="brush:php;toolbar:false">root@b98940b00a9b /v/w/c/p/swoole# time php co.phphello main1528965150.4834: hello 01528965151.4846: hello 11528965152.4859: hello 21528965153.4872: hello 3real    0m 4.03s
user    0m 0.00s
sys     0m 0.02s
⏎
Copier après la connexion
  • 多协程版: 见证奇迹的时刻
$n = 4;for ($i = 0; $i <pre class="brush:php;toolbar:false">root@b98940b00a9b /v/w/c/p/swoole# time php co.phphello main1528965245.5491: hello 01528965245.5498: hello 31528965245.5502: hello 21528965245.5506: hello 1real    0m 1.02s
user    0m 0.01s
sys     0m 0.00s
⏎
Copier après la connexion

为什么时间有这么大的差异呢:

  • 普通写法, 会遇到 IO阻塞 导致的性能损失

  • 单协程: 尽管 IO阻塞 引发了协程调度, 但当前只有一个协程, 调度之后还是执行当前协程

  • 多协程: 真正发挥出了协程的优势, 遇到 IO阻塞 时发生调度, IO就绪时恢复运行

我们将多协程版稍微修改一下:

  • 多协程版2: CPU密集型
$n = 4;for ($i = 0; $i <pre class="brush:php;toolbar:false">root@b98940b00a9b /v/w/c/p/swoole# time php co.php1528965743.4327: hello 01528965744.4331: hello 11528965745.4337: hello 21528965746.4342: hello 3hello main
real    0m 4.02s
user    0m 0.01s
sys     0m 0.00s
⏎
Copier après la connexion

只是将 Co::sleep() 改成了 sleep(), 时间又和普通版差不多了. 因为:

  • sleep() 可以看做是 CPU密集型任务, 不会引起协程的调度

  • Co::sleep() 模拟的是 IO密集型任务, 会引发协程的调度
    这也是为什么, 协程适合 IO密集型 的应用.

再来一组对比的例子: 使用 redis

// 同步版, redis使用时会有 IO 阻塞$cnt = 2000;for ($i = 0; $i connect('redis');
    $redis->auth('123');
    $key = $redis->get('key');}// 单协程版: 只有一个协程, 并没有使用到协程调度减少 IO 阻塞go(function () use ($cnt) {
    for ($i = 0; $i connect('redis', 6379);
        $redis->auth('123');
        $redis->get('key');
    }});// 多协程版, 真正使用到协程调度带来的 IO 阻塞时的调度for ($i = 0; $i connect('redis', 6379);
        $redis->auth('123');
        $redis->get('key');
    });}
Copier après la connexion

性能对比:

# 多协程版root@0124f915c976 /v/w/c/p/swoole# time php co.phpreal    0m 0.54s
user    0m 0.04s
sys     0m 0.23s
⏎# 同步版root@0124f915c976 /v/w/c/p/swoole# time php co.phpreal    0m 1.48s
user    0m 0.17s
sys     0m 0.57s
⏎
Copier après la connexion

swoole 协程和 go 协程对比: 单进程 vs 多线程

接触过 go 协程的 coder, 初始接触 swoole 的协程会有点 懵, 比如对比下面的代码:

package main

import (
    "fmt"
    "time")func main() {
    go func() {
        fmt.Println("hello go")
    }()

    fmt.Println("hello main")

    time.Sleep(time.Second)}
Copier après la connexion
> 14:11 src $ go run test.go
hello main
hello go
Copier après la connexion

刚写 go 协程的 coder, 在写这个代码的时候会被告知不要忘了 time.Sleep(time.Second), 否则看不到输出 hello go, 其次, hello gohello main 的顺序也和 swoole 中的协程不一样.

原因就在于 swoole 和 go 中, 实现协程调度的模型不同.

上面 go 代码的执行过程:

  • 运行 go 代码, 系统启动一个新进程
  • 查找 package main, 然后执行其中的 func mian()
  • 遇到协程, 交给协程调度器执行
  • 继续向下执行, 输出 hello main
  • 如果不添加 time.Sleep(time.Second), main 函数执行完, 程序结束, 进程退出, 导致调度中的协程也终止

go 中的协程, 使用的 MPG 模型:

  • M 指的是 Machine, 一个M直接关联了一个内核线程
  • P 指的是 processor, 代表了M所需的上下文环境, 也是处理用户级代码逻辑的处理器
  • G 指的是 Goroutine, 其实本质上也是一种轻量级的线程

MPG 模型

而 swoole 中的协程调度使用 单进程模型, 所有协程都是在当前进程中进行调度, 单进程的好处也很明显 – 简单 / 不用加锁 / 性能也高.

无论是 go 的 MPG模型, 还是 swoole 的 单进程模型, 都是对 CSP理论 的实现.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment prolonger Swoole avec des modules personnalisés? Comment prolonger Swoole avec des modules personnalisés? Mar 18, 2025 pm 03:57 PM

L'article discute de l'extension de Swoole avec des modules personnalisés, des étapes de détail, des meilleures pratiques et du dépannage. L'objectif principal est d'améliorer les fonctionnalités et l'intégration.

Comment puis-je utiliser le pool de mémoire de Swoole pour réduire la fragmentation de la mémoire? Comment puis-je utiliser le pool de mémoire de Swoole pour réduire la fragmentation de la mémoire? Mar 17, 2025 pm 01:23 PM

L'article discute de l'utilisation du pool de mémoire de Swoole pour réduire la fragmentation de la mémoire par une gestion et une configuration efficaces de la mémoire. L'accent principal est d'activer, de dimensionner et de réutiliser la mémoire dans le pool.

Comment configurer l'isolement du processus de Swoole? Comment configurer l'isolement du processus de Swoole? Mar 18, 2025 pm 03:55 PM

L'article discute de la configuration de l'isolement du processus de Swoole, de ses avantages tels que l'amélioration de la stabilité et de la sécurité, et les méthodes de dépannage. Compte de chargement: 159

Comment utiliser les fonctionnalités d'E / S asynchrones de Swoole? Comment utiliser les fonctionnalités d'E / S asynchrones de Swoole? Mar 18, 2025 pm 03:56 PM

L'article discute de l'utilisation des fonctionnalités d'E / S asynchrones de Swoole en PHP pour les applications hautes performances. Il couvre l'installation, la configuration du serveur et les stratégies d'optimisation. Nombre de mots: 159

Comment puis-je contribuer au projet Swoole Open-source? Comment puis-je contribuer au projet Swoole Open-source? Mar 18, 2025 pm 03:58 PM

L'article décrit les moyens de contribuer au projet Swoole, notamment la déclaration des bogues, la soumission des fonctionnalités, le codage et l'amélioration de la documentation. Il traite des compétences et des étapes requises pour que les débutants commencent à contribuer, et comment trouver des pressions est

Comment fonctionne le modèle du réacteur de Swoole sous le capot? Comment fonctionne le modèle du réacteur de Swoole sous le capot? Mar 18, 2025 pm 03:54 PM

Le modèle de réacteur de Swoole utilise une architecture d'E / S non bloquante axée sur les événements pour gérer efficacement les scénarios à haute monnaie, optimisant les performances via diverses techniques. (159 caractères)

Comment puis-je utiliser Swoole pour construire une architecture de microservices? Comment puis-je utiliser Swoole pour construire une architecture de microservices? Mar 17, 2025 pm 01:18 PM

L'article discute de l'utilisation de Swoole pour les microservices, en se concentrant sur la conception, la mise en œuvre et l'amélioration des performances via des E / S asynchrones et des coroutines. Nombre de mots: 159

Quels outils puis-je utiliser pour surveiller les performances de Swoole? Quels outils puis-je utiliser pour surveiller les performances de Swoole? Mar 18, 2025 pm 03:52 PM

L'article traite des outils et des meilleures pratiques pour surveiller et optimiser les performances de Swoole et le dépannage des méthodes de problèmes de performance.

See all articles