Slide 1

Slide 1 text

A NEW TYPE OF PHP: HHVM AND HACK Jeremy Mikola jmikola

Slide 2

Slide 2 text

A Brief History of Time

Slide 3

Slide 3 text

2008 HipHop PHP compiler (HPHPc) PHP → AST → C++ → x64 Developer tools Interpreter (HPHPi) Debugger (HPHPd)

Slide 4

Slide 4 text

2010 Facebook open-sources HPHPc HipHop Virtual Machine (HHVM) PHP → AST → HHBC HHBC → x64 (JIT)

Slide 5

Slide 5 text

2011 Facebook open-sources HHVM HHVM replaces HPHPi for development

Slide 6

Slide 6 text

2012

Slide 7

Slide 7 text

2013 HHVM replaces HPHPc in production HHVM 2.3.0 adds support for FastCGI Travis CI adds HHVM runtime Performance and parity lockdowns

Slide 8

Slide 8 text

2014 Facebook open-sources Hack language HHVM 3.0.0 adds support for Hack 27 PHP framework test suites at 100% Tracking PHP HEAD

Slide 9

Slide 9 text

HHVM

Slide 10

Slide 10 text

Why Are We Still Using PHP? : “objective issues… which make me sad” PHP: A Fractal of Bad Design PHP Sadness

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Lifetime of a Request

Slide 13

Slide 13 text

Bytecode Interpreter

Slide 14

Slide 14 text

Native Code JIT

Slide 15

Slide 15 text

Repo Authoritative Pre-compile HHBC: h h v m - - h p h p - t a n a l y z e

Slide 16

Slide 16 text

Benchmarking HHVM

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Small Responses (7 KB) Requests / Second Response Time (ms) https://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html

Slide 19

Slide 19 text

Medium Responses (80 KB) Requests / Second Response Time (ms) https://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html

Slide 20

Slide 20 text

Large Responses (220 KB) Requests / Second Response Time (ms) https://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Installing HHVM

Slide 23

Slide 23 text

Platform Support 64-bit Linux: It just works™ Mac OS X: interpreter only Windows and ARM in development

Slide 24

Slide 24 text

Linux Binaries Ubuntu (LTS, recent releases) Debian 8 Fedora 20 Mint 16 CentOS (community supported)

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Grab a Snickers…

Slide 27

Slide 27 text

HACK < ? h h

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Wonderful World of Types

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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 ; } }

Slide 32

Slide 32 text

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 ; } }

Slide 33

Slide 33 text

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 ; } }

Slide 34

Slide 34 text

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 ; }

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Stop Using PHP Arrays (ab)

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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 ) ; }

Slide 39

Slide 39 text

Collections Specialized array objects Vector, Map, Set, Pair Ordered, immutable or mutable Accessible, iterable like PHP arrays Literal syntax, familiar collection API

Slide 40

Slide 40 text

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 }

Slide 41

Slide 41 text

These May Be Useful, Too

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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 ) ;

Slide 45

Slide 45 text

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 ) ; }

Slide 46

Slide 46 text

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 ) ; }

Slide 47

Slide 47 text

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 ( ) ;

Slide 48

Slide 48 text

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)

Slide 49

Slide 49 text

Extending HHVM

Slide 50

Slide 50 text

Creating an Extension Bootstrap PHP in SystemLib HHVM Native Interface (HNI) Dynamically Loaded Objects

Slide 51

Slide 51 text

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/

Slide 52

Slide 52 text

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/

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

Getting the Community on Board http://hhvm.h4cc.de/

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

Image Credits id Software (Doom character sprites) http://xkcd.com/303/