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

Pushing the limits with ReactPHP (ScotlandPHP17)

Pushing the limits with ReactPHP (ScotlandPHP17)

It’s 2017 and times have changed – yet PHP is still most often associated with your average product catalogue or blogging platform. In this talk you will learn that PHP’s huge ecosystem has way more to offer and PHP is not inferior at all to its evil cousin Node.js.

You will learn about the core concepts of async PHP and why you too should care about ReactPHP being a real thing. The talk has a strong focus on sparking the idea that PHP can be way faster and more versatile than you probably thought. Bring along an open mind and through lots of examples and demos learn why what sounds crazy at first might soon be a valuable addition in your toolbox.

Christian Lück

November 04, 2017
Tweet

More Decks by Christian Lück

Other Decks in Programming

Transcript

  1. pushing the limits with ReactPHP
    why ReactPHP is awesome and why YOU should care
    ScotlandPHP

    View full-size slide

  2. Agenda
    - Hello!
    - PHP, the web of the ‘90s?
    - Enter React
    - Core components
    - Examples and demo time
    - Conclusions
    2

    View full-size slide

  3. $ whoami
    Christian Lück
    5

    View full-size slide

  4. $ whoami
    Christian Lueck
    6

    View full-size slide

  5. $ whoami
    Christian Lueck
    7

    View full-size slide

  6. $ whoami
    Christian Lueck
    @clue
    8

    View full-size slide

  7. $ whoami
    Christian Lueck
    @another_clue
    9

    View full-size slide

  8. $ whoami
    Christian Lueck
    @another_clue
    passionate about pushing the limits
    10

    View full-size slide

  9. $ whoami
    Christian Lueck
    @another_clue
    passionate about pushing the limits
    freelance software engineer 11

    View full-size slide

  10. Who are you?
    12
    now that you know me…

    View full-size slide

  11. Who are you?
    13
    now that you know me…
    - PHP developers?
    - architecs / engineers?

    View full-size slide

  12. Who are you?
    14
    now that you know me…
    - PHP developers?
    - architecs / engineers?
    - know React?

    View full-size slide

  13. The other React™
    16

    View full-size slide

  14. The REAL React™
    17

    View full-size slide

  15. PHP, the web of the ‘90s?
    18

    View full-size slide

  16. PHP and the web of the ‘90s
    - traditional LAMP stack
    - Request-Response-Cycle
    - PHP is too slow?
    19
    Apache
    Client PHP MySQL

    View full-size slide

  17. PHP and the web of the ‘90s
    - traditional LAMP stack
    - Request-Response-Cycle
    - PHP is too slow?
    - We sure can improve this…
    20
    Apache
    Client PHP MySQL

    View full-size slide

  18. PHP and the web of the ‘90s
    - traditional LAMP stack
    - Request-Response-Cycle
    - PHP is too slow?
    - We sure can improve this…
    21
    Apache
    Client PHP MySQL
    Apache
    Client
    FPM
    MySQL
    PHP
    PHP

    View full-size slide

  19. PHP and the web of the ‘90s
    - traditional LAMP stack
    - Request-Response-Cycle
    - PHP is too slow?
    - We sure can improve this…
    22
    Apache
    Client PHP MySQL
    Apache
    Client
    FPM
    MySQL
    PHP
    PHP
    nginx
    Client
    FPM
    MySQL
    PHP
    PHP

    View full-size slide

  20. PHP and the web of the ‘90s
    - traditional LAMP stack
    - Request-Response-Cycle
    - PHP is too slow?
    - We sure can improve this…
    23
    Apache
    Client PHP MySQL
    Apache
    Client
    FPM
    MySQL
    PHP
    PHP
    nginx
    Client
    FPM
    MySQL
    PHP
    PHP
    nginx
    Client
    FPM
    memcache
    PHP
    PHP
    MySQL

    View full-size slide

  21. PHP may not be pretty…
    24

    View full-size slide

  22. PHP may not be pretty…
    but it gets the job done!
    25

    View full-size slide

  23. Knock knock!
    Who’s there?
    26

    View full-size slide

  24. Knock knock!
    2017!
    Who’s there?
    27

    View full-size slide

  25. Knock knock!
    2017!
    - Separation of concerns
    (Frontend↔Backend)
    - HTTP APIs (RESTful)
    - Integration with 3rd parties
    - Live-Data (ticker)
    - CLI tools
    Who’s there?
    28

    View full-size slide

  26. Enter React!
    31

    View full-size slide

  27. What is React?
    32

    View full-size slide

  28. What is React?
    non-blocking I/O
    33

    View full-size slide

  29. What is React?
    non-blocking I/O
    event-driven
    34

    View full-size slide

  30. What is React?
    non-blocking I/O
    event-driven
    async
    35

    View full-size slide

  31. 100%
    pure PHP
    37

    View full-size slide

  32. 100%
    pure PHP
    no extensions
    38

    View full-size slide

  33. 100%
    pure PHP
    no extensions
    no magic
    39

    View full-size slide

  34. What does that even mean?!
    40

    View full-size slide

  35. the idea
    calculations are fast
    42

    View full-size slide

  36. the idea
    calculations are fast
    I/O is slow
    43

    View full-size slide

  37. I/O is everywhere
    44

    View full-size slide

  38. I/O is everywhere
    third party HTTP APIs (RESTful, SOAP, you name it…)
    45

    View full-size slide

  39. I/O is everywhere
    third party HTTP APIs (RESTful, SOAP, you name it…)
    mysql, postgres
    46

    View full-size slide

  40. I/O is everywhere
    third party HTTP APIs (RESTful, SOAP, you name it…)
    mysql, postgres
    filesystem I/O (session files)
    47

    View full-size slide

  41. I/O is everywhere
    third party HTTP APIs (RESTful, SOAP, you name it…)
    mysql, postgres
    filesystem I/O (session files)
    redis, memcache 48

    View full-size slide

  42. 49
    Source: Latency Numbers Every Programmer Should Know: https://gist.github.com/jboner/2841832
    CPU vs I/O

    View full-size slide

  43. I/O is slow!
    50

    View full-size slide

  44. I/O is slow!
    So why wait?
    51

    View full-size slide

  45. This is React
    52

    View full-size slide

  46. This is React
    53
    Start multiple I/O operations (non-blocking)

    View full-size slide

  47. This is React
    54
    Start multiple I/O operations (non-blocking)
    Get notified when something happens (react)

    View full-size slide

  48. This is React
    55
    Start multiple I/O operations (non-blocking)
    Get notified when something happens (react)
    Don’t waste time waiting

    View full-size slide

  49. What React is not
    56

    View full-size slide

  50. What React is not
    React is not black magic / vodoo
    57

    View full-size slide

  51. What React is not
    React is not black magic / vodoo
    React is not a framework
    58

    View full-size slide

  52. What React is not
    React is not black magic / vodoo
    React is not a framework
    React is not the new buzz
    59

    View full-size slide

  53. React core components
    60

    View full-size slide

  54. React Core components
    - Event loop (reactor)
    - Streams
    - Promises
    61

    View full-size slide

  55. Event loop
    Consumers
    - THE core, low-level component
    62

    View full-size slide

  56. Event loop
    Consumers
    - THE core, low-level component
    - Create an instance
    - Just use the Factory
    - Additional extensions for bigger payloads
    - something inbetween…
    - just pass the $loop around
    - Start running
    - keeps running forever
    - unless stopped or done
    63

    View full-size slide

  57. Event loop
    Consumers
    - THE core, low-level component
    - Create an instance
    - Just use the Factory
    - Additional extensions for bigger payloads
    - something inbetween…
    - just pass the $loop around
    - Start running
    - keeps running forever
    - unless stopped or done
    64
    $loop = Factory::create();
    // something inbetween
    // pass the $loop around to all components
    $loop->run();

    View full-size slide

  58. Event loop
    Implementors
    - Reactor pattern (hence the name)
    65

    View full-size slide

  59. Event loop
    Implementors
    - Reactor pattern (hence the name)
    - start timers
    - once
    - periodic
    - ticks
    66
    $loop->addTimer(0.5, function () {
    echo ‘world’;
    });
    $loop->addTimer(0.3, function () {
    echo ‘hello’;
    });

    View full-size slide

  60. Event loop
    Implementors
    - Reactor pattern (hence the name)
    - start timers
    - once
    - periodic
    - ticks
    - wait for stream resources to become
    - readable
    - writable
    67
    $loop->addTimer(0.5, function () {
    echo ‘world’;
    });
    $loop->addTimer(0.3, function () {
    echo ‘hello’;
    });
    $loop->addReadStream($stream, $fn);
    $loop->addWriteStream($stream, $fn);

    View full-size slide

  61. Streams
    - Process large strings in chunks as they happen (think downloads)
    - Types
    - Readable (e.g. STDIN pipe)
    - Writable (e.g. STDOUT pipe)
    - Duplex (e.g. TCP/IP connection)
    68

    View full-size slide

  62. Streams
    - interfaces, events and listeners:
    69
    $dest->write(‘hello’);
    $source->on(‘data’, function ($data) {
    var_dump($data);
    });
    $source->on(‘close’, function () {
    echo ‘stream closed’;
    });

    View full-size slide

  63. Streams
    - interfaces, events and listeners:
    70
    $dest->write(‘hello’);
    $source->on(‘data’, function ($data) {
    var_dump($data);
    });
    $source->on(‘close’, function () {
    echo ‘stream closed’;
    });
    $source->pipe($gunzip)->pipe($badwords)->pipe($dest);

    View full-size slide

  64. Promises
    - Placeholder for a single future result
    - Possible states:
    - pending
    - fulfilled (successfully resolved)
    - rejected (Exception occured)
    71

    View full-size slide

  65. Promises
    - no more imperative code flow
    - instead (tell, don’t ask)
    72
    $a->then($fulfilled = null, $rejected = null);
    $a->then(‘process’);
    $a->then(‘process’, ‘var_dump’);

    View full-size slide

  66. Examples and demo time!
    73

    View full-size slide

  67. Examples and demo time!
    All open source with links
    74

    View full-size slide

  68. Socket server
    75
    react/socket
    - THE canonical chat example
    - broadcast all incoming msgs

    View full-size slide

  69. Socket server
    76
    react/socket
    - THE canonical chat example
    - broadcast all incoming msgs
    - run example server
    - connect via telnet:
    $ telnet clue.engineering 6001

    View full-size slide

  70. HTTP client
    78
    clue/buzz-react
    - Simple HTTP requests
    - inspired by kriswallsmith/buzz
    - PSR-7 compatible

    View full-size slide

  71. HTTP client
    79
    clue/buzz-react
    - Simple HTTP requests
    - inspired by kriswallsmith/buzz
    - PSR-7 compatible
    - Promises and Streams
    - It’s fast…

    View full-size slide

  72. HTTP client
    80
    clue/buzz-react
    - Simple HTTP requests
    - inspired by kriswallsmith/buzz
    - PSR-7 compatible
    - Promises and Streams
    - It’s fast…
    - benchmarks in following slides about
    clue/docker-react

    View full-size slide

  73. Packagist API
    clue/packagist-api-react
    - get information about any
    Composer package
    - simple, Promise-based
    - lightweight wrapper between
    - KnpLabs/packagist-api
    - clue/buzz-react
    81

    View full-size slide

  74. Packagist API
    clue/packagist-api-react
    - get information about any
    Composer package
    - simple, Promise-based
    - lightweight wrapper between
    - KnpLabs/packagist-api
    - clue/buzz-react
    82
    - see its examples
    $ php examples/search.php

    View full-size slide

  75. Docker client
    clue/docker-react
    - Run apps in isolated containers
    - “build, ship and run, anywhere”
    - Controlled through HTTP API
    - Promises and Streams
    83

    View full-size slide

  76. Docker client
    clue/docker-react
    - Run apps in isolated containers
    - “build, ship and run, anywhere”
    - Controlled through HTTP API
    - Promises and Streams
    84
    - see its promise examples
    $ php examples/info.php
    - see its streaming examples
    $ php examples/benchmark-exec.php

    View full-size slide

  77. 700 MiB/s
    87
    dockerd maxed out
    PHP not

    View full-size slide

  78. HTTP server
    react/http
    - Pure PHP, with
    no additional webserver
    - standard PSR-7 interfaces
    88

    View full-size slide

  79. HTTP server
    react/http
    - Pure PHP, with
    no additional webserver
    - standard PSR-7 interfaces
    - Lots of third-party integrations
    with traditional frameworks
    (symfony, slim, silex, PIMF etc.)
    89

    View full-size slide

  80. 5k requests/s
    90

    View full-size slide

  81. 5k requests/s
    91

    View full-size slide

  82. 5k requests/s
    92
    this is a local single core benchmark!

    View full-size slide

  83. 5k requests/s
    93
    this is a local single core benchmark!
    dual core i3 => 10k requests/s

    View full-size slide

  84. 5k requests/s
    94
    this is a local single core benchmark!
    dual core i3 => 10k requests/s
    36M requests/h

    View full-size slide

  85. Server sent events
    clue/sse-react
    - Server sent events (SSE)
    - aka. EventSource (browser API)
    - Streaming events to browser
    - limited browser support
    95

    View full-size slide

  86. Server sent events
    clue/sse-react
    - Server sent events (SSE)
    - aka. EventSource (browser API)
    - Streaming events to browser
    - limited browser support
    96
    - see examples connecting to initial chat
    $ php examples/chat-server.php
    - open browser:
    http://clue.engineering:7000/

    View full-size slide

  87. Websocket server
    cboden/ratchet
    - Async WebSocket server
    - bidirectional data flow between
    browser and server
    - better browser support
    98

    View full-size slide

  88. Redis client
    99
    clue/redis-react
    - Redis is a fast in-memory DB
    - very simple commands
    - very simple protocol
    - pipelined, Promise-based

    View full-size slide

  89. Redis client
    100
    clue/redis-react
    - Redis is a fast in-memory DB
    - very simple commands
    - very simple protocol
    - pipelined, Promise-based
    - see its examples
    $ php examples/incr.php

    View full-size slide

  90. Redis server
    101

    View full-size slide

  91. Redis server
    102
    - Official Redis is written in C

    View full-size slide

  92. Redis server
    103
    clue/php-redis-server
    - Official Redis is written in C
    - Reimplementation is pure PHP

    View full-size slide

  93. Redis server
    104
    clue/php-redis-server
    - Official Redis is written in C
    - Reimplementation is pure PHP
    - Very simple to add commands

    View full-size slide

  94. Redis server
    105
    clue/php-redis-server
    - Official Redis is written in C
    - Reimplementation is pure PHP
    - Very simple to add commands
    - How fast could PHP possibly be?
    Let’s see…

    View full-size slide

  95. Redis server
    106
    clue/php-redis-server
    - Official Redis is written in C
    - Reimplementation is pure PHP
    - Very simple to add commands
    - How fast could PHP possibly be?
    Let’s see…
    - see its bin
    $ php bin/redis-server.php
    - test via clue/redis-react
    - test via official redis CLI
    - run official redis benchmark during talk:
    - official server: ~90k OP/s

    View full-size slide

  96. 50k OP/s
    pure PHP
    who needs native code anyway?
    109

    View full-size slide

  97. Redis framework
    110
    clue/php-redis-framework
    - Development preview
    - Very simple to add custom
    commands

    View full-size slide

  98. Redis framework
    111
    clue/php-redis-framework
    - Development preview
    - Very simple to add custom
    commands
    - run example server
    $ php examples/11-beer.php
    - connect via telnet:
    $ telnet IP 9000

    View full-size slide

  99. Quassel
    clue/quassel-react
    - Quassel IRC core
    - event-driven IRC chatbots
    - re-using existing identity
    113

    View full-size slide

  100. Zenity
    clue/zenity-react
    - PHP desktop GUI applications
    - very simple, Promise-based
    115

    View full-size slide

  101. Zenity
    clue/zenity-react
    - PHP desktop GUI applications
    - very simple, Promise-based
    116
    - see its simple examples
    $ php examples/01-dialog.php
    - see its more realistic examples
    $ php examples/06-menu.php
    $ php examples/03-progress-pulsate.php
    $ php examples/03-progress-random.php

    View full-size slide

  102. many, MANY more third-party projects:
    https://github.com/reactphp/react/wiki/Users
    120

    View full-size slide

  103. Conclusions
    121

    View full-size slide

  104. PHP
    faster than you probably thought
    123

    View full-size slide

  105. PHP
    faster than you probably thought
    more versatile than you probably thought
    124

    View full-size slide

  106. ReactPHP
    126
    a real deal and here to stay

    View full-size slide

  107. ReactPHP
    127
    a real deal and here to stay
    stable & production ready

    View full-size slide

  108. ReactPHP
    128
    a real deal and here to stay
    stable & production ready
    *awesome*

    View full-size slide

  109. try!
    whenever having to wait
    130

    View full-size slide

  110. try!
    whenever having to wait
    whenever accessing network
    131

    View full-size slide

  111. Need help? Want to help?
    - check each component’s README
    - check open issues
    132

    View full-size slide

  112. Need help? Want to help?
    - check each component’s README
    - check open issues
    - join #reactphp on irc.freenode.org
    - tweet @ReactPHP or #reactphp
    133

    View full-size slide

  113. Need help? Want to help?
    - check each component’s README
    - check open issues
    - join #reactphp on irc.freenode.org
    - tweet @ReactPHP or #reactphp
    - Talk to me
    134

    View full-size slide

  114. Need help? Want to help?
    - check each component’s README
    - check open issues
    - join #reactphp on irc.freenode.org
    - tweet @ReactPHP or #reactphp
    - Talk to me
    Did I mention I’m available?
    135

    View full-size slide

  115. // thank you!
    $loop->stop();
    136
    @another_clue – https://lueck.tv/

    View full-size slide

  116. // thank you!
    $loop->stop();
    137
    @another_clue – https://lueck.tv/
    Feedback?
    https://joind.in/talk/21f76

    View full-size slide

  117. Avoid blocking!
    - The loop must not be blocked
    138

    View full-size slide

  118. Avoid blocking!
    - The loop must not be blocked
    - Many functions / lib assume blocking by default
    - Anything >1ms should be reconsidered
    139

    View full-size slide

  119. Avoid blocking!
    - The loop must not be blocked
    - Many functions / lib assume blocking by default
    - Anything >1ms should be reconsidered
    - Alternatives
    - Single result: Promises
    - Evented: Streams
    140

    View full-size slide

  120. Avoid blocking!
    - The loop must not be blocked
    - Many functions / lib assume blocking by default
    - Anything >1ms should be reconsidered
    - Alternatives
    - Single result: Promises
    - Evented: Streams
    - Need a blocking function?
    - Fork off!
    - Use IPC
    141

    View full-size slide

  121. Avoid blocking!
    - The loop must not be blocked
    - Many functions / lib assume blocking by default
    - Anything >1ms should be reconsidered
    - Alternatives
    - Single result: Promises
    - Evented: Streams
    - Need a blocking function?
    - Fork off!
    - Use IPC
    142
    Pay attention:
    - PDO, mysql etc.
    - file system access
    - network access
    - third-party APIs

    View full-size slide

  122. Integration with traditional environments
    143
    integrating async into sync is easy

    View full-size slide

  123. Integration with traditional environments
    144
    integrating async into sync is easy
    - just run the loop until you’re done
    - see clue/block-react

    View full-size slide

  124. Integration with traditional environments
    145
    integrating async into sync is easy
    - just run the loop until you’re done
    - see clue/block-react
    integrating sync into async is hard

    View full-size slide

  125. Integration with traditional environments
    146
    integrating async into sync is easy
    - just run the loop until you’re done
    - see clue/block-react
    integrating sync into async is hard
    - often requires async rewrite
    - consider forking instead

    View full-size slide