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

Pushing the limits of PHP (SymfonyLive Berlin)

Christian Lück
September 27, 2019

Pushing the limits of PHP (SymfonyLive Berlin)

It's 2019 and times have changed – yet PHP is still most often associated with your average product catalog 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 interesting examples and live demos learn why what sounds crazy at first might soon be a valuable addition in your toolbox.

Christian Lück

September 27, 2019
Tweet

More Decks by Christian Lück

Other Decks in Programming

Transcript

  1. pushing the limits of PHP
    @another_clue

    View Slide

  2. pushing the limits of PHP
    why ReactPHP is awesome and why YOU should care
    @another_clue

    View Slide

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

    View Slide

  4. Hello!
    4

    View Slide

  5. $ whoami
    5

    View Slide

  6. $ whoami
    Christian Lück
    6

    View Slide

  7. $ whoami
    Christian Lück
    7

    View Slide

  8. $ whoami
    Christian Lueck
    8

    View Slide

  9. $ whoami
    Christian Lueck
    9

    View Slide

  10. $ whoami
    Christian Lueck
    @clue
    10

    View Slide

  11. $ whoami
    Christian Lueck
    @another_clue
    11

    View Slide

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

    View Slide

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

    View Slide

  14. Who are you?
    14
    now that you know me…

    View Slide

  15. Who are you?
    15
    now that you know me…
    - PHP developers?
    - architects / engineers?

    View Slide

  16. Who are you?
    16
    now that you know me…
    - PHP developers?
    - architects / engineers?
    - know React?

    View Slide

  17. PHP, the web of the ‘90s?
    17

    View Slide

  18. PHP and the web of the ‘90s
    18

    View Slide

  19. PHP and the web of the ‘90s
    19
    Apache
    Client PHP MySQL

    View Slide

  20. PHP and the web of the ‘90s
    traditional LAMP stack
    20
    Apache
    Client PHP MySQL

    View Slide

  21. PHP and the web of the ‘90s
    traditional LAMP stack
    Request-Response-Cycle
    21
    Apache
    Client PHP MySQL

    View Slide

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

    View Slide

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

    View Slide

  24. PHP and the web of the ‘90s
    traditional LAMP stack
    Request-Response-Cycle
    PHP is too slow? 24
    nginx
    Client MySQL
    FPM
    PHP
    PHP

    View Slide

  25. PHP and the web of the ‘90s
    traditional LAMP stack
    Request-Response-Cycle
    PHP is too slow? 25
    nginx
    Client
    FPM
    PHP
    PHP memcache
    MySQL

    View Slide

  26. PHP may not be pretty…
    26

    View Slide

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

    View Slide

  28. Knock knock!
    Who’s there?
    28

    View Slide

  29. Knock knock!
    2019!
    Who’s there?
    29

    View Slide

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

    View Slide

  31. Node.js
    31

    View Slide

  32. Node.js
    32
    good fit, huge ecosystem

    View Slide

  33. Node.js
    33
    good fit, huge ecosystem
    interesting concepts

    View Slide

  34. Node.js
    34
    good fit, huge ecosystem
    interesting concepts
    npm install…

    View Slide

  35. nodejs?
    35

    View Slide

  36. no js!
    36

    View Slide

  37. Everybody’s favorite language…
    37

    View Slide

  38. PHP
    38

    View Slide

  39. PHP
    39
    gets the job done

    View Slide

  40. PHP
    40
    gets the job done
    widespread usage

    View Slide

  41. PHP
    41
    gets the job done
    widespread usage
    if PHP can do it…

    View Slide

  42. Enter React!
    42

    View Slide

  43. 43

    View Slide

  44. The other React™
    44

    View Slide

  45. The REAL React™
    45

    View Slide

  46. 46

    View Slide

  47. What is React?
    47

    View Slide

  48. What is React?
    non-blocking I/O
    48

    View Slide

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

    View Slide

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

    View Slide

  51. 100%
    51

    View Slide

  52. 100%
    pure PHP
    52

    View Slide

  53. 100%
    pure PHP
    no extensions
    53

    View Slide

  54. 100%
    pure PHP
    no extensions
    no magic
    54

    View Slide

  55. What does that even mean?!
    55

    View Slide

  56. the idea
    56

    View Slide

  57. calculations are fast
    57
    the idea

    View Slide

  58. calculations are fast
    I/O is slow
    58
    the idea

    View Slide

  59. I/O is everywhere
    59

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  65. I/O is slow!
    65

    View Slide

  66. I/O is slow!
    So why wait?
    66

    View Slide

  67. This is React
    67

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  71. What React is not
    71

    View Slide

  72. What React is not
    React is not black magic / vodoo
    72

    View Slide

  73. What React is not
    React is not black magic / vodoo
    React is not a framework
    73

    View Slide

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

    View Slide

  75. React core components
    75

    View Slide

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

    View Slide

  77. Event loop
    Consumers
    - THE core, low-level component
    77

    View Slide

  78. 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
    78

    View Slide

  79. 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
    79
    $loop = Factory::create();
    // something inbetween
    // pass the $loop around to all components
    $loop->run();

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  83. 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)
    83

    View Slide

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

    View Slide

  85. Streams
    - interfaces, events and listeners:
    85
    $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 Slide

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

    View Slide

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

    View Slide

  88. Examples and demo time!
    88

    View Slide

  89. Examples and demo time!
    All open source with links
    89

    View Slide

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

    View Slide

  91. Socket server
    91
    react/socket
    - THE canonical chat example
    - broadcast all incoming msgs
    - run example server
    - connect via telnet:
    $ telnet live.clue.engineering 8000

    View Slide

  92. 92

    View Slide

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

    View Slide

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

    View Slide

  95. HTTP client
    95
    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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  100. 2400 MB/s
    100

    View Slide

  101. 2400 MB/s
    101

    View Slide

  102. 2400 MB/s
    102
    dockerd maxed out
    PHP not

    View Slide

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

    View Slide

  104. HTTP server
    react/http
    - Pure PHP, with
    no additional webserver
    - standard PSR-7 interfaces
    - Lots of third-party integrations
    with traditional frameworks
    (Symfony, Slim etc.)
    104

    View Slide

  105. 11k requests/s
    105

    View Slide

  106. 11k requests/s
    106

    View Slide

  107. 11k requests/s
    107
    this is a local, single core benchmark!

    View Slide

  108. 11k requests/s
    108
    this is a local, single core benchmark!
    quad core i7 + HT => ~88k requests/s

    View Slide

  109. 11k requests/s
    109
    this is a local, single core benchmark!
    quad core i7 + HT => ~88k requests/s
    40M requests/h (single core)

    View Slide

  110. 11k requests/s
    110
    this is a local, single core benchmark!
    quad core i7 + HT => ~88k requests/s
    40M requests/h (single core)
    ~300M requests/h

    View Slide

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

    View Slide

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

    View Slide

  113. 113

    View Slide

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

    View Slide

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

    View Slide

  116. Redis client
    116
    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 Slide

  117. Redis server
    117

    View Slide

  118. Redis server
    118
    - Official Redis is written in C

    View Slide

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

    View Slide

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

    View Slide

  121. Redis server
    121
    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 Slide

  122. Redis server
    122
    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: ~150k OP/s

    View Slide

  123. 100k OP/s
    123

    View Slide

  124. 100k OP/s
    124

    View Slide

  125. 100k OP/s
    pure PHP
    125

    View Slide

  126. 100k OP/s
    pure PHP
    who needs native code anyway?
    126

    View Slide

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

    View Slide

  128. Redis framework
    128
    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 Slide

  129. 129

    View Slide

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

    View Slide

  131. 131

    View Slide

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

    View Slide

  133. Zenity
    clue/zenity-react
    - PHP desktop GUI applications
    - very simple, Promise-based
    133
    - 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 Slide

  134. 134

    View Slide

  135. 135

    View Slide

  136. 136

    View Slide

  137. BunnyPHP
    bunny/bunny
    - AMQP (RabbitMQ)
    - job worker processes
    - run slow things in background
    137

    View Slide

  138. no polling
    138

    View Slide

  139. no polling
    139
    jobs instantly picked up

    View Slide

  140. no polling
    140
    jobs instantly picked up
    thousands of jobs per second

    View Slide

  141. no polling
    141
    jobs instantly picked up
    thousands of jobs per second
    concurrently processing hundreds or more

    View Slide

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

    View Slide

  143. Conclusions
    143

    View Slide

  144. 144
    Can I use ReactPHP to make my website 1000x faster?

    View Slide

  145. YES
    145
    Can I use ReactPHP to make my website 1000x faster?

    View Slide

  146. YES
    146
    But you might be missing the point…
    Can I use ReactPHP to make my website 1000x faster?

    View Slide

  147. PHP
    147

    View Slide

  148. PHP
    faster than you probably thought
    148

    View Slide

  149. PHP
    faster than you probably thought
    more versatile than you probably thought
    149

    View Slide

  150. ReactPHP
    150

    View Slide

  151. ReactPHP
    151
    a real deal and here to stay

    View Slide

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

    View Slide

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

    View Slide

  154. try!
    154

    View Slide

  155. try!
    whenever having to wait
    155

    View Slide

  156. try!
    whenever having to wait
    whenever accessing network
    156

    View Slide

  157. help!
    157

    View Slide

  158. help!
    elaborate documentation on ReactPHP.org
    158

    View Slide

  159. help!
    elaborate documentation on ReactPHP.org
    tweet @ReactPHP or #reactphp
    159

    View Slide

  160. help!
    elaborate documentation on ReactPHP.org
    tweet @ReactPHP or #reactphp
    Talk to me
    160

    View Slide

  161. help!
    elaborate documentation on ReactPHP.org
    tweet @ReactPHP or #reactphp
    Talk to me
    Did I mention I’m available? 161

    View Slide

  162. // thank you!
    $loop->stop();
    162
    @another_clue – https://clue.engineering/

    View Slide

  163. integration
    163

    View Slide

  164. integration
    non-blocking and blocking don’t mix well
    164

    View Slide

  165. integration
    non-blocking and blocking don’t mix well
    decide for either approach
    165

    View Slide

  166. integration
    non-blocking and blocking don’t mix well
    decide for either approach
    isolate & communicate
    166

    View Slide

  167. Integration with traditional environments
    167
    integrating async into sync is easy

    View Slide

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

    View Slide

  169. Integration with traditional environments
    169
    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 Slide

  170. Integration with traditional environments
    170
    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 Slide

  171. Avoid blocking!
    - The loop must not be blocked
    171

    View Slide

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

    View Slide

  173. 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
    173

    View Slide

  174. 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
    174

    View Slide

  175. 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
    175
    Pay attention:
    - PDO, mysql etc.
    - file system access
    - network access
    - third-party APIs

    View Slide