HHVM: Efficient and Scalable PHP/Hack Execution / Guilherme Ottoni (Facebook)
Diving into HHVM Extensions (PHPNW Conference 2015)
-
Upload
james-titcumb -
Category
Technology
-
view
511 -
download
0
Transcript of Diving into HHVM Extensions (PHPNW Conference 2015)
Diving intoHHVM Extensions
James TitcumbPHPNW Conference 2015
James Titcumbwww.jamestitcumb.comwww.roave.comwww.phphants.co.ukwww.phpsouthcoast.co.uk@asgrim
Who is this guy?
First, some background...
source: Microsoft
How PHP works
PHP code
OpCache
Execute (VM)
Lexer + Parser
Compiler
How HHVM worksPHP code
OpCache
Execute (VM)
Lexer + Parser
Compiler
JIT
Execute (Native)
Hack features
● Return/parameter type hints● ?nullable● Collections (Vectors, Sets, Maps, etc.)● Async functions● Enums● Generics● Lambda expressions ==>● XHP● more stuff
The HHVM codebase
The Engine
hphp/parser
The Engine
hphp/parserhphp/compiler
The Engine
hphp/parserhphp/compilerhphp/hhbbc
The Engine
hphp/parserhphp/compilerhphp/hhbbchphp/hhvm
The Engine
hphp/parserhphp/compilerhphp/hhbbchphp/hhvmhphp/runtime/vm
The Engine
hphp/parserhphp/compilerhphp/hhbbchphp/hhvmhphp/runtime/vmhphp/runtime/vm/jit
The Extensions
hphp/runtime/ext
The Extensions
hphp/runtime/exthphp/system/php
Compile HHVM?
source: https://xkcd.com/303/
My First HHVM Extension™
config.cmake
HHVM_EXTENSION(calc ext_calc.cpp)
ext_calc.cpp#include "hphp/runtime/ext/extension.h"
namespace HPHP {
static class CalcExtension : public Extension {
public:
CalcExtension(): Extension("calc") {}
virtual void moduleInit() {}
} s_calc_extension;
HHVM_GET_MODULE(calc);
} // namespace HPHP
ext_calc.cpp#include "hphp/runtime/ext/extension.h"
namespace HPHP {
static class CalcExtension : public Extension {
public:
CalcExtension(): Extension("calc") {}
virtual void moduleInit() {}
} s_calc_extension;
HHVM_GET_MODULE(calc);
} // namespace HPHP
ext_calc.cpp#include "hphp/runtime/ext/extension.h"
namespace HPHP {
static class CalcExtension : public Extension {
public:
CalcExtension(): Extension("calc") {}
virtual void moduleInit() {}
} s_calc_extension;
HHVM_GET_MODULE(calc);
} // namespace HPHP
ext_calc.cpp#include "hphp/runtime/ext/extension.h"
namespace HPHP {
static class CalcExtension : public Extension {
public:
CalcExtension(): Extension("calc") {}
virtual void moduleInit() {}
} s_calc_extension;
HHVM_GET_MODULE(calc);
} // namespace HPHP
ext_calc.cpp#include "hphp/runtime/ext/extension.h"
namespace HPHP {
static class CalcExtension : public Extension {
public:
CalcExtension(): Extension("calc") {}
virtual void moduleInit() {}
} s_calc_extension;
HHVM_GET_MODULE(calc);
} // namespace HPHP
… that’s it.
<?php
var_dump(extension_loaded('calc'));
test.php
Compile it.(waaaat?!)
Compile & run the test#!/bin/bash
hphpize
cmake . && make
/usr/bin/hhvm \
-d extension_dir=. \
-d hhvm.extensions[]=calc.so \
test.php
Compile & run the test$ ./build.sh
bool(true)
$
Hack it!
source: http://goo.gl/kUAxBI
config.cmake
HHVM_EXTENSION(calc ext_calc.cpp)HHVM_SYSTEMLIB(calc ext_calc.php)
ext_calc.cpp#include "hphp/runtime/ext/extension.h"
namespace HPHP {
static class CalcExtension : public Extension {
public:
CalcExtension(): Extension("calc") {}
virtual void moduleInit() {
loadSystemlib();
}
} s_calc_extension;
HHVM_GET_MODULE(calc);
} // namespace HPHP
ext_calc.php<?hh
function calc_sub(int $a, int $b): int {
return $a - $b;
}
… that’s it.
<?php
var_dump(extension_loaded('calc'));
var_dump(calc_sub(5, 3));
test.php
Compile & run the test$ ./build.sh
bool(true)
int(2)
$
Sprinkle some C++ infor good measure
ext_calc.cpp// ... SNIP ...
virtual void moduleInit() {
HHVM_FE(calc_add);
loadSystemlib();
}
// ... SNIP ...
ext_calc.cpp// ... SNIP ...
static int64_t HHVM_FUNCTION(calc_add, int64_t a, int64_t b) {
return a + b;
}
// ... SNIP ...
in php extensions...PHP_FUNCTION(calc_add)
{
// ... SNIP ...
#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &a, &b) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_LONG(a)
Z_PARAM_LONG(b)
ZEND_PARSE_PARAMETERS_END();
#endif
// ... SNIP ...
ext_calc.php<?hh
<<__Native>>
function calc_add(int $a, int $b): int;
function calc_sub(int $a, int $b): int {
return $a - $b;
}
… that’s it.
<?php
var_dump(extension_loaded('calc'));
var_dump(calc_sub(5, 3));
var_dump(calc_add(5, 3));
test.php
Compile & run the test$ ./build.sh
bool(true)
int(2)
int(8)
$
Debugging?!
source: http://www.gnu.org/software/gdb/
Add debug mode#!/bin/bash
hphpize
cmake \
-DCMAKE_C_FLAGS="-O0 -ggdb3" \
-DCMAKE_CXX_FLAGS="-O0 -ggdb3" \
-DCMAKE_BUILD_TYPE=Debug \
.
make
# ... SNIP ...
Run with gdb$ gdb --args \
/usr/bin/hhvm \
-d extension_dir=. \
-d hhvm.extensions[]=calc.so \
test.php
GNU gdb (Ubuntu 7.9-1ubuntu1) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.
org/licenses/gpl.html>
--- snip ---
Reading symbols from /usr/bin/hhvm...done.
(gdb)
Breakpoints(gdb) b ext_calc.cpp:6
No source file named ext_calc.cpp.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (ext_calc.cpp:6) pending.
(gdb)
Running(gdb) r
Starting program: /usr/bin/hhvm -d extension_dir=. -d hhvm.extensions\[\]
=calc.so smoke.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 2, HPHP::f_calc_add (a=5, b=3) at /home/james/workspace/hhvm-
calc/ext_calc.cpp:6
6 return a + b;
(gdb) p a
$1 = 5
(gdb) p b
$2 = 3
(gdb)
Handy commands
c continue / step out
n step over
s step into
p x print the value of a variable (x)
set x = y set a variable (x) to value (y)
bt print backtrace
q quit :)
When NOT to write extensions
When to write extensions
BUCKLE UP.
source: https://goo.gl/x7Srhe
Integrating OpenGLinto an HHVM extension
Don’t try this in production!
srsly.
Extension
Browser
What I did
huh?!
Make it OOOOOOO
ext_foo.php<?hh
<<__NativeData("Foo")>>
class Foo {
<<__Native>>
public function bar(): int;
}
C++ object!==
PHP object
source: http://goo.gl/HORwLQ
HHVM Universe
<?php
$o = new Foo();$o->bar();
PHP Landclass Foo {public: Foo() {} ~Foo() {}
int value = 5;}
Planet C++
int64_t HHVM_METHOD(Foo,bar){ auto data = Native::data<Foo>(this_);
return data->value;}
Time Vortex!?!?!
C++ object !== PHP object
HHVM Universe
<?php
$o = new Foo();$o->bar();
PHP Landclass Foo {public: Foo() {} ~Foo() {}
int value = 5;}
Planet C++
int64_t HHVM_METHOD(Foo,bar){ auto data = Native::data<Foo>(this_);
return data->value;}
Time Vortex!?!?!
C++ object !== PHP object
HHVM Universe
<?php
$o = new Foo();$o->bar();
PHP Landclass Foo {public: Foo() {} ~Foo() {}
int value = 5;}
Planet C++
int64_t HHVM_METHOD(Foo,bar){ auto data = Native::data<Foo>(this_);
return data->value;}
Time Vortex!?!?!
C++ object !== PHP object
HHVM Universe
<?php
$o = new Foo();$o->bar();
PHP Landclass Foo {public: Foo() {} ~Foo() {}
int value = 5;}
Planet C++
int64_t HHVM_METHOD(Foo,bar){ auto data = Native::data<Foo>(this_);
return data->value;}
Time Vortex!?!?!
C++ object !== PHP object
this slide is intentionally left blank
ext_foo.php<?hh
class Foo {
private int $value
public function bar(): int
{
return $this->value;
}
}
Demo?
source: http://goo.gl/7gWfNz
Resources
● OpenGL Tutorial○ http://www.opengl-tutorial.org/
● HHVM Example Extension○ https://github.com/hhvm/extension-example
● Sara Golemon - HHVM extension blog series○ http://blog.golemon.com/2015/01/hhvm-extension-writing-part-iii.html
● Derick Rethans’ extension API cookbook○ https://github.com/derickr/hhvm-hni-cookbook
● The official API documentation○ https://github.com/facebook/hhvm/wiki/Extension%20API
● Journey of a Thousand Bytecodes○ http://hhvm.com/blog/6323/the-journey-of-a-thousand-bytecodes
Any questions? :)
https://joind.in/15434James Titcumb @asgrim