Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Hacking hhvm

452 views

Published on

#php #hhvm #apache #nginx #web #performance

Published in: Software
  • Be the first to comment

  • Be the first to like this

Hacking hhvm

  1. 1. Hacking HHVM Waqar Alamgir @wajrcs walamgir@folio3.com Aug 13, 2015
  2. 2. “What is HHVM?”
  3. 3. HHVM is not a source code transformer That was HPHPc, it’s dead. ▪ Runs your PHP pages live, just like PHP ▪ Uses a builtin web server or 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.phplogin.php index.php PHP A P C
  4. 4. HHVM is not a source code transformer That was HPHPc, it’s dead. ▪ Runs your PHP pages live, just like PHP ▪ Uses a builtin web server or 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.phplogin.php index.php HHVM Just Plug and Pray! Erm, I mean… Play
  5. 5. HHVM supports (most) PHP syntax Tracking 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
  6. 6. 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.
  7. 7. HHVM is easy to install If 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…
  8. 8. HHVM is buildable On 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 git@github.com:facebook/hhvm cmake . make –j • hphp/hhvm/hhvm xkcd.org/303
  9. 9. Running a server Built-in HTTP server FastCGI Server { 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
  10. 10. Running a FastCGI server nginx HHVM server { 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 }} }
  11. 11. 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.
  12. 12. PHP is webscale HHVM’s JIT is the secret sauce
  13. 13. HHVM – Bytecode interpreter • PHP5 style bytecode execution • APC-like caching of bytecodes • Perf about on par with PHP Modified? Invalidate Cache Compile to Bytecode Run Bytecode Y N
  14. 14. HHVM – Native code JIT • Bytecodes run a few times “cold” • Variable type inference • Hotpath detection • Transform to native code Modified? Invalidate Cache Compile to Bytecode Have native? Run Native Hot? Run Bytecode Compile to Native Y Y Y N N N
  15. 15. HHVM – Compiling to Native
  16. 16. HHVM – Repo Authoritative Mode • “Production Mode” • Improved offline pre-analysis • Assumes no changes • Another 10% or so perf gain PreCompil e Bytecode Have native? Run Native Hot? Run Bytecode Compile to Native Y Y N N
  17. 17. HHVM – Warming Up Server
  18. 18. Your CPU on PHP.
  19. 19. Magento (Daniel Sloof) https://t.co/UB1aOzJ73c
  20. 20. Magento (Daniel Sloof) https://t.co/UB1aOzJ73c
  21. 21. Symfony (Christian Stocker) Requests per Second http://bit.ly/1fCRw99
  22. 22. Symfony (Christian Stocker) Page load Time http://bit.ly/1fCRw99
  23. 23. HPHPd – HPHP Debugger • Interactive shell • GDB-like debugging • Standalone or w/ server • Breakpoints • Watches • Macros
  24. 24. Extending HHVM You *can* do that in PHP
  25. 25. 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); } } }
  26. 26. 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; }
  27. 27. Crossing the PHP->C++ barrier Array 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; }
  28. 28. Questions
  29. 29. 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

×