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

PCS2020 - PHP Além do Síncrono

Diana Arnos
September 12, 2020

PCS2020 - PHP Além do Síncrono

Apresentada durante o PHP Community Summit de 2020.

Quando tudo era mato, ninguém acreditava que a linguagem PHP poderia ser usada para nada além da execução de scripts simples, sites ou um CMS de código bem bagunçado.
Então o mundo mudou e hoje temos grandes frameworks, sistemas corporativos, grandes portais e redes sociais e até sistemas de segurança e pagamentos escritos em PHP.
Agora, a comunidade se debruça sobre o novo hype (ou seria necessidade?): processamento assíncrono e paralelo.
Nessa apresentação, vamos entender a difereça entre async e paralelo, como podemos trabalhar com isso usando PHP (inclusive nativamente) e quais as principais diferenças entre as soluções mais hypadas (digo, famosas) do momento.

Diana Arnos

September 12, 2020
Tweet

More Decks by Diana Arnos

Other Decks in Programming

Transcript

  1. PHP Além do Síncrono
    O reino mágico do processamento async e paralelo

    View full-size slide

  2. @dianaarnos
    Dev, Sec, Music, Kung Fu.
    PHP Engineer @ Usabilla (Amsterdã, Holanda) (soon)
    Evangelista @ PHPSP
    Evangelista @ PHPWomenBR

    View full-size slide

  3. PHP é síncrono

    View full-size slide

  4. PHP é síncrono
    Mas dá pra trabalhar
    assíncrono

    View full-size slide

  5. PHP é síncrono
    Mas dá pra trabalhar
    assíncrono
    Não é pra isso
    que serve!

    View full-size slide

  6. PHP é síncrono
    Mas dá pra trabalhar
    assíncrono
    Não é pra isso
    que serve!
    Se funciona,
    então serve

    View full-size slide

  7. PHP é síncrono
    Mas dá pra trabalhar
    assíncrono
    Não é pra isso
    que serve!
    Se funciona,
    então serve
    M
    AS
    E
    O
    SHARE
    NOTHING?!

    View full-size slide

  8. PHP é síncrono
    Mas dá pra trabalhar
    assíncrono
    Não é pra isso
    que serve!
    Se funciona,
    então serve
    M
    AS
    E
    O
    SHARE
    NOTHING?!
    M
    AS
    É
    O
    UTRO
    CO
    NTEXTO
    !

    View full-size slide

  9. Calma, xovem. É muita emoção.

    View full-size slide

  10. Síncrono
    Requests
    Tempo
    Task #1
    Task #2
    Task #3

    View full-size slide

  11. Assíncrono
    Requests
    Tempo
    Task #1
    Task #2
    Task #3
    Task #1
    Task #3

    View full-size slide

  12. Paralelo
    Requests
    Tempo
    Task #1
    Task #2
    Task #3
    Task #1
    Task #3
    Task #2
    Task #1
    Task #2
    Task #3

    View full-size slide

  13. Paralelismo e Assíncronismo = Concorrência

    View full-size slide

  14. Concorrência no PHP?

    View full-size slide

  15. Ext Parallel

    View full-size slide

  16. Ext Parallel - ZTS

    View full-size slide

  17. use parallel\Runtime;
    $runtime = new Runtime();
    $future = $runtime->run(function(){
    for ($i = 0; $i < 100; $i++)
    echo "*";
    return "fácil";
    });
    for ($i = 0; $i < 100; $i++) {
    echo ".";
    }
    printf("\nUsar o \\parallel\\Runtime é %s\n", $future->value());

    View full-size slide

  18. Parallel x Swoole
    Swoole implements co-operative multi-tasking, and if you were following along, you
    already figured out that this is not based on parallel concurrency, but on
    asynchronous concurrency. When the readme says "you can think of co-routines as
    individual threads", it's referring to green threads. No user code is executed in
    parallel, it is executed asynchronously. The internals of swoole does use threads
    but to service I/O, not to execute user code.
    - Joe Watkins (krakjoe)

    View full-size slide

  19. PHP é síncrono. Realmente.

    View full-size slide

  20. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  21. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  22. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  23. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  24. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  25. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  26. echo PHP_EOL . "Step 1" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Step 2" . PHP_EOL;
    for ($i = 0; $i <11; $i++) {
    echo ".";
    }
    echo PHP_EOL . "Finish." . PHP_EOL;

    View full-size slide

  27. Mas dá pra ser assíncrono também.

    View full-size slide

  28. Mas dá pra ser assíncrono também.
    Nativo.

    View full-size slide

  29. Olá, generators!

    View full-size slide

  30. $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL . "Generator's end."
    ;
    };

    View full-size slide

  31. $generator = $function();
    echo PHP_EOL . "Main flow";
    echo $generator->current();
    echo PHP_EOL . "Main flow";
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow";
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() . PHP_EOL;
    echo PHP_EOL . "Main flow";
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL . "Generator's end."
    ;
    };

    View full-size slide

  32. $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };
    $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;

    View full-size slide

  33. $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };
    $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;

    View full-size slide

  34. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  35. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  36. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  37. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  38. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  39. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  40. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  41. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  42. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  43. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  44. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  45. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  46. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  47. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  48. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  49. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  50. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  51. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  52. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  53. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  54. $generator = $function();
    echo PHP_EOL . "Main flow" ;
    echo $generator->current();
    echo PHP_EOL . "Main flow" ;
    $generator->next();
    echo $generator->current();
    $generator->next();
    echo PHP_EOL . "Main flow" ;
    $generator->send("aeeewww");
    $generator->next();
    echo $generator->getReturn() .
    PHP_EOL;
    echo PHP_EOL . "Main flow" ;
    $function = function ()
    {
    yield PHP_EOL . "Starting";
    echo PHP_EOL . "-";
    yield PHP_EOL . ".";
    $incoming = yield;
    echo PHP_EOL . $incoming;
    return PHP_EOL .
    "Generator's end.";
    };

    View full-size slide

  55. Prazer, corrotina.

    View full-size slide

  56. Mas… e requests?

    View full-size slide

  57. curl_multi_*

    View full-size slide

  58. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  59. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  60. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  61. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  62. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  63. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  64. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  65. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  66. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  67. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  68. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  69. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  70. $urls = ["http://dummy.restapiexample.com/api/v1/employee/1"
    , "http://dummy.restapiexample.com/api/v1/employee/2"
    ,];
    $multiHandle = curl_multi_init()
    ;
    $curls = [];
    $results = [];
    $callback = function ($data) {
    echo $data . PHP_EOL;
    };
    foreach ($urls as $url) {
    $handle = curl_init()
    ;
    curl_setopt_array(
    $handle, [CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => false]);
    $curls[$url] = $handle;
    curl_multi_add_handle(
    $multiHandle
    , $handle);
    }
    $isRunning = null;
    do {
    $multiCurlStatus = curl_multi_exec(
    $multiHandle
    , $isRunning);
    $resource = curl_multi_info_read(
    $multiHandle
    );
    if ($resource) {
    $callback(curl_multi_getcontent(
    $resource['handle']));
    curl_multi_remove_handle(
    $multiHandle
    , $resource['handle']);
    }
    } while ($multiCurlStatus == CURLM_CALL_MULTI_PERFORM || $isRunning);

    View full-size slide

  71. Concorrência assíncrona :)

    View full-size slide

  72. Mas tem mais!

    View full-size slide

  73. I/O multiplexing com… stream_select

    View full-size slide

  74. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  75. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  76. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  77. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  78. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  79. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  80. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  81. $host = "dummy.restapiexample.com";
    $resource = [
    "api/v1/employee/1",
    "api/v1/employee/2",
    ];
    $clients = [];
    foreach ($resource as $url) {
    $socketClient = stream_socket_client(
    'tcp://' . $host . ':80',
    $errno,
    $errstr,
    10,
    STREAM_CLIENT_ASYNC_CONNECT
    );
    $clients[$url] = $socketClient;
    $request = "GET /" . $url . " HTTP/1.1" . PHP_EOL . "Host: " . $host . PHP_EOL . PHP_EOL;
    fwrite($socketClient, $request);
    stream_set_blocking($socketClient, 0);
    }
    stream_select($clients, $write, $ex, 10);
    if (count($clients)) {
    foreach ($clients as $id => $socket) {
    echo fread($socket, 2000);
    }
    }

    View full-size slide

  82. MAIS AINDA!
    Eventos com stream context

    View full-size slide

  83. public function download
    ()
    {
    $context = stream_context_create()
    ;
    stream_context_set_params(
    $context
    , ['notification' => [Downloader::
    class, 'streamCallback'
    ]]);
    $handler = fopen(
    $this->youtube->getUrl(), 'r', false, $context
    );
    if (!$handler
    ) {
    throw new \InvalidArgumentException(
    "Unable to download from link "
    . $this->youtube->getUrl());
    }
    file_put_contents(
    $this->youtube->getName(), $handler
    );
    }
    public function streamCallback
    ($notification_code
    , $severity
    , $message
    , $message_code
    , $bytes_transfered
    , $bytes_max
    )
    {
    static $filesize = null;
    switch ($notification_code
    ) {
    case STREAM_NOTIFY_RESOLVE:
    case STREAM_NOTIFY_AUTH_REQUIRED:
    case STREAM_NOTIFY_COMPLETED:
    case STREAM_NOTIFY_FAILURE:
    case STREAM_NOTIFY_AUTH_RESULT:
    break;
    case STREAM_NOTIFY_REDIRECTED:
    echo "Being redirected to: " . $message . PHP_EOL;
    break;
    case STREAM_NOTIFY_CONNECT:
    echo "Connected!" . PHP_EOL;
    case STREAM_NOTIFY_FILE_SIZE_IS:
    $filesize = $bytes_max
    ;
    echo "Filesize: " . $filesize . PHP_EOL;
    case STREAM_NOTIFY_MIME_TYPE_IS:
    echo "Mime-type: " . $message . PHP_EOL;
    case STREAM_NOTIFY_PROGRESS:
    if ($bytes_transfered > 0) {
    $length = (int)(($bytes_transfered / $filesize
    ) * 100);
    printf("\r[%-100s] %d%% (%2d/%2d mb)"
    , str_repeat(
    "=", $length) . ">", $length, ($bytes_transfered / 1024 / 1024), $filesize / 1024 / 1024);
    }
    break;
    }
    }

    View full-size slide

  84. public function download
    ()
    {
    $context = stream_context_create()
    ;
    stream_context_set_params(
    $context
    , ['notification' => [Downloader::
    class, 'streamCallback'
    ]]);
    $handler = fopen(
    $this->youtube->getUrl(), 'r', false, $context
    );
    if (!$handler
    ) {
    throw new \InvalidArgumentException(
    "Unable to download from link "
    . $this->youtube->getUrl());
    }
    file_put_contents(
    $this->youtube->getName(), $handler
    );
    }
    public function streamCallback
    ($notification_code
    , $severity
    , $message
    , $message_code
    , $bytes_transfered
    , $bytes_max
    )
    {
    static $filesize = null;
    switch ($notification_code
    ) {
    case STREAM_NOTIFY_RESOLVE:
    case STREAM_NOTIFY_AUTH_REQUIRED:
    case STREAM_NOTIFY_COMPLETED:
    case STREAM_NOTIFY_FAILURE:
    case STREAM_NOTIFY_AUTH_RESULT:
    break;
    case STREAM_NOTIFY_REDIRECTED:
    echo "Being redirected to: " . $message . PHP_EOL;
    break;
    case STREAM_NOTIFY_CONNECT:
    echo "Connected!" . PHP_EOL;
    case STREAM_NOTIFY_FILE_SIZE_IS:
    $filesize = $bytes_max
    ;
    echo "Filesize: " . $filesize . PHP_EOL;
    case STREAM_NOTIFY_MIME_TYPE_IS:
    echo "Mime-type: " . $message . PHP_EOL;
    case STREAM_NOTIFY_PROGRESS:
    if ($bytes_transfered > 0) {
    $length = (int)(($bytes_transfered / $filesize
    ) * 100);
    printf("\r[%-100s] %d%% (%2d/%2d mb)"
    , str_repeat(
    "=", $length) . ">", $length, ($bytes_transfered / 1024 / 1024), $filesize / 1024 / 1024);
    }
    break;
    }
    }

    View full-size slide

  85. public function download
    ()
    {
    $context = stream_context_create()
    ;
    stream_context_set_params(
    $context
    , ['notification' => [Downloader::
    class, 'streamCallback'
    ]]);
    $handler = fopen(
    $this->youtube->getUrl(), 'r', false, $context
    );
    if (!$handler
    ) {
    throw new \InvalidArgumentException(
    "Unable to download from link "
    . $this->youtube->getUrl());
    }
    file_put_contents(
    $this->youtube->getName(), $handler
    );
    }
    public function streamCallback
    ($notification_code
    , $severity
    , $message
    , $message_code
    , $bytes_transfered
    , $bytes_max
    )
    {
    static $filesize = null;
    switch ($notification_code
    ) {
    case STREAM_NOTIFY_RESOLVE:
    case STREAM_NOTIFY_AUTH_REQUIRED:
    case STREAM_NOTIFY_COMPLETED:
    case STREAM_NOTIFY_FAILURE:
    case STREAM_NOTIFY_AUTH_RESULT:
    break;
    case STREAM_NOTIFY_REDIRECTED:
    echo "Being redirected to: " . $message . PHP_EOL;
    break;
    case STREAM_NOTIFY_CONNECT:
    echo "Connected!" . PHP_EOL;
    case STREAM_NOTIFY_FILE_SIZE_IS:
    $filesize = $bytes_max
    ;
    echo "Filesize: " . $filesize . PHP_EOL;
    case STREAM_NOTIFY_MIME_TYPE_IS:
    echo "Mime-type: " . $message . PHP_EOL;
    case STREAM_NOTIFY_PROGRESS:
    if ($bytes_transfered > 0) {
    $length = (int)(($bytes_transfered / $filesize
    ) * 100);
    printf("\r[%-100s] %d%% (%2d/%2d mb)"
    , str_repeat(
    "=", $length) . ">", $length, ($bytes_transfered / 1024 / 1024), $filesize / 1024 / 1024);
    }
    break;
    }
    }

    View full-size slide

  86. public function download
    ()
    {
    $context = stream_context_create()
    ;
    stream_context_set_params(
    $context
    , ['notification' => [Downloader::
    class, 'streamCallback'
    ]]);
    $handler = fopen(
    $this->youtube->getUrl(), 'r', false, $context
    );
    if (!$handler
    ) {
    throw new \InvalidArgumentException(
    "Unable to download from link "
    . $this->youtube->getUrl());
    }
    file_put_contents(
    $this->youtube->getName(), $handler
    );
    }
    public function streamCallback
    ($notification_code
    , $severity
    , $message
    , $message_code
    , $bytes_transfered
    , $bytes_max
    )
    {
    static $filesize = null;
    switch ($notification_code
    ) {
    case STREAM_NOTIFY_RESOLVE:
    case STREAM_NOTIFY_AUTH_REQUIRED:
    case STREAM_NOTIFY_COMPLETED:
    case STREAM_NOTIFY_FAILURE:
    case STREAM_NOTIFY_AUTH_RESULT:
    break;
    case STREAM_NOTIFY_REDIRECTED:
    echo "Being redirected to: " . $message . PHP_EOL;
    break;
    case STREAM_NOTIFY_CONNECT:
    echo "Connected!" . PHP_EOL;
    case STREAM_NOTIFY_FILE_SIZE_IS:
    $filesize = $bytes_max
    ;
    echo "Filesize: " . $filesize . PHP_EOL;
    case STREAM_NOTIFY_MIME_TYPE_IS:
    echo "Mime-type: " . $message . PHP_EOL;
    case STREAM_NOTIFY_PROGRESS:
    if ($bytes_transfered > 0) {
    $length = (int)(($bytes_transfered / $filesize
    ) * 100);
    printf("\r[%-100s] %d%% (%2d/%2d mb)"
    , str_repeat(
    "=", $length) . ">", $length, ($bytes_transfered / 1024 / 1024), $filesize / 1024 / 1024);
    }
    break;
    }
    }

    View full-size slide

  87. public function download
    ()
    {
    $context = stream_context_create()
    ;
    stream_context_set_params(
    $context
    , ['notification' => [Downloader::
    class, 'streamCallback'
    ]]);
    $handler = fopen(
    $this->youtube->getUrl(), 'r', false, $context
    );
    if (!$handler
    ) {
    throw new \InvalidArgumentException(
    "Unable to download from link "
    . $this->youtube->getUrl());
    }
    file_put_contents(
    $this->youtube->getName(), $handler
    );
    }
    public function streamCallback
    ($notification_code
    , $severity
    , $message
    , $message_code
    , $bytes_transfered
    , $bytes_max
    )
    {
    static $filesize = null;
    switch ($notification_code
    ) {
    case STREAM_NOTIFY_RESOLVE:
    case STREAM_NOTIFY_AUTH_REQUIRED:
    case STREAM_NOTIFY_COMPLETED:
    case STREAM_NOTIFY_FAILURE:
    case STREAM_NOTIFY_AUTH_RESULT:
    break;
    case STREAM_NOTIFY_REDIRECTED:
    echo "Being redirected to: " . $message . PHP_EOL;
    break;
    case STREAM_NOTIFY_CONNECT:
    echo "Connected!" . PHP_EOL;
    case STREAM_NOTIFY_FILE_SIZE_IS:
    $filesize = $bytes_max
    ;
    echo "Filesize: " . $filesize . PHP_EOL;
    case STREAM_NOTIFY_MIME_TYPE_IS:
    echo "Mime-type: " . $message . PHP_EOL;
    case STREAM_NOTIFY_PROGRESS:
    if ($bytes_transfered > 0) {
    $length = (int)(($bytes_transfered / $filesize
    ) * 100);
    printf("\r[%-100s] %d%% (%2d/%2d mb)"
    , str_repeat(
    "=", $length) . ">", $length, ($bytes_transfered / 1024 / 1024), $filesize / 1024 / 1024);
    }
    break;
    }
    }

    View full-size slide

  88. Forks?
    pnct_*

    View full-size slide

  89. $pid = pcntl_fork() ;
    if ($pid == -1) {
    die('could not fork' );
    } else if ($pid) {
    // we are the parent
    pcntl_wait($status); //Protect against Zombie children
    } else {
    // we are the child
    }

    View full-size slide

  90. Só funciona em Linux

    View full-size slide

  91. Só funciona em Linux
    Limitado ao número de CPUs

    View full-size slide

  92. Fork != Thread

    View full-size slide

  93. - Concorrência paralela

    View full-size slide

  94. - Concorrência paralela
    - Concorrência assíncrona

    View full-size slide

  95. - Concorrência paralela
    - Concorrência assíncrona
    - Eventos

    View full-size slide

  96. - Concorrência paralela
    - Concorrência assíncrona
    - Eventos
    - Paralelização

    View full-size slide

  97. Você tem seu próprio ReactPHP, Amp,
    etc...

    View full-size slide

  98. Ahhhh, mas se fosse Java...

    View full-size slide

  99. O PHP também faz.

    View full-size slide

  100. REFERÊNCIAS
    http://bit.ly/pcs2020-ref

    View full-size slide

  101. SLIDES
    http://bit.ly/pcs2020-slides

    View full-size slide

  102. JOIND.IN
    https://joind.in/talk/43ab3

    View full-size slide

  103. OBRIGADA!
    Fale comigo: @dianaarnos

    View full-size slide