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

InspiringCon14: ElePHPants on speed: Running TYPO3 Flow on HipHop VM

InspiringCon14: ElePHPants on speed: Running TYPO3 Flow on HipHop VM

License: CC BY-SA

The rise of increasingly complex PHP frameworks and applications in the past few years has also changed the requirements that are put on the performance of the PHP interpreter itself – a field in which PHP as an interpreted language has always had a conceptual disadvantage in comparison to compiled languages.

A common approach to optimize the performance of PHP applications is the use of opcode caches like APC or OpCache, which cache the interpreter-generated byte code. A different solution is provided by HipHop VM, which implements a just-in-time compiler that translates PHP code into native machine code.

This talk aims at exploring if and how the current state of HHVM can be used to run TYPO3 Flow applications like TYPO3 Neos, what limitations need to be considered and what performance gains can be achieved in comparison to the traditional Zend Engine in conjunction with various opcode caches.

Martin Helmich

March 28, 2014
Tweet

More Decks by Martin Helmich

Other Decks in Programming

Transcript

  1. ElePHPants on speed

    Running TYPO3 Flow on HipHop VM

    Inspiring Conference, March 28th 2014
    Martin Helmich, Mittwald CM Service

    [email protected]
    Photo: George Lamson, CC BY-NC-SA

    http://www.flickr.com/photos/lamsongf/6415913075/

    View Slide

  2. YOUR SPEAKER
    Martin Helmich
    Software architect at Mittwald
    TYPO3 addicted since 2004

    Caffeine addicted since 2007

    View Slide

  3. Sebastian Bergmann, CC BY-SA

    http://www.flickr.com/photos/sebastian_bergmann/2337231691/

    View Slide

  4. Lexing
    Parsing
    Compilation
    Execution
    PHP execution,

    traditional

    View Slide

  5. !
    $locations = [
    0 => "Kolbermoor",
    1 => "Espelkamp",
    2 => "Las Vegas"
    ];
    !
    $currentLoc = 0;
    $currentLocName = $locations[$currentLoc];
    !
    if ($currentLoc === 2) {
    $greeting = "%s, baby!";
    } else {
    $greeting = "Hello %s!";
    }
    !
    echo sprintf($greeting, $currentLocName) . "\n";
    Lexing
    Parsing
    Compilat
    Executio

    View Slide

  6. T_OPEN_TAG
    T_VARIABLE
    T_LNUMBER
    T_DOUBLE_

    ARROW
    T_CONSTANT_ENCAPSED_STRING
    T_IF
    T_ELSE
    T_ECHO
    T_STRING
    Lexing
    Parsing
    Compilat
    Executio
    !
    $locations = [
    0 => "Kolbermoor",
    1 => "Espelkamp",
    2 => "Las Vegas"
    ];
    !
    $currentLoc = 0;
    $currentLocName = $locations[$currentLoc];
    !
    if ($currentLoc === 2) {
    $greeting = "%s, baby!";
    } else {
    $greeting = "Hello %s!";
    }
    !
    echo sprintf($greeting, $currentLocName) . "\n";

    View Slide

  7. Lexing
    Parsing
    Compilat
    Executio
    Variable

    assignment
    Array

    constructor
    Array

    accessor
    Constant
    Conditional

    statement
    Boolean

    expression
    Function

    call
    Print

    statement
    !
    $locations = [
    0 => "Kolbermoor",
    1 => "Espelkamp",
    2 => "Las Vegas"
    ];
    !
    $currentLoc = 0;
    $currentLocName = $locations[$currentLoc];
    !
    if ($currentLoc === 2) {
    $greeting = "%s, baby!";
    } else {
    $greeting = "Hello %s!";
    }
    !
    echo sprintf($greeting, $currentLocName) . "\n";

    View Slide

  8. Lexing
    Parsing
    Compilat
    Executio
    compiled vars: !0 = $locations, !1 = $currentLocationId, !2 = $currentLocationName,
    !3 = $greetingTemplate
    line # * op fetch ext return operands
    ----------------------------------------------------------------
    4 0 > EXT_STMT
    1 INIT_ARRAY ~0 'Kolbermoor', 0
    5 2 ADD_ARRAY_ELEMENT ~0 'Espelkamp', 1
    7 3 ADD_ARRAY_ELEMENT ~0 'Las+Vegas', 2
    4 ASSIGN !0, ~0
    9 5 EXT_STMT
    6 ASSIGN !1, 0
    10 7 EXT_STMT
    8 FETCH_DIM_R $3 !0, !1
    9 ASSIGN !2, $3
    12 10 EXT_STMT
    11 IS_IDENTICAL ~5 !1, 2
    12 > JMPZ ~5, ->16
    13 13 > EXT_STMT
    14 ASSIGN !3, '%25s%2C+baby%21'
    14 15 > JMP ->18
    15 16 > EXT_STMT
    17 ASSIGN !3, 'Hello+%25s%21'
    18 18 > EXT_STMT
    19 EXT_FCALL_BEGIN
    20 SEND_VAR !3
    21 SEND_VAR !2
    22 DO_FCALL 2 $8 'sprintf'
    23 EXT_FCALL_END
    24 CONCAT ~9 $8, '%0A'
    25 ECHO ~9
    19 26 > RETURN 1
    !

    View Slide

  9. Lexing
    Parsing
    Compilat
    Executio

    View Slide

  10. Lexing
    Parsing
    Compilation
    Execution
    PHP execution,

    traditional

    View Slide

  11. Lexing
    Parsing
    Compilation
    Execution
    Opcode

    Cache
    PHP

    opcodes
    PHP execution,

    opcode cache
    opcodes executed

    by PHP interpreter

    View Slide

  12. Lexing
    Parsing
    Compilation
    Execution
    HipHop

    bytecode
    JIT

    compiler
    HipHop

    intermediate

    representation
    Code

    repository
    x86-64/arm

    machine code
    PHP execution,

    HipHop VM
    executed as

    native machine code
    AST
    https://www.facebook.com/notes/facebook-engineering/the-hiphop-virtual-machine/10150415177928920

    http://www.hhvm.com/blog/2027/faster-and-cheaper-the-evolution-of-the-hhvm-jit

    View Slide

  13. $whatAmI = "Dynamic typization is great!";
    !
    if ($whatAmI > 0) {
    $whatAmI = [
    "But in many PHP programs,",
    "this is not excessively used."
    ];
    } else {
    $whatAmI = FALSE;
    }

    View Slide

  14. !
    $locations = [
    0 => "Kolbermoor",
    1 => "Espelkamp",
    2 => "Las Vegas"
    ];
    !
    $currentLoc = 0;
    $currentLocName = $locations[$currentLoc];
    !
    if ($currentLoc === 2) {
    $greeting = "%s, baby!";
    } else {
    $greeting = "Hello %s!";
    }
    !
    echo sprintf($greeting, $currentLocName) . "\n";
    Array of

    strings
    Integer
    String

    View Slide

  15. How to install
    wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | apt-key add -
    echo deb http://dl.hhvm.com/debian wheezy main | tee /etc/apt/sources.list.d/hhvm.list
    sudo apt-get update
    sudo apt-get install hhvm
    https://github.com/facebook/hhvm/wiki/Prebuilt-Packages-on-Debian-7

    View Slide

  16. View Slide

  17. Running TYPO3 Flow

    on HHVM

    View Slide

  18. One does not simply

    run TYPO3 Flow on
    HHVM.
    Flore Allemandou, CC BY-NC-SA

    http://www.flickr.com/photos/flore_frmoz/5031037626/

    View Slide

  19. View Slide

  20. View Slide

  21. TYPO3.Flow/Classes/.../Core/Bootstrap.php ---|+++++++
    TYPO3.Flow/Classes/.../Error/ErrorHandler.php -|+
    TYPO3.Flow/Classes/.../Http/Headers.php |+++++
    TYPO3.Flow/Classes/.../Mvc/Routing/ObjectPathMappingRepository.php -----|++++
    TYPO3.Flow/Classes/.../Object/Configuration/ConfigurationArgument.php --|++++++++
    TYPO3.Flow/Classes/.../Object/Configuration/ConfigurationProperty.php --|++++++++
    TYPO3.Flow/Classes/.../Package/Package.php -|+
    TYPO3.Flow/Classes/.../Security/AccountRepository.php -----|++++
    TYPO3.Flow/Classes/.../Security/Policy/Role.php -|+++++
    TYPO3.Flow/Classes/.../Security/Policy/RoleRepository.php -----|+++++++
    TYPO3.Flow/Classes/.../Utility/Unicode/TextIterator.php -|+++++
    TYPO3.Party/Classes/TYPO3/Party/Domain/Repository/PartyRepository.php -|+++
    doctrine/dbal/lib/.../Driver/PDOConnection.php |+++++++++++++++++++++++++++++++++++++++
    doctrine/dbal/lib/.../Driver/PDOStatement.php -|+++++++++++++++++++++++++++++++++++++++
    Web/index.php |++
    TYPO3.Media/Classes/.../Domain/Model/Image.php -|++++
    TYPO3.Media/Classes/.../Domain/Model/ImageVariant.php -|++++
    TYPO3.Setup/Classes/.../Core/BasicRequirements.php -|
    TYPO3.Setup/Classes/.../Core/RequestHandler.php |+++
    TYPO3.TYPO3CR/Classes/.../Migration/Command/NodeCommandController.php -|+++++
    imagine/imagine/lib/.../Filter/Basic/Resize.php --|++
    imagine/imagine/lib/.../Filter/Basic/Thumbnail.php --|++
    Doctrine issue #372 (https://github.com/doctrine/dbal/pull/373),

    backported to 2.3
    Hacks around various HHVM glitches

    View Slide

  22. TYPO3 Flow 2.1
    Unit tests, PHP 5.5
    Tests: 4186, Assertions: 10145, Failures: 1, Incomplete: 1, Skipped: 95
    Unit tests, HHVM

    (with compatibility patches)
    Tests: 4186, Assertions: 10057, Failures: 14, Errors: 21, Incomplete: 1, Skipped: 95
    99,98 %
    99,14 %

    View Slide

  23. Configuration/Production.hdf
    Server {
    SourceRoot = /var/www/my-flow-site/Web
    DefaultDocument = index.php
    Port = 9000
    ThreadCount = 100
    }


    Eval {
    Jit = true
    }
    !
    VirtualHost {
    my-flow-site {
    Pattern = .*
    ServerVariables {
    FLOW_REWRITEURLS = 1
    FLOW_CONTEXT = Production
    }

    View Slide

  24. Server {
    SourceRoot = /var/www/my-flow-site/Web
    DefaultDocument = index.php
    Port = 9000
    ThreadCount = 100
    }


    Eval {
    Jit = true
    }
    !
    VirtualHost {
    my-flow-site {
    Pattern = .*
    ServerVariables {
    FLOW_REWRITEURLS = 1
    FLOW_CONTEXT = Production
    }
    RewriteRules {
    persistentresources {
    pattern = ^/?(_Resources/Persistent/.{40})/.+(\..+)
    to = $1$2
    }
    !
    index {
    pattern = ^(.*)
    to = index.php/$1
    qsa = true
    }
    }
    }
    }
    !
    StaticFile {
    Extensions {
    css = text/css
    js = text/javascript
    png = image/png
    jpg = image/jpeg
    }
    }

    View Slide

  25. TYPO3:
    Flow:
    core:
    phpBinaryPathAndFilename: /usr/bin/hhvm
    subRequestPhpIniPathAndFilename: false
    Configuration/Settings.yaml

    (configured for speed)
    Use HHVM on sub-requests, too

    for even more performance.
    Nico Kaiser, CC BY

    http://www.flickr.com/photos/nicokaiser/6070496071/

    View Slide

  26. TYPO3:
    Flow:
    core:
    phpBinaryPathAndFilename: /usr/bin/php
    subRequestPhpIniPathAndFilename: /etc/php5/cli/php.ini
    Always specify a php.ini or “false”.

    Automatic detection will fail.
    Configuration/Settings.yaml

    (configured conservatively)

    View Slide

  27. Start it
    > FLOW_CONTEXT=PRODUCTION hhvm -m server -c Configuration/Production.hdf

    View Slide

  28. View Slide

  29. 0
    20
    40
    60
    80
    Concurrency
    50 100 150 200 250 300 350 400 450 500
    PHP (Apache+opcache) HHVM (standalone)
    HHVM (FCGI+Apache) HHVM (FCGI+nginx)
    Requests per second

    TYPO3 Neos 1.0.2, production mode, with HHVM patches

    View Slide

  30. 0
    4
    8
    12
    16
    Concurrency
    50 100 150 200 250 300 350 400 450 500
    PHP (Apache+opcache) HHVM (standalone)
    HHVM (FCGI+Apache) HHVM (FCGI+nginx)
    Response times

    TYPO3 Neos 1.0.2, production mode, with HHVM patches

    View Slide

  31. 91 %
    93,25 %
    95,5 %
    97,75 %
    100 %
    Concurrency
    50 100 150 200 250 300 350 400 450 500
    PHP (Apache+opcache) HHVM (standalone)
    HHVM (FCGI+Apache) HHVM (FCGI+nginx)
    Availability

    TYPO3 Neos 1.0.2, production mode, with HHVM patches

    View Slide

  32. Don't forget!

    Always enable production mode!

    View Slide

  33. > composer create-project \
    mittwald-typo3/neos-hhvm-distribution
    > composer create-project \
    mittwald-typo3/flow-hhvm-distribution
    Contribute:

    https://github.com/mittwald/flow-hhvm

    View Slide

  34. > composer create-project \
    mittwald-typo3/neos-hhvm-distribution
    Apply compatibility patches

    Adjust configuration

    Create appropriate HDF configuration file
    What does it do?

    View Slide

  35. HHVM
    FastCGI
    Static

    files
    nginx

    View Slide

  36. Use HHVM as FastCGI backend
    Server {
    Type = fastcgi
    FileSocket = /var/run/hhvm.sock
    SourceRoot = /var/www/my-flow-site/Web
    DefaultDocument = index.php
    ThreadCount = 100
    }
    configuration.hdf

    View Slide

  37. Use HHVM as FastCGI backend
    ProxyPassMatch ^/_Resources !
    ProxyPass / fcgi://127.0.0.1:9000/var/www/flow/Web/
    Apache configuration
    location /_Resources {
    try_files $uri;
    }
    !
    location / {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/flow/Web/$fastcgi_script_name;
    include fastcgi_params;
    }
    Nginx configuration

    View Slide

  38. Tobias Schlitt, CC-BY-NC-SA

    http://www.flickr.com/photos/tobiasschlitt/2644905363/

    View Slide

  39. Duncan

    View Slide

  40. Reading
    The HipHop virtual machine

    https://www.facebook.com/notes/facebook-engineering/the-hiphop-virtual-machine/10150415177928920

    !
    Faster and cheaper: The evolution of the HHVM JIT

    http://www.hhvm.com/blog/2027/faster-and-cheaper-the-evolution-of-the-hhvm-jit

    !
    HHVM runtime options

    https://github.com/facebook/hhvm/wiki/Runtime-options

    !
    Running HHVM as FastCGI server

    https://github.com/facebook/hhvm/wiki/FastCGI

    !
    HipHop bytecode specification

    https://github.com/facebook/hhvm/blob/master/hphp/doc/bytecode.specification

    !
    HipHop intermediate representation specification

    https://github.com/facebook/hhvm/blob/master/hphp/doc/ir.specification

    !
    HHVM compatibility package for TYPO3 Flow and Neos

    https://github.com/mittwald/flow-hhvm

    !
    Alla breve: Serverlasten halbieren mit dem PHP-zu-C++-Konverter HipHop

    c't, 23/2010, p. 180

    View Slide