Your SlideShare is downloading. ×
0
Hacking with HHVM
Sara Golemon
pollita@php.net
Mar 5, 2014
1 A quick recap
2 PHP is WebScale
3 Sure it’s fast but…
4 Extending HHVM
5 Conclusion / Resources
Agenda
A quick recap
“What is HHVM?”
HHVM is not a source code transformer
That was HPHPc, it’s dead.
▪ Runs your PHP pages live,
just like PHP
▪ Uses a builti...
HHVM is not a source code transformer
That was HPHPc, it’s dead.
▪ Runs your PHP pages live,
just like PHP
▪ Uses a builti...
HHVM supports (most) PHP syntax
Tracking HEAD
▪ Pending: Splat (5.6)
(Variadics work already)
And some of its own
▪ Scalar...
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 is buildable
On other linux distros (MacOSX in interp mode only)
• http://hhvm.com/repo/wiki
• gcc 4.8 or later (soon...
Running a server
Built-in HTTP server FastCGI
Server {
Port = 80
Type = libevent
SourceRoot = /var/www
}
Log {
Level = Err...
Running a FastCGI server
nginx HHVM
server {
server_name www.example.com;
root /var/www;
index index.php;
location ~ .php$...
PHP is webscale
HHVM’s JIT is the secret sauce
HHVM – Bytecode interpreter
• PHP5 style bytecode execution
• APC-like caching of bytecodes
• Perf about on par with PHP
M...
HHVM – Native code JIT
• Bytecodes run a few times “cold”
• Variable type inference
• Hotpath detection
• Transform to nat...
HHVM – Repo Authoritative Mode
• “Production Mode”
• Improved offline pre-analysis
• Assumes no changes
• Another 10% or s...
But don’t take my word for it…
Magento (Daniel Sloof)
https://t.co/UB1aOzJ73c
Magento (Daniel Sloof)
https://t.co/UB1aOzJ73c
Symfony
(Christian Stocker)
Requests per Second
http://bit.ly/1fCRw99
Symfony
(Christian Stocker)
Page load Time
http://bit.ly/1fCRw99
I heard PHP is getting a JIT…
▪ phpng
▪ Translates Zend bytecode to LLVM intermediate
▪ Compiles to machine code which get...
Sure it’s fast
But what else can it do?
HACK (yes, it’s a horrible name…)
Type Hinting gone mad
▪ Scalars
▪ bool, int, float, num, string
▪ Return typehints
▪ Typ...
HACK
<?hh
class Foo {
private int $num = 123;
public function add(int $delta): Foo {
$this->num += $delta;
return $this;
}...
HACK – Constructor arg promotion
<?hh
class Foo {
public function add(int $delta): Foo {
$this->num += $delta;
return $thi...
HACK – Generics
<?hh
class Foo<T> {
public function add(T $delta): Foo {
$this->num += $delta;
return $this;
}
public func...
HACK – Collections
<?hh
function foo(Vector<int> $nums,
Set<string> $names,
Map<int,string> $numNameMap,
FrozenVector<int>...
Async Functions
<?php
// NOT ACTUAL SYNTAX
// Way over-simplified to fit on a slide 
async function getPage($url) {
$fp =...
User Attributes
<?php
<<Author(“sgolemon”),Clowny>>
function life() {
return 42;
}
$rf = new ReflectionFunction(‘life’);
p...
XHP – XHtml for PHP
<?php
if (validate($_GET[‘id’], $_GET[‘pwd’]))
loginAndRedirectToHome();
exit;
}
?><html>
<head><title...
XHP – XHtml for PHP
<?php
if (validate($_GET[‘id’], $_GET[‘pwd’]))
loginAndRedirectToHome();
exit;
}
include ‘xhp/init.php...
XHP – XHtml for PHP
<?php
class :mysite:footer extends :xhp:html-element {
attribute enum {‘en’,’es’} lang = ‘en’;
attribu...
XHP – XHtml for PHP
<?php
class :blink extends :xhp:html-element {
category %flow, %phrase;
children (pcdata | %phrase);
p...
HPHPd – HPHP Debugger
• Interactive shell
• GDB-like debugging
• Standalone or w/ server
• Breakpoints
• Watches
• Macros
Extending HHVM
You *can* do that in PHP
Writing a PHP Extension…
zend_bool array_column_param_helper(zval **param,
const char *name TSRMLS_DC) {
switch (Z_TYPE_PP...
The same function in HHVM
<?php
function array_column(array $arr, $col, $key = null) {
$ret = [];
foreach($arr as $key => ...
Crossing the PHP->C++ barrier
Array HHVM_FUNCTION(array_column, CArrRef arr, CVarRef col, CVarRef key) {
Array ret;
for (a...
Blurring the PHP/C++ line
class MyClass {
public static function escapeString(string $str): string {
return str_replace(“’...
Questions
?
Resources
• http://hhvm.com/repo
• http://hhvm.com/blog
• http://hhvm.com/twitter
• http://docs.hhvm.com
• hphp/doc in git...
Upcoming SlideShare
Loading in...5
×

Hacking with hhvm

1,009

Published on

Given at php tek 2014 by Elizabeth Smith as replacement for Sara

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,009
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
24
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide
  • Facebook started to work on HipHop for PHP in 2008. Their goal was to speed up the PHP execution speed and the first version of the project was composed of the tandem HPHPc/HPHPi. HPHPc is a PHP to C++ transpiler which was used to deploy the code to the production servers while HPHPi was an interpreter used during development and debug stages.
    HPHPc did a good job on improving performance but it was not without issues: maintaining both HPHPc and HPHPi in sync proved to be cumbersome plus some differences still existed between the transpiled code vs the interpreted one. That&amp;apos;s why back in 2010 Facebook decided to go for another approach and created HHVM – a new virtual machine designed to replace the Zend Engine used by PHP. By the end of 2012 HHVM achieved performance parity with the former HPHPc and soon surpassed it.
  • Rather than directly interpret or compile PHP code directly to C++, HHVM compiles Hack and PHP into an intermediate bytecode. This bytecode is then translated into x64 machine code dynamically at runtime by a just-in-time (JIT) compiler. This compilation process allows for all sorts of optimizations that cannot be made in a statically compiled binary, thus enabling higher performance of your Hack and PHP programs.
  • Okay to mention that we’re about to move to github.com/hhvm/hhvm
  • PHPNG is awesome for the future of the PHP language.It’s great that PHP is getting a JIT.
    Okay to mention the language spec Rex is working on.
  • This slide isn’t meant to be readable. It just illustrates how onerous writing an extension function for PHP can be.
  • Transcript of "Hacking with hhvm"

    1. 1. Hacking with HHVM Sara Golemon pollita@php.net Mar 5, 2014
    2. 2. 1 A quick recap 2 PHP is WebScale 3 Sure it’s fast but… 4 Extending HHVM 5 Conclusion / Resources Agenda
    3. 3. A quick recap “What is HHVM?”
    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.php home.phplogin.php index.php PHP A P C
    5. 5. 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.php home.phplogin.php index.php HHVM
    6. 6. HHVM supports (most) PHP syntax Tracking HEAD ▪ Pending: Splat (5.6) (Variadics work already) And some of its own ▪ Scalar type hint (and much much more) ▪ Async co-routines ▪ Generics ▪ Collections (smart arrays) ▪ XHP (Integrated XHTML) ▪ User Attributes
    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. PHP is webscale HHVM’s JIT is the secret sauce
    12. 12. 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
    13. 13. 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
    14. 14. 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
    15. 15. But don’t take my word for it…
    16. 16. Magento (Daniel Sloof) https://t.co/UB1aOzJ73c
    17. 17. Magento (Daniel Sloof) https://t.co/UB1aOzJ73c
    18. 18. Symfony (Christian Stocker) Requests per Second http://bit.ly/1fCRw99
    19. 19. Symfony (Christian Stocker) Page load Time http://bit.ly/1fCRw99
    20. 20. I heard PHP is getting a JIT… ▪ phpng ▪ Translates Zend bytecode to LLVM intermediate ▪ Compiles to machine code which gets run directly ▪ Yes, it’s faster than PHP 5.6, but not faster than HHVM ▪ LLVM is a general purpose JIT. HHVM was designed for PHP’s “quirks” ▪ HHVM’s variable types were laid out with JITting in mind, PHP is stuck with the zval ▪ ZE must use a caller frame. HHVM issues direct CPU fcalls ▪ HHVM has access to Hack type hinting/inference
    21. 21. Sure it’s fast But what else can it do?
    22. 22. HACK (yes, it’s a horrible name…) Type Hinting gone mad ▪ Scalars ▪ bool, int, float, num, string ▪ Return typehints ▪ Typed properties ▪ Constructor arg promotion ▪ Specialization ▪ array<int> ▪ array<string,array<string,stdClass>> Static Analysis ▪ Analyze entire code tree without running ▪ Report type errors like a strictly typed language ▪ Fallback on loose typing when needed (because that’s what PHP is good at)
    23. 23. HACK <?hh class Foo { private int $num = 123; public function add(int $delta): Foo { $this->num += $delta; return $this; } public function get(): int { return $this->num; } public function __constructor(int $num): void { $this->num = $num; } } $f = new Foo(123); $f->add(456); $f->add(“banana”); Basic Hack ▪ Static Analyzer traces value through whole program ▪ Looks for mismatches and reports errors ▪ “Foo::add() expected int” “Foo::add() received string”
    24. 24. HACK – Constructor arg promotion <?hh class Foo { public function add(int $delta): Foo { $this->num += $delta; return $this; } public function get(): int { return $this->num; } public function __constructor( private int $num) : void { } } $f = new Foo(123); echo $f->add(456)->get(); Avoid repeated patterns ▪ public/protected/private as __construct arg modifiers ▪ Declares the property and initializes from value ▪ Less boilerplate, more coding
    25. 25. HACK – Generics <?hh class Foo<T> { public function add(T $delta): Foo { $this->num += $delta; return $this; } public function get(): T { return $this->num; } public function __constructor( private T $num) : void { } } $i = new Foo<int>(123); echo $i->add(456)->get(); $f = new Foo<float>(3.14); echo $f->add(2.17)->get(); Specialize common code ▪ T is replaced w/ specialization type at instantiation ▪ Typecheker propagates replacement through generic ▪ Less boilerplate, more coding
    26. 26. HACK – Collections <?hh function foo(Vector<int> $nums, Set<string> $names, Map<int,string> $numNameMap, FrozenVector<int> $nums2): bool { foreach($nums as $num) { $mappedName = $numNameMap[$num]; if ($names->contains($mappedName)) { return true; } } if ($nums2->count() == 0) return true; return false; } Specialized array objects ▪ Vector, Set, Map, StableMap ▪ Frozen* Mutable* (default) ▪ Support ArrayAccess ▪ Extensive library of methods
    27. 27. Async Functions <?php // NOT ACTUAL SYNTAX // Way over-simplified to fit on a slide  async function getPage($url) { $fp = fopen($url, ‘r’); await $fp; return stream_get_contents($fp); } $pages = await [ getPage(‘http://php.net’), getPage(‘http://example.com’), getPage(‘http://hhvm.com’), ]; Cooperative Multitasking ▪ Parallelizing made easy ▪ Allow multiple functions to run “simultaneously” ▪ While one is blocking, the other executes
    28. 28. User Attributes <?php <<Author(“sgolemon”),Clowny>> function life() { return 42; } $rf = new ReflectionFunction(‘life’); print_r($rf->getAttributes()); print_r($rf->getAttribute(‘Author’)); Array ( [Author] => Array ( [0] => sgolemon ) [Clowny] => Array ( ) ) Array ( [0] => sgolemon ) User-defined metadata ▪ Arbitrary labels surfaced via reflection ▪ Basically what it says on the tin
    29. 29. XHP – XHtml for PHP <?php if (validate($_GET[‘id’], $_GET[‘pwd’])) loginAndRedirectToHome(); exit; } ?><html> <head><title>Login</title></head> <body> <form> ID: <input type=text name=“username” value=“{$_GET[‘id’]}” /> Pass: <input type=password name=“password” value=“{$_GET[‘pwd’]}” /> </form> </body> </html>  Easy noob mistake ▪ http://example.com/?id=“> <script>alert(“Gotcha!”)</script > ▪ Trivial vector for stealing user’s cookies (and login credentials)
    30. 30. XHP – XHtml for PHP <?php if (validate($_GET[‘id’], $_GET[‘pwd’])) loginAndRedirectToHome(); exit; } include ‘xhp/init.php’; $form = <form> ID: <input type=text name=“username” value=“{$_GET[‘id’]}” /> Pass: <input type=password name=“password” value=“{$_GET[‘pwd’]}” /> </form>; echo <html> <head><title>Login</title></head> <body>{$form}</body> </html>; Markup as 1st class syntax ▪ Parser can tell what’s userdata, and what isn’t ▪ Catch most XSS automatically ▪ Formalizes component modularity
    31. 31. XHP – XHtml for PHP <?php class :mysite:footer extends :xhp:html-element { attribute enum {‘en’,’es’} lang = ‘en’; attribute string prefix; public function stringify() { $home = ($this->lang == ‘es’) ? ‘Casa’ : ‘Home’; $footer = <div class=“footer”> <a href=“{$this- >prefix}/”>$home</a> <a href=“{$this- >prefix}/contact.php”> Contact Us </a> etc… </div>; return (string)$footer; } } echo <html> <body> Blah Blah <mysite:footer lang=‘es’ /> </body> </html>; Markup as 1st class syntax ▪ Custom components ▪ Compose from other tags or generate custom xhtml
    32. 32. XHP – XHtml for PHP <?php class :blink extends :xhp:html-element { category %flow, %phrase; children (pcdata | %phrase); protected $tagName = ‘blink’; } echo <html> <body> <blink>UNDER CONSTRUCTION</blink> <mysite:footer lang=‘es’ /> </body> </html>; Markup as 1st class syntax ▪ Can also contain other tags ▪ Default :xhp:html-element behavior makes simple tags easy ▪ Replace :blink’s stringify to use javascript since browsers disable
    33. 33. HPHPd – HPHP Debugger • Interactive shell • GDB-like debugging • Standalone or w/ server • Breakpoints • Watches • Macros
    34. 34. Extending HHVM You *can* do that in PHP
    35. 35. 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); } } }
    36. 36. 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; }
    37. 37. 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; }
    38. 38. Blurring the PHP/C++ line class MyClass { public static function escapeString(string $str): string { return str_replace(“’”, “’”, $str); } <<__Native>> public funtion query(string $sql): array; } Array HHVM_METHOD(MyClass, query, const String& sql) { // Call C/C++ library function and return result… // Called object available as: CObjRef this_ // Static calls come through: Class *self_ }
    39. 39. Questions ?
    40. 40. 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
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×