Share
Embed
A New Type of PHP: HHVM and Hack
Presented May 8, 2015 at OpenWest: http://joind.in/talk/view/14032
Presented July 14, 2014 at Midwest.io: http://www.midwest.io/archive/2014/sessions/#monday-2a
Reveal.js presentation published at: http://jmikola.github.io/slides/hhvm_and_hack/
Jeremy Mikola
May 08, 2015
Transcript
58 slides
-
2008 HipHop PHP compiler (HPHPc) PHP → AST → C++
→ x64 Developer tools Interpreter (HPHPi) Debugger (HPHPd) -
2010 Facebook open-sources HPHPc HipHop Virtual Machine (HHVM) PHP →
AST → HHBC HHBC → x64 (JIT) -
2013 HHVM replaces HPHPc in production HHVM 2.3.0 adds support
for FastCGI Travis CI adds HHVM runtime Performance and parity lockdowns -
2014 Facebook open-sources Hack language HHVM 3.0.0 adds support for
Hack 27 PHP framework test suites at 100% Tracking PHP HEAD -
Why Are We Still Using PHP? : “objective issues… which
make me sad” PHP: A Fractal of Bad Design PHP Sadness -
The Elephant in the Room It’s had a role in
significant projects Wikipedia, Drupal, Wordpress Facebook: x * 10⁵ files, y * 10⁷ LOC It gets some things right Developer workflow: tight feedback loop State: each request is a blank slate Concurrency: share nothing Taking PHP Seriously – Keith Adams, Facebook -
Repo Authoritative Pre-compile HHBC: h h v m - -
h p h p - t a n a l y z e -
Test Environment Symfony2, ElasticSearch (HTTP API) JSON → PHP serialization
PHP 5.3 (APC), PHP 5.5 (OpCache), HHVM 2.3.0 nginx web server with FastCGI ApacheBench for load testing Results from: , Christian Stocker Liip AG -
Small Responses (7 KB) Requests / Second Response Time (ms)
https://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html -
Medium Responses (80 KB) Requests / Second Response Time (ms)
https://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html -
Large Responses (220 KB) Requests / Second Response Time (ms)
https://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html -
Some Conclusions PHP 5.5 is up to 1.5 times faster
than PHP 5.3 HHVM is up to 3.5 times faster than PHP 5.3 HHVM is up to twice as fast as PHP 5.5 HHVM shines under high load, larger requests Stop using PHP 5.3 -
Platform Support 64-bit Linux: It just works™ Mac OS X:
interpreter only Windows and ARM in development -
Linux Binaries Ubuntu (LTS, recent releases) Debian 8 Fedora 20
Mint 16 CentOS (community supported) -
Building from Source Fair amount of dependencies A must for
extension development $ g i t c l o n e g i t : / / g i t h u b . c o m / f a c e b o o k / h h v m . g i t $ c d h h v m $ g i t c h e c k o u t H H V M - 3 . 1 . 0 $ g i t s u b m o d u l e u p d a t e - - i n i t - - r e c u r s i v e $ c m a k e . $ m a k e - j [ n u m _ c o r e s ] $ s u d o m a k e i n s t a l l -
In a Nutshell Static type analysis Local type inference, meaningful
errors Tight feedback loop (h h _ c l i e n t , h h _ s e r v e r ) Checked before runtime New language features, core classes Some PHP ‘features’ removed Catch bugs early, develop faster -
Type Hinting Scalars bool, int, float, num, string Array elements
(and keys) a r r a y < i n t > , a r r a y < s t r i n g , i n t > Properties and return types Nullable and m i x e d types Generics lend to code reuse -
Type Hinting c l a s s A d d
e r { p r i v a t e i n t $ x ; p u b l i c f u n c t i o n _ _ c o n s t r u c t ( i n t $ x ) : v o i d { $ t h i s - > x = $ x ; } p u b l i c f u n c t i o n a d d ( i n t $ y ) : v o i d { $ t h i s - > x + = $ y ; } p u b l i c f u n c t i o n g e t ( ) : i n t { r e t u r n $ t h i s - > x ; } } -
Constructor Arg Promotion c l a s s A d
d e r { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( p r i v a t e i n t $ x ) : v o i d { } p u b l i c f u n c t i o n a d d ( i n t $ y ) : v o i d { $ t h i s - > x + = $ y ; } p u b l i c f u n c t i o n g e t ( ) : i n t { r e t u r n $ t h i s - > x ; } } -
Generics c l a s s A d d e
r < T > { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( p r i v a t e T $ x ) : v o i d { } p u b l i c f u n c t i o n a d d ( T $ y ) : v o i d { $ t h i s - > x + = $ y ; } p u b l i c f u n c t i o n g e t ( ) : T { r e t u r n $ t h i s - > x ; } } -
Type Aliasing Declared outside of classes, functions Opaque aliasing abstracts
underlying type / / t y p e s . p h p t y p e M y I n t = i n t ; n e w t y p e M y O p a q u e I n t = i n t ; r e q u i r e ' t y p e s . p h p ' ; f u n c t i o n f o o ( M y I n t $ x ) : M y I n t { r e t u r n $ x + 1 ; } f u n c t i o n b a r ( M y O p a q u e I n t $ x ) : M y O p a q u e I n t { / / E r r o r : c a n n o t a s s u m e i n t e g e r b e h a v i o r o u t s i d e o f t y p e s . p h p r e t u r n $ x + 1 ; } -
Type Checking is Configurable Modes: strict, partial, decl < ?
h h / / m o d e Partial is most flexible, the default Classes and functions can be partially typed Allows calling into untyped code (i.e. PHP) Decl useful for calling into legacy code from strict Type checker looks at signatures, but not code -
Tuples Typed, fixed-length lists Size and types are immutable Useful
for custom types, multiple return values t y p e P o i n t 2 D = ( i n t , i n t ) ; f u n c t i o n c r e a t e P o i n t ( i n t $ x , i n t $ y ) : P o i n t 2 D { r e t u r n t u p l e ( $ x , $ y ) ; } f u n c t i o n g e t D a t e A n d T i m e s t a m p ( ) : ( s t r i n g , i n t ) { r e t u r n t u p l e ( d a t e ( ' c ' ) , t i m e ( ) ) ; } -
Shapes Typed, structured dictionaries Alternative to classes with public properties
Useful for simple data structures, argument bags t y p e P a g e V i e w = s h a p e ( ' u r l ' = > s t r i n g , ' c o u n t ' = > i n t , ) ; f u n c t i o n c r e a t e P a g e V i e w ( s t r i n g $ u r l , i n t $ c o u n t ) : P a g e V i e w { r e t u r n s h a p e ( ' u r l ' = > $ u r l , ' c o u n t ' = > $ c o u n t ) ; } -
Collections Specialized array objects Vector, Map, Set, Pair Ordered, immutable
or mutable Accessible, iterable like PHP arrays Literal syntax, familiar collection API -
Vectors vs. PHP Arrays $ v e c t o
r = V e c t o r { 5 , 1 0 , 1 5 , 2 0 } ; $ v e c t o r - > r e m o v e K e y ( 2 ) ; f o r e a c h ( $ v e c t o r a s $ k e y = > $ v a l u e ) { p r i n t f ( " % d = > % d \ n " , $ k e y , $ v a l u e ) ; } $ a r r a y = [ 5 , 1 0 , 1 5 , 2 0 ] ; u n s e t ( $ a r r a y [ 2 ] ) ; f o r e a c h ( $ a r r a y a s $ k e y = > $ v a l u e ) { p r i n t f ( " % d = > % d \ n " , $ k e y , $ v a l u e ) ; } [ 5 , 1 0 , 2 0 ] vs. { " 0 " : 5 , " 1 " : 1 0 , " 3 " : 2 0 } -
Lambda Expressions PHP has closures, but… Parent scope is not
implicitly inherited Can be verbose for simple expressions $ i n c = f u n c t i o n ( $ x ) { r e t u r n $ x + 1 ; } $ i n c ( 1 1 ) ; / / r e t u r n s 1 2 $ f = f u n c t i o n ( $ x ) { r e t u r n f u n c t i o n ( $ y ) u s e ( $ x ) { r e t u r n $ x + $ y ; } ; } ; $ g = $ f ( 4 ) ; $ g ( 5 ) ; / / r e t u r n s 9 -
Lambda Expressions Parent scope is inherited automatically Concise syntax well-suited
to callback APIs $ i n c = $ x = = > $ x + 1 ; $ i n c ( 1 1 ) ; / / r e t u r n s 1 2 $ f = $ x = = > $ y = = > $ x + $ y ; $ g = $ f ( 4 ) ; $ g ( 5 ) ; / / r e t u r n s 9 -
Lambdas and Collections $ a r r a y =
[ 2 , 4 , 6 , 8 ] ; $ i n c = 3 ; a r r a y _ f i l t e r ( a r r a y _ m a p ( f u n c t i o n ( $ x ) u s e ( $ i n c ) { r e t u r n $ x + $ i n c ; } , $ a r r a y ) , f u n c t i o n ( $ x ) { r e t u r n $ x > 1 0 ; } ) ; vs. $ v e c t o r = V e c t o r { 2 , 4 , 6 , 8 } ; $ i n c = 3 ; $ v e c t o r - > m a p ( $ x = = > $ x + $ i n c ) - > f i l t e r ( $ x = = > $ x > 1 0 ) ; -
Continuations Like generators in PHP 5.5, slight differences Must be
primed with n e x t ( ) y i e l d must always return a value f u n c t i o n i n f i n i t e ( ) : C o n t i n u a t i o n < i n t > { $ i = 0 ; w h i l e ( t r u e ) { y i e l d $ i + + ; } } f o r e a c h ( i n f i n i t e ( ) a s $ i ) { p r i n t f ( " % d \ n " , $ i ) ; } -
Async Functions Functions use a s y n c modifier,
return Awaitables Callers opt in with a w a i t keyword a s y n c f u n c t i o n c o m p l e x C a l c u l a t i o n ( … ) : A w a i t a b l e < R e s u l t > { / / q u e r y d a t a b a s e s , c a l l s e r v i c e s , e t c . r e t u r n n e w R e s u l t ( … ) ; } a s y n c f u n c t i o n f e t c h U s e r ( i n t $ i d ) : A w a i t a b l e < U s e r > { $ a r g s = [ ' i d ' = > $ i d , ' t y p e ' = > ' u s e r ' ] ; $ a = c o m p l e x C a l c u l a t i o n ( $ a r g s ) ; / / $ a r e p r e s e n t s u n s t a r t e d s t a t e o f a c o m p u t a t i o n $ r e s u l t = a w a i t $ a ; / / b l o c k u n t i l $ a i s r e s o l v e d r e t u r n c o n v e r t R e s u l t T o U s e r ( $ r e s u l t ) ; } -
Async Functions Parallelism by awaiting multiple things at once Top-level
context can j o i n ( ) (block on results) a s y n c f u n c t i o n g e n e r a t e R e s p o n s e ( ) : A w a i t a b l e < R e s p o n s e > { l i s t ( $ a , $ b , $ c ) = a w a i t G e n A r r a y W a i t H a n d l e : : c r e a t e ( [ f e t c h U s e r ( … ) , q u e r y C a c h e ( … ) , c a l l S e r v i c e ( … ) , ] ) ; r e t u r n n e w R e s p o n s e ( $ a , $ b , $ c ) ; } a s y n c f u n c t i o n f e t c h U s e r ( … ) : A w a i t a b l e < … > { } a s y n c f u n c t i o n q u e r y C a c h e ( … ) : A w a i t a b l e < … > { } a s y n c f u n c t i o n c a l l S e r v i c e ( … ) : A w a i t a b l e < … > { } $ r e s p o n s e = g e n e r a t e R e s p o n s e ( ) - > j o i n ( ) ; -
Additional Features User attributes (accessible via Reflection) Trait requirements (support
static analysis) Override attribute (child counterpart to abstract) Variadic arguments (not type-checked) XHP (templated XML fragments in PHP) -
Creating an Extension Bootstrap PHP in SystemLib HHVM Native Interface
(HNI) Dynamically Loaded Objects -
HHVM Native Interface (PHP) Implement as much as possible in
PHP Annotated methods point to C++ implementations c l a s s M o n g o C l i e n t { < < _ _ N a t i v e > > p u b l i c f u n c t i o n _ _ c o n s t r u c t ( s t r i n g $ s e r v e r = ' m o n g o d b : / / l o c a l h o s t : 2 7 0 1 7 ' , a r r a y $ o p t i o n s = [ ' c o n n e c t ' = > t r u e ] ) : v o i d ; p u b l i c f u n c t i o n s e l e c t D B ( s t r i n g $ n a m e ) : M o n g o D B { r e t u r n n e w M o n g o D B ( $ t h i s , $ n a m e ) ; } / / … } https://github.com/10gen-labs/mongo-hhvm-driver/ -
HHVM Native Interface (C++) Method macros similar to PHP extension
API 1:1 mapping between PHP and C++ types s t a t i c v o i d H H V M _ M E T H O D ( M o n g o C l i e n t , _ _ c o n s t r u c t , c o n s t S t r i n g & u r i , A r r a y o p t i o n s ) { m o n g o c _ c l i e n t _ t * c l i e n t = m o n g o c _ c l i e n t _ n e w ( u r i . c _ s t r ( ) ) ; / / w r a p m o n g o c _ c l i e n t _ t i n a n H H V M r e s o u r c e o b j e c t t h i s _ - > o _ s e t ( " _ r e s o u r c e " , c l i e n t R e s o u r c e , " C l i e n t R e s o u r c e " ) ; } https://github.com/10gen-labs/mongo-hhvm-driver/ -
Undocumented Territory Learn by example, consult prior art Core extensions
(h p h p / r u n t i m e / e x t / ) Community extensions (about a dozen) Become an IRC regular -
Looking Ahead PHP iterating faster than ever Multiple implementations is
a plus Competition drives progress Hack features and overlapping PHP RFCs Facebook still active on php-internals -
PHPNG (Next Generation) JIT based on Fair amount of internal
refactoring Some behavioral changes, BC breaks Progress since January 2014 1.5x execution speed-up 30–60% less CPU instructions LLVM -
THANKS! Any Questions? and and # h h v m
on Freenode jmikola.net/blog/hack-dev-day/ github.com/facebook/hhvm wiki hhvm.com hacklang.org Thanks to: , , , and Elizabeth Smith Sara Golemon Christian Stocker Chris Heng