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

Tirer le maximum du moteur PHP 7 - l'exemple de...

Tirer le maximum du moteur PHP 7 - l'exemple de Symfony

PHP 7.0 est déjà de l'histoire ancienne. Mais savez-vous en tirer partie à fond ? Si le moteur est plus rapide sur toutes les opérations en général, il y en a quelques unes qui sont particulièrement optimisées. Avec PHP 5, vous avez peut-être pris certains réflexes qui ne sont plus d'actualité, pour soi-disant écrire du code plus performant ? Je vous propose de passer en revues les différentes techniques d'optimisation mises en place dans Symfony, qui font de la v4 la plus rapide jamais publiée. Ce sera l'occasion de tordre le coup à quelques idées reçues, et de vous en donner quelques autres pour le jour où vous chercherez à presser les dernières millisecondes hors de cette boucle intensive. Benchmark à l'appui évidement.

Nicolas Grekas

March 30, 2018
Tweet

More Decks by Nicolas Grekas

Other Decks in Technology

Transcript

  1. • Born in 1995 – v7 end of 2016 •

    870,000 C lines of code • Distributed leadership The PHP engine
  2. Synchronous and parallel Master Child 1 Child 2 Child n

    index.php index.php index.php index.php index.php index.php PHP’s memory manager insulates each scripts
  3. First steps are immutable index.php Lexing + parsing AST opcodes

    Compiling Executing result Shared memory* *append-only
  4. Compile time optimizations AST opcodes Compiling Shared memory • Compile-time

    evaluation 'foo'."bar" • Dead-code elimination if (false) {…}
  5. Compile time optimizations AST opcodes Compiling Shared memory • Compile-time

    evaluation 'foo'."bar" • Dead-code elimination if (false) {…} • Interned strings "foobar" len=6 hash=Ox1234 • Immutable arrays [123, ["ab" => 34]] len=2 len=1
  6. Compile time optimizations AST opcodes Compiling Shared memory • Compile-time

    evaluation 'foo'."bar" • Dead-code elimination if (false) {…} • Interned strings "foobar" len=6 hash=Ox1234 • Immutable arrays [123, ["ab" => 34]] len=2 len=1
  7. • Works for constants 'cli' === PHP_SAPI • Works for

    some native functions 1 === count([123]) • Needs fully-qualified identifiers namespace App; \count([123]); Compile time evaluation
  8. namespace App; is_array($a); \is_array($a); Compile time inlining https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/3048 strlen(), is_{type}(),

    {type}val() casts, defined(), chr(), ord(), call_user_function(), call_user_function_array(), get_class(), get_called_class(), gettype(), count(), in_array(), array_slice(), func_num_args(), func_get_args(), function_exists(), is_callable(), extension_loaded(), constant(), dirname()
  9. Runtime-resolved identifiers are cached in the (local) opcode array Don’t

    « \ » all function calls Stick to the short list
  10. Let’s split the container in one file per service PHP

    7 is slow… at compiling https://github.com/symfony/symfony/pull/23678
  11. • Loading opcodes is really fast • Still takes time

    and memory • « require » is also really fast opcodes move from shared memory to process’ https://github.com/symfony/symfony/pull/23678
  12. • Shared memory is read-only $a = […]; $a[0] =

    123; • Duplication happens on « write » $a = "abc"; $b = $a . "def"; $c = $b . "ghi"; (by the way, scalars are free, and declared properties make objects very compact) https://blog.blackfire.io/php-7-performance-improvements-ints-floats-free.html ❤ Copy-on-write
  13. • gc_collect_cycles() autotriggered past 10k objects • gc_mem_caches() PHP7 memory

    manager is lazy • Much improved in PHP 7.3 PHP garbage collector
  14. • Coalesce operator A ?? B vs isset(A) ? A

    : B https://github.com/symfony/symfony/pull/26161 • Ropes for encapsed strings "$a and $b" vs $a." and ".$b https://blog.blackfire.io/php-7-performance-improvements-encapsed-strings-optimization.html • Packed arrays (incrementing keys only) https://blog.blackfire.io/php-7-performance-improvements-packed-arrays.html • Class constants can be slow https://github.com/symfony/symfony/pull/25474 - https://github.com/twigphp/Twig/pull/2636 More goodies
  15. • Reference mismatches are gone https://blog.blackfire.io/php-7-performance-improvements-references-mismatch.html • Copy-on-write is not

    triggered by (string)/(array) cast • Since PHP 7.2, « switch » statements use a hashmap • JIT is actively worked on for PHP 8 (no ETA) Even more goodies
  16. Conclusion • Wow PHP 7 • Source ideas in PHP’s

    C • Use only in tight loops • Never stop measuring