inspiringcon14: elephpants on speed: running typo3 flow on hiphop vm
DESCRIPTION
Slides of my presentation at the Inspiring Conference (http://www.inspiring-conference.com) in Kolbermoor on March 28th, 2014.TRANSCRIPT
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/
YOUR SPEAKER
Martin Helmich Software architect at Mittwald
TYPO3 addicted since 2004 Caffeine addicted since 2007
Sebastian Bergmann, CC BY-SA http://www.flickr.com/photos/sebastian_bergmann/2337231691/
Lexing
Parsing
Compilation
Execution
PHP execution, traditional
<?php!$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
Compilation
Execution
T_OPEN_TAG
T_VARIABLE
T_LNUMBER
T_DOUBLE_ ARROW
T_CONSTANT_ENCAPSED_STRING
T_IF
T_ELSE
T_ECHO
T_STRING
Lexing
Parsing
Compilation
Execution
<?php!$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
Compilation
Execution
Variable assignment
Array constructor
Array accessor
Constant
Conditional statement
Boolean expression
Function call
Print statement
<?php!$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
Compilation
Execution
compiled vars: !0 = $locations, !1 = $currentLocationId, !2 = $currentLocationName, !3 = $greetingTemplateline # * 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!
Lexing
Parsing
Compilation
Execution
Lexing
Parsing
Compilation
Execution
PHP execution, traditional
Lexing
Parsing
Compilation
Execution
Opcode Cache
PHP opcodesPHP execution,
opcode cacheopcodes executed by PHP interpreter
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
$whatAmI = "Dynamic typization is great!";!if ($whatAmI > 0) { $whatAmI = [ "But in many PHP programs,", "this is not excessively used." ];} else { $whatAmI = FALSE;}
<?php!$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
IntegerString
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.listsudo apt-get updatesudo apt-get install hhvm
https://github.com/facebook/hhvm/wiki/Prebuilt-Packages-on-Debian-7
Running TYPO3 Flow on HHVM
One does not simply run TYPO3 Flow on HHVM.
Flore Allemandou, CC BY-NC-SA http://www.flickr.com/photos/flore_frmoz/5031037626/
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
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 %
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 } RewriteRules {
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 }}
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/
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)
Start it> FLOW_CONTEXT=PRODUCTION hhvm -m server -c Configuration/Production.hdf
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
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
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
Don't forget! Always enable production mode!
> composer create-project \ mittwald-typo3/neos-hhvm-distribution
> composer create-project \ mittwald-typo3/flow-hhvm-distribution
Contribute: https://github.com/mittwald/flow-hhvm
> composer create-project \ mittwald-typo3/neos-hhvm-distribution
Apply compatibility patches Adjust configuration
Create appropriate HDF configuration file
What does it do?
HHVM
FastCGI
Static files
nginx
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
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
Tobias Schlitt, CC-BY-NC-SA http://www.flickr.com/photos/tobiasschlitt/2644905363/
Duncan����������� ������������������ Hull,����������� ������������������ CC����������� ������������������ BY����������� ������������������ http://www.flickr.com/photos/dullhunk/202872717/
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