$30 off During Our Annual Pro Sale. View Details »

ハチャメチャに叩く

uzulla
July 13, 2018

 ハチャメチャに叩く

【非公式】PHPカンファレンス 2018 関西 前夜祭
https://dbstudychugoku.connpass.com/event/92337/

uzulla

July 13, 2018
Tweet

More Decks by uzulla

Other Decks in Programming

Transcript

  1. ϋνϟϝνϟʹhttp(s)
    ͰԥΓ͍ͨ

    View Slide

  2. @uzulla

    View Slide

  3. ઌ೔Swooleͷ࿩Λ͠·͕ͨ͠
    • https:/
    /speakerdeck.com/uzulla/zui-jin-
    meruhuomukaitenaimeruhuomaniyoru-tiyotutodakebian-watuta-
    ying-phpfalsemeruhuomu-falseohua-fu-ti-zui-jin-
    swoolegatafalsesiidesu
    • ʢ௕͍…ʣ
    • ʢuzulla swoole speakerdeckͰݕࡧʣ
    • ඇಉظɺcoroutine౳ͷ࿩͕͋·ΓͰ͖ͳ͔ͬͨͷͰ
    • ͦͷؔ࿈

    View Slide

  4. ਓ͸ϋνϟϝνϟʹʢAPIͱ͔Λʣୟ͖͍ͨ
    • PHPͰ΋ͲΜͲΜୟ͖͍ͨ
    • Ϋϩʔϧ͍ͨͨ͠Ί
    • ྲྀߦͷϚΠΫϩφϯτΧͰ୔ࢁAPIΛୟ͘ඞཁ
    • ૘շײΛಘΔͨΊ

    View Slide

  5. • ͔͠͠PHP͸ʮ஗͍ʯ(Β͍͠) !

    View Slide

  6. • Կ͕஗͍͔ʁ!
    • http͸ʮऔಘ͢Δ଴ͪ࣌ؒʯ͕ࢧ഑త
    • ௚ྻͷಉظॲཧͰ͸ͦͷؒͳʹ΋Ͱ͖ͳ͍ʂ "
    • ଞͷݴޠͰ͸؆୯ʹʢʁʣϚϧνεϨουʹͨ͠Γ͢Δʢཁ
    ग़య#ʣ
    • ͔͠͠PHP͸ϚϧνεϨουɺϚϧνϓϩηε͸Ή͔͍ͣ͠
    ʢཁग़య#ʣ

    View Slide

  7. Ͳ͏͢Δ͔ʁ
    • ඇಉظͩʂ
    • PHPͷඇಉظ͸݁ߏྺ࢙͕͋Δ(ओ؍)
    • ʢඇಉظI/OɺϊϯϒϩοΩϯάI/OɺଟॏԽI/Oͱ͔৭ʑ͋Δ
    ͕ɺ͜͜Ͱ͸Ұॹͨ͘ʹඇಉظͱ͓͖ͯ͠·͢ʣ

    View Slide

  8. ʮඇಉظʯͱ͸ʁ
    • I/OॲཧதʹϘʔͬͱͤͣɺଞͷ͜ͱΛ΍ΕΔ
    • ฒྻॲཧͰ͸ͳ͍ɺʢਅͷʣϚϧνεϨουͰ͸ͳ͍
    • ͳΜΒ͔c֦ுΛೖΕͳ͍ͱCPUෛՙ͕ߴ͍
    • ex: ev,uv,event,swoole
    • ૉखͰ৮Δͷ͸େมͳͷͰϑϨʔϜϫʔΫ͕ॏཁ
    • ex: reactPHP,swoole,amp౳

    View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. ༨ஊ curl_multi Ͱ͍͍ͷͰ͸ʁ
    • ࠷ॳʹʮNݸऔಘʯΈ͍ͨʹͳΔͷͰɺ̍ͭऴΘΓ࣍ୈҰͭى
    ಈͱ͔Ͱ͖ͳ͍
    • ༻్ʹΑΔ͕ɺྫ͑͹ΫϩʔϥͰ͸ඞཁ
    • selectͷѻ͍͸೉͍͠…
    • ʢͦ΋ͦ΋curl_* ࣗମ͕೉͍͠ʣ
    • ʢͲ͜ʹͰ΋ೖ͍ͬͯΔʢʁʣͷ͸࠷ߴʣ

    View Slide

  15. ʮͱ͍͏͜ͱͰswooleͰඇಉظͩʂʯ
    • ຺བྷ͸লུ͠·͢ɻ
    • ʮͳͥPHPͳͷ͔ɺదࡐదॴ͕ඞཁͰ͸ʁʁʯ
    • ʮࠓ೔PHPҎ֎ͷ࿩ͯ͠΋͔ͨ͠ͳ͍Ͱ͠ΐ…ʯ

    View Slide

  16. swooleʹ͓͚Δهड़ํࣜ
    • callbackํࣜ
    • coroutineํࣜ

    View Slide

  17. • callbackํࣜ
    • ΠϕϯτۦಈΒ͍͠ॻ͖ํ
    • JSͬΆ͍
    • ຊདྷ͕ͪ͜ΒͳͷͰɺݫີʹௐ੔͠΍͍͢
    • ωετ΍෼அ͕૿͑ΔͷͰগʑಡΈͮΒ͍

    View Slide

  18. • coroutineํࣜ
    • ී௨ͷίʔυͬΆ͍ɺಡΈ΍͍͢ɺָ
    • (PHPͷ) δΣωϨʔλͬΆ͍
    • ͪΐͬͱͨ͠ແବ͕Ͱ͖΍͍͢
    • ৭ʑӅṭ͞Ε͍ͯΔͷͰɺٯʹ೴಺࣮ߦͮ͠Β͍͜ͱ΋
    • ࠓճ͸ͪ͜Β

    View Slide

  19. • swoole͸࠷ۙcoroutineํࣜਪ͠
    • swoole͸go()Λ͔ͭ͏ͱɺઐ༻؀ڥʢΠϕϯτϧʔϓͳͲʣ֎Ͱ
    ΋ίϧʔνϯΛಈ͔ͤΔ
    • ʢͷͰָɻׂ͕͜͜ͱॏཁͳͷ͕ͩɺൺֱʹͳΔ͠આ໌͕௕
    ͘ͳΔͷͰলུʣ

    View Slide

  20. coroutineͷྑ͍ͱ͜Ζ
    • ;ͭʔͷίʔυͰ͸ɺAPI΍DBΞΫηεΛ͍͔ͭ͘ॱ൪ʹߦ͏
    • coroutine͸ී௨(௚ྻ)ʹॻ͚Δ
    • callbackํࣜ͸ωετ(ؔ਺Ͱ෼ׂ)͠ͳ͚Ε͹ͳΒͳ͍
    • PromiseΛ͔ͭ͑͹ฏୱʹ͸Ͱ͖Δ͕ɺείʔϓͷ෼ׂ͸͞Ε
    Δ

    View Slide

  21. ͱ͍͏͜ͱͰαϯϓϧίʔυ
    • coroutineํࣜ
    • ʮwhileͰ΍ΔͷɺͲ͏ͳͷʁʯ
    ʮsleepΛௐ੔͢Ε͹࣮༻Ͱ͠ΐ…ʢͲ͏͔ͳʁʣʯ

    View Slide

  22. • ͓ࢼ͢͠Δਓ͸ͪ͜Β͔ΒͲ͏ͧ
    • https:/
    /github.com/uzulla/sample-co-get

    View Slide

  23. const MAX_REQ = 10; // نఆॲཧ਺
    $req_num = 0;
    while (1) {
    echo ".";
    // نఆॲཧ਺Λ௒͑ͨͷͰऴྃ
    if ($req_num >= MAX_REQ) { break; }
    // औಘ
    $req_num++;
    $_ = file_get_contents("http://example.jp");
    }

    View Slide

  24. • 1req2ඵ͔͔ΔAPIΛ10ճऔಘͩͱ…
    real 0m20.199s
    user 0m0.089s
    sys 0m0.067s

    View Slide

  25. go(function () {
    $now_worker_num = 0;
    $req_num = 0;
    while (1) { echo ".";
    co::sleep(0.001); // εέδϡʔϥͷͨΊʹ
    // نఆॲཧूΛ௒͑ͨͷͰऴྃ
    if ($req_num >= MAX_REQ) { break; }
    // ىಈதͷίϧʔνϯ͕نఆ਺ʹୡ͍ͯ͠ͳ͚Ε͹௥Ճىಈɺ
    // ʢنఆϫʔΧʔ਺ͳΒىಈͤͣɺϧʔϓઌ಄΁ʣ
    if ($now_worker_num >= MAX_WORKER_NUM) { continue; }

    View Slide

  26. // while (1) {
    // ...
    // go()಺ͷΫϩʔδϟ͕ίϧʔνϯͱͯ͠εέδϡʔϥʹొ࿥
    go(function () use (&$now_worker_num, &$req_num) {
    $req_num++;
    $now_worker_num++;
    $http = new \Swoole\Coroutine\Http\Client(
    "http://example.jp", 80);
    $http->get('/');
    $_ = $http->body;
    $now_worker_num--;
    }); // ্ه׬ྃΛ଴ͨͣʹൈ͚Δ
    }
    });

    View Slide

  27. real 0m4.187s
    user 0m0.267s
    sys 0m0.523s

    View Slide

  28. • 1req2ඵ͔͔ΔAPIΛ10ճऔಘ͢Δͷʹ
    • ʢಉظʣ20ඵ->ʢඇಉظʣ4ඵ
    • ಉ࣌5઀ଓͩͱ̎ճ
    • ಉ࣌10ʹͳΒҰׅͰऴΘΔͷͰ̎ඵʹ
    • ʢ…ͳΔ͜ͱ΋͋Δʣ

    View Slide

  29. coroutineཧղצॴ
    • go()ͰίϧʔνϯΛ࡞੒ͯ͠ʮޙͰ࣮ߦϦετʯʹ௥Ճ͠ʢεέ
    δϡʔϧ͞ΕΔʣɺޙͰ࣮ߦ͢Δ
    • ઐ༻ʹ࡞ΒΕͨؔ਺Ҏ֎͸ඇಉظʹ͸ͳΒͳ͍

    View Slide

  30. εέδϡʔϧ…ʁ
    • ֓೦ਤͰͬ͘͟Γઆ໌͍ͨ͠

    View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. View Slide

  38. • ʮεέδϡʔϧͬͯΫϩʔδϟΛฒ΂ସ͍͑ͯΔ͚ͩͳͷͰ
    ͸ʁʯʮ͜͜Ͱ͸͋Δҙຯਖ਼ղͰ͢ʯ
    • (ࠓճ͸set/getDeferͷ࿩͸͠·ͤΜ)
    • ʢͪΌΜͱཧղ͢ΔͨΊʹίʔυΛಡΉͳΒɺreactPHPͳͲͷ
    ίʔυ͸ൺֱతಡΈ΍͍͢ʢSwoole͸CͳͷͰ…ʣʣ

    View Slide

  39. • Ͳ͔͜ΒͰ΋ࣗ༝ʹεΠον͞ΕΔ༁Ͱ͸ͳ͍
    • ओʹIO΍sleepͳͲɺ໭ͯ͠ҙຯ͕͋ΔॴͰ౉͞ΕΔ
    • ͦ͏͍͏;͏ʹSwoole͕औΓ࢓੾͍ͬͯΔ

    View Slide

  40. • JSΈ͍ͨʹؔ਺୯ҐͰࣗಈతʹ੾Γସ͑͞Εͳ͍ͷͰ஫ҙ
    • ʮͳΜ͔ίϧʔνϯ͕ಈ͔ΜʂແݶϧʔϓʂϩοΫʂʯͱ͍
    ͏࣌͸େମ͜Ε
    • ׳ΕΔ·Ͱ͸ࢥͬͨ௨Γͷ࣮ߦλΠϛϯάʢεέδϡʔϦϯ
    άʣʹͳΒͳ͍͜ͱ΋͋Δ
    • ඞཁͳΒɺखಈͰco::sleepͳͲΛೖΕͨΓ͢Δ
    • ׳ΕΔ·Ͱ͸ʮͳΜͰಈ͔ͳ͍Μͩ…ʯͱࢥ͏͜ͱ΋
    ->׳ΕΑ͏ʂ

    View Slide

  41. ·ͱΊ
    • ʮඇಉظ͸͋Μ·Γා͘ͳ͍ʯ
    • γϯϓϧʹॻ͖΍͘͢ಡΈ΍͍͢ͷ͕ʢSwooleͷʣ
    Coroutineʢओ؍ʣ
    • ͲΜͲΜAPIͳͲΛୟ͍ͯճΓ·͠ΐ͏ʂ

    View Slide

  42. ຊ౰ͷ(?)·ͱΊ
    • file_get_contentsͰे෼ͳΒɺͦ͏͠·͠ΐ͏
    • ʮfile_get_contentsͰ଎౓͕ͨΓͳ͍༻్ͱ͸…͏͝͝…ʯ
    • ʮඇಉظͰ͏·͘΍Ε͹ඵؒXXXXճୟ͘͜ͱ΋ເͰ͸ͳ
    ͍ʂʯ
    • → ࣄ݅ʹͳΔ
    • ʮඇಉظͱ͔ɺ୭͕ϝϯς͢ΔΜͩ…ʯ
    • ʢ ચ೴ ҭ੒͍ͯ͜͠͏ʣ

    View Slide

  43. ࠓ೔͸࿩͞ͳ͔࣮ͬͨࡍʹϋνϟϝνϟʹୟͨ͘
    Ίʹॏཁͳॴ
    • DNSΩϟογϡɺkeep-aliveɺλΠϜΞ΢τ&ϦτϥΠɺಈతε
    ϩοτϦϯάɺchanͳͲͰͷσʔλड͚౉͠ɺDefer
    • ʮຊ౰ʹඇಉظ͕ඞཁͳॴͱ͸Ͳ͔͜ʁʯ
    • ॏ͍݁Ռॲཧ͕ඞཁͳΒϚϧνίΞ͕׆͔ͤΔͷͰϚϧνϓ
    ϩηεͷ΄͏͕ྑ͍
    • ʮϚϧνϓϩηεʴඇಉظͩʂʯʮγϯϓϧͱ͸…ʯ

    View Slide

  44. go()͝ਗ਼ௌ͍͖ͨͩ͋Γ͕ͱ͏͍͟͝
    ·ͨ͠ɻ

    View Slide

  45. • ͕࣌ؒ༨Ε͹ҎԼ

    View Slide

  46. coroutine͕ಡΈ΍͍͢ɺͱ͸ʁ
    • ʢҎԼ࣮ࡍʹಈ͔͍ͯ͠ΔίʔυͰ͸ͳ͍Ͱ͕͢ʣ

    View Slide

  47. go(function () {
    $http = new Co\Http\Client("http://example.jp", 80);
    $http->get('/api.json');
    $data = json_decode($http->body);
    $id = $data[0]['id'];
    $http->get('/api.json?id='.$id);
    $data = json_decode($http->body);
    $child_id = $data[0]['child_id'];
    $http->get('/api.json?child_id='.$child_id);
    $data = json_decode($http->body);
    echo $data['title'];
    //->
    });

    View Slide

  48. $client = new Swoole\Http2\Client("example.jp", 80);
    $client->get("/", function ($o) use($client) {
    $data = json_decode($o->body);
    $id = $data[0]['id'];
    $client->get("/api.json?id=".$id, function ($o) use($client) {
    $data = json_decode($o->body);
    $child_id = $data[0]['child_id'];
    $client->get("/api.json?child_id=".$id, function ($o) use($client) {
    $data = json_decode($o->body);
    echo $data['title'];
    //--------->
    }
    }
    });

    View Slide

  49. 3ճϦΫΤετΛͳ͛Δͱ…
    # coro
    //-> (1Πϯσϯτ
    # cb
    //---------> (3Πϯσϯτ

    View Slide

  50. • ී௨ɺ͍͔ͭ͘ͷAPI΍DBΞΫηεΛॱ൪ʹߦ͏
    • coroutine͸ී௨(௚ྻ)ʹॻ͚Δ
    • ίʔϧόοΫํࣜ͸ωετ(ؔ਺Ͱ෼ׂ)͠ͳ͚Ε͹ͳΒͳ͍
    • PromiseΛ͔ͭ͑͹ฏୱʹ͸Ͱ͖Δ͕ɺείʔϓͷ෼ׂ͸͞Ε
    Δ

    View Slide

  51. see also
    • https:/
    /wiki.swoole.com/wiki/page/p-coroutinehttpclient.html
    • https:/
    /github.com/swoole/swoole-src/tree/master/examples/
    coroutine
    • https:/
    /wiki.swoole.com/wiki/page/752.html
    • https:/
    /wiki.swoole.com/wiki/page/784.html
    • https:/
    /github.com/eaglewu/swoole-ide-helper
    • https:/
    /www.swoole.com/
    • https:/
    /www.swoole.co.uk/docs/modules/swoole-async-http-client

    View Slide