Hacking hhvm

33
Hacking HHVM Waqar Alamgir @ wajrcs [email protected] Aug 13, 2015

Transcript of Hacking hhvm

Page 2: Hacking hhvm

“What is HHVM?”

Page 3: Hacking hhvm

HHVM is not a source code transformerThat was HPHPc, it’s dead.

▪ Runs your PHP pages live,just like PHP

▪ Uses a builtin web serveror FastCGI – Runs anywhere(on 64-bit x86 linux)

▪ Drop-in replacement for PHP(mostly)

Webserver(apache, nginx,

etc…)

Database(mysql, posges,mongo, redis,

etc…)

cart.phphome.php

login.php

index.php

PHPAPC

Page 4: Hacking hhvm

HHVM is not a source code transformerThat was HPHPc, it’s dead.

▪ Runs your PHP pages live,just like PHP

▪ Uses a builtin web serveror FastCGI – Runs anywhere(on 64-bit x86 linux)

▪ Drop-in replacement for PHP(mostly)

Webserver(apache, nginx,

etc…)

Database(mysql, posges,mongo, redis,

etc…)

cart.phphome.php

login.php

index.php

HHVM

Just Plug and Pray!

Erm, I mean… Play

Page 5: Hacking hhvm

HHVM supports (most) PHP syntaxTracking HEAD▪ Pending: Splat (5.6)(Variadics work already)

▪ Finally

▪ Generators▪ Namespaces

And some of its own▪ Scalar type hint(and much much more)

▪ Async co-routines▪ Generics▪ Collections (smart arrays)

▪ XHP (Integrated XHTML)▪ User Attributes

Page 6: Hacking hhvm

HHVM’s Parity Gap• Only about 60% of PHP’s unit tests pass.

• 20 top framework (and more) do pass.

• So I wouldn’t sweat the small stuff.

Page 7: Hacking hhvm

HHVM is easy to installIf you’re on Ubuntu▪ deb http://dl.hhvm.com/ubuntu saucy main▪ apt-get update▪ apt-get install hhvm (or hhvm-nightly)

▪ Provides one binary covering cli, fcgi server, and libevent server

▪ Coming very soon to a Debian near you!

Or something Debianish…

Page 8: Hacking hhvm

HHVM is buildableOn other linux distros (MacOSX in interp mode only)• http://hhvm.com/repo/wiki

• gcc 4.8 or later (soon to be 4.8 or later)

• Boost 1.49 or later

• Lots of other dependencies….

• git clone [email protected]:facebook/hhvmcmake .make –j

• hphp/hhvm/hhvm xkcd.org/303

Page 9: Hacking hhvm

Running a serverBuilt-in HTTP server FastCGIServer { Port = 80 Type = libevent SourceRoot = /var/www}Log { Level = Error UseLogFile = true File = /var/log/hhvm-error.log Access { * { File = /var/log/hhvm-access.log Format = %h %l %u %t \”%r\” %>s %b }}}

VirtualHost {…}StaticFile {…}

Server { Port = 9000 Type = fastcgi SourceRoot = /var/www}Log { Level = Error UseLogFile = true File = /var/log/hhvm-error.log Access { * { File = /var/log/hhvm-access.log Format = %h %l %u %t \”%r\” %>s %b }}}

Requires patched libevent

Page 10: Hacking hhvm

Running a FastCGI servernginx HHVMserver { server_name www.example.com;

root /var/www; index index.php;

location ~ \.php$ { fastcgi_pass unix:/var/run/hhvm.sock fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name; include fastcgi_param; }}

Server { FileSocket = /var/run/hhvm.sock Type = fastcgi SourceRoot = /var/www}Log { Level = Error UseLogFile = true File = /var/log/hhvm-error.log Access { * { File = /var/log/hhvm-access.log Format = %h %l %u %t \”%r\” %>s %b }}}

Page 11: Hacking hhvm

HPHPC in 2010 - 2011• Crazy cross compiler.

• Converts php to C++.

HHVM in 2013• Complete new VM.

• Facebook is running it on Production.

• Great community, over 750 pull requests.

Page 12: Hacking hhvm

PHP is webscale HHVM’s JIT is the secret sauce

Page 13: Hacking hhvm

HHVM – Bytecode interpreter

• PHP5 style bytecode execution

• APC-like caching of bytecodes

• Perf about on par with PHP

Modified? InvalidateCache

Compile to

Bytecode

RunBytecode

Y

N

Page 14: Hacking hhvm

HHVM – Native code JIT

• Bytecodes run a few times “cold”

• Variable type inference

• Hotpath detection

• Transform to native code

Modified? InvalidateCache

Compile to

BytecodeHave native?

Run Native

Hot?

RunBytecode

Compile to

Native

Y

Y

Y

N

N

N

Page 15: Hacking hhvm

HHVM – Compiling to Native

Page 16: Hacking hhvm

HHVM – Repo Authoritative Mode

• “Production Mode”

• Improved offline pre-analysis

• Assumes no changes

• Another 10% or so perf gain

PreCompile

Bytecode

Have native?

Run Native

Hot?

RunBytecode

Compile to

Native

Y

Y

N

N

Page 17: Hacking hhvm

HHVM – Warming Up Server

