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
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
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
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
(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
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 ; } }
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 ; } }
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 ; } }
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 ; }
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
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 ( ) ) ; }
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 ) ; }
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 }
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
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
[ 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 ) ;
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 ) ; }
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 ) ; }
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 ( ) ;
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/
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/
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