Page 18: Hacking hhvm

Your CPU on PHP.

Page 19: Hacking hhvm
Page 20: Hacking hhvm
Page 21: Hacking hhvm
Page 22: Hacking hhvm
Page 23: Hacking hhvm

Magento (Daniel Sloof)https://t.co/UB1aOzJ73c

Page 24: Hacking hhvm

Magento (Daniel Sloof)https://t.co/UB1aOzJ73c

Page 25: Hacking hhvm

Symfony(Christian Stocker)

Requests per Secondhttp://bit.ly/1fCRw99

Page 26: Hacking hhvm

Symfony(Christian Stocker)

Page load Timehttp://bit.ly/1fCRw99

Page 27: Hacking hhvm

HPHPd – HPHP Debugger

• Interactive shell

• GDB-like debugging

• Standalone or w/ server

• Breakpoints

• Watches

• Macros

Page 28: Hacking hhvm

Extending HHVMYou *can* do that in PHP

Page 29: Hacking hhvm

Writing a PHP Extension…zend_bool array_column_param_helper(zval **param, const char *name TSRMLS_DC) { switch (Z_TYPE_PP(param)) { case IS_DOUBLE: convert_to_long_ex(param); case IS_LONG: return 1; case IS_OBJECT: convert_to_string_ex(param); case IS_STRING: return 1; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The %s key should be either a string or an integer", name); return 0; }}PHP_FUNCTION(array_column) { zval **zcolumn = NULL, **zkey = NULL, **data; HashTable *arr_hash; HashPosition pointer;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "hZ!|Z!", &arr_hash, &zcolumn, &zkey) == FAILURE) { return; } if ((zcolumn && !array_column_param_helper(zcolumn, "column" TSRMLS_CC)) || (zkey && !array_column_param_helper(zkey, "index" TSRMLS_CC))) { RETURN_FALSE; } array_init(return_value); for (zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); zend_hash_get_current_data_ex(arr_hash, (void**)&data, &pointer) == SUCCESS; zend_hash_move_forward_ex(arr_hash, &pointer)) { zval **zcolval, **zkeyval = NULL; HashTable *ht; if (Z_TYPE_PP(data) != IS_ARRAY) { continue; } ht = Z_ARRVAL_PP(data); if (!zcolumn) { zcolval = data; } else if ((Z_TYPE_PP(zcolumn) == IS_STRING) && (zend_hash_find(ht, Z_STRVAL_PP(zcolumn), Z_STRLEN_PP(zcolumn) + 1, (void**)&zcolval) == FAILURE)) { continue; } else if ((Z_TYPE_PP(zcolumn) == IS_LONG) && (zend_hash_index_find(ht, Z_LVAL_PP(zcolumn), (void**)&zcolval) == FAILURE)) { continue; } if (zkey && (Z_TYPE_PP(zkey) == IS_STRING)) { zend_hash_find(ht, Z_STRVAL_PP(zkey), Z_STRLEN_PP(zkey) + 1, (void**)&zkeyval); } else if (zkey && (Z_TYPE_PP(zkey) == IS_LONG)) { zend_hash_index_find(ht, Z_LVAL_PP(zkey), (void**)&zkeyval); } Z_ADDREF_PP(zcolval); if (zkeyval && Z_TYPE_PP(zkeyval) == IS_STRING) { add_assoc_zval(return_value, Z_STRVAL_PP(zkeyval), *zcolval); } else if (zkeyval && Z_TYPE_PP(zkeyval) == IS_LONG) { add_index_zval(return_value, Z_LVAL_PP(zkeyval), *zcolval); } else if (zkeyval && Z_TYPE_PP(zkeyval) == IS_OBJECT) { SEPARATE_ZVAL(zkeyval); convert_to_string(*zkeyval); add_assoc_zval(return_value, Z_STRVAL_PP(zkeyval), *zcolval); } else { add_next_index_zval(return_value, *zcolval); } }}

Page 30: Hacking hhvm

The same function in HHVM<?php

function array_column(array $arr, $col, $key = null) { $ret = []; foreach($arr as $key => $val) { if (!is_array($val)) continue; $cval = ($col === null) ? $val : $val[$col]; if ($key === null || !isset($val[$key])) {

$ret[] = $cval; } else { $ret[$val[$key]] = $cval; } } return $ret;}

Page 31: Hacking hhvm

Crossing the PHP->C++ barrierArray HHVM_FUNCTION(array_column, CArrRef arr, CVarRef col, CVarRef key) { Array ret; for (auto &pair : arr) { Variant key = pair.first, val = pair.second; if (val.isArray()) continue; Array aval = val.toArray(); Variant cval = col.isNull() ? aval : aval[col]; if (key.isNull() || !aval.exists(key)) { ret.append(cval); } else { ret[aval[key]] = cval; } } return ret;}

Page 32: Hacking hhvm

Questions ?

Page 33: Hacking hhvm

Resources

• http://hhvm.com/repo

• http://hhvm.com/blog

• http://hhvm.com/twitter

• http://docs.hhvm.com

• hphp/doc in git repository for Options and Technical… Stuff

• Freenode / #hhvm

• http://hhvm.com/fb/page

• http://hhvm.com/fb/general

• @HipHopVM

• @HackLang