實戰 hhvm extension php conf 2014

109
實戰 HHVM Extension Ricky Su @phpconf2014

Upload: ricky-su

Post on 28-Nov-2014

120 views

Category:

Internet


2 download

DESCRIPTION

HHVM 是 Facebook 開發的一個高效能 PHP 虛擬機用來取代行之有年的 Zend Engine。 但是,在獲得更高效能的同時也意味著原本 PECL 上的大量 Extension 必須一一改寫。 藉由這個議程可以了解到如何透過 HNI 界面,混用 C++ 以及 Hack Lang。 在效能以及開發速度上取得平衡,撰寫出屬於自己的 HHVM Extension。

TRANSCRIPT

Page 1: 實戰 Hhvm extension   php conf 2014

實戰 HHVM Extension

Ricky Su@phpconf2014

Page 2: 實戰 Hhvm extension   php conf 2014

About me

Ricky 是我 哥

● Symfony 愛好者

● PHP也有Day 固定攝影師。

● 目前在 擔任高級水電工。

[email protected]

● http://www.facebook.com/ricky.su.35

● http://ricky.ez2.us/ (目前Server掛點中)

玩體驗

Page 3: 實戰 Hhvm extension   php conf 2014

HHVM是什麼?

Page 4: 實戰 Hhvm extension   php conf 2014

● 由 Facebook 於 2010年2月2日發布

● 將 PHP 轉換成 C++,再透過 g++ 編

譯執行檔。

● 於2013年2月19日被官方棄用。

HipHop (HPHPc)

Page 5: 實戰 Hhvm extension   php conf 2014

● 透過 JIT 的方式加速 PHP 執行。

● 運行速度已經超越 HPHPc。

● 除了 PHP 外,還支援了 Hack Lang。

● 只支援 x64 平台,未來會支援 ARM。

● 目前 Facebook 的 PHP 程式皆運行在

HHVM 上。

HHVM

Page 6: 實戰 Hhvm extension   php conf 2014

HHVM != PHP (Zend Engine)

Page 7: 實戰 Hhvm extension   php conf 2014

HHVM 的執行效能?

Page 8: 實戰 Hhvm extension   php conf 2014

fibonacci(40) 殘酷考驗

Page 9: 實戰 Hhvm extension   php conf 2014

fibonacci(40)

<?php function fibonacci($n) { return $n<2?$n:fibonacci($n-1)+fibonacci($n-2); }

Page 10: 實戰 Hhvm extension   php conf 2014

HHVM benchmark

Less is better

Page 11: 實戰 Hhvm extension   php conf 2014

HHVM Extension benchmark

Less is better

Page 12: 實戰 Hhvm extension   php conf 2014

但是開發

HHVM Extension

Page 13: 實戰 Hhvm extension   php conf 2014

有個東西一定要了解

Page 14: 實戰 Hhvm extension   php conf 2014

Hack Lang

Page 15: 實戰 Hhvm extension   php conf 2014

Hack = 強型態的 PHP

Page 16: 實戰 Hhvm extension   php conf 2014

Hack Lang

<?hhfunction fibonacci(int $n):int{ return $n<2?$n:fibonacci($n-1)+fibonacci($n-2); }

Page 17: 實戰 Hhvm extension   php conf 2014

Hack Lang

<?hhfunction print_nl(?string $n = null): void{ echo "$n\n";}

Page 18: 實戰 Hhvm extension   php conf 2014

Hack Lang Reference

http://goo.gl/PPB64m

Page 19: 實戰 Hhvm extension   php conf 2014

HHVM Extension requirement

● x64 OS● gcc >= 4.7.3● g++ >= 4.7.3● cmake >= 2.8.3

Page 20: 實戰 Hhvm extension   php conf 2014

HHVM Extension

寫起來很複雜嗎

Page 21: 實戰 Hhvm extension   php conf 2014

只要三個檔案

Page 22: 實戰 Hhvm extension   php conf 2014

就可以寫出

fibonacci

Page 23: 實戰 Hhvm extension   php conf 2014

config.cmakeHHVM_EXTENSION( fibonacci fibonacci.cpp)HHVM_SYSTEMLIB( fibonacci ext_fibonacci.php)

Page 24: 實戰 Hhvm extension   php conf 2014

ext_fibonacci.php<?hh<<__Native>> function fibonacci(int $n): int;

Page 25: 實戰 Hhvm extension   php conf 2014

fibonacci.cpp#include "hphp/runtime/base/base-includes.h"namespace HPHP {static int64_t HHVM_FUNCTION(fibonacci, int64_t n) { return n<2?n:HHVM_FN(fibonacci)(n-2) + HHVM_FN(fibonacci)(n-1);}static class FibonacciExtension : public Extension { public: FibonacciExtension() : Extension("fibonacci") {} virtual void moduleInit() { HHVM_FE(fibonacci); loadSystemlib(); }} s_fibonacci_extension;HHVM_GET_MODULE(fibonacci)} // namespace HPHP

Page 26: 實戰 Hhvm extension   php conf 2014

build extension

$ hphpize$ cmake .$ make && make install

Page 27: 實戰 Hhvm extension   php conf 2014

config.cmakeHHVM_EXTENSION( fibonacci fibonacci.cpp foo.cpp bar.cpp other.cpp)

extensionname

Page 28: 實戰 Hhvm extension   php conf 2014

config.cmakeHHVM_EXTENSION( fibonacci fibonacci.cpp foo.cpp bar.cpp other.cpp)

cpp files

Page 29: 實戰 Hhvm extension   php conf 2014

config.cmakeHHVM_SYSTEMLIB( fibonacci ext_fibonacci.php)

PHP檔案只能一個而且命名必須是 ext_ 開頭

Page 30: 實戰 Hhvm extension   php conf 2014

HNI (HHVM Native Interface)<?hh<<__Native>> function fibonacci(int $n): int;

function echo_ fibonacci(int $n): void{ echo fibonacci($n);}

Page 31: 實戰 Hhvm extension   php conf 2014

register extenstionstatic class FibonacciExtension : public Extension { public: FibonacciExtension() : Extension("fibonacci") {} virtual void moduleInit() {

HHVM_FE(fibonacci);

loadSystemlib(); }} s_fibonacci_extension;HHVM_GET_MODULE(fibonacci)

Page 32: 實戰 Hhvm extension   php conf 2014

register extenstionstatic class FibonacciExtension : public Extension { public: FibonacciExtension() : Extension("fibonacci") {} virtual void moduleInit() {

HHVM_FE(fibonacci);

loadSystemlib(); }} s_fibonacci_extension;HHVM_GET_MODULE(fibonacci)

定義函數

Page 33: 實戰 Hhvm extension   php conf 2014

register extenstionstatic class FibonacciExtension : public Extension { public: FibonacciExtension() : Extension("fibonacci") {} virtual void moduleInit() { HHVM_FE(fibonacci);

HHVM_FE(foo);

loadSystemlib(); }} s_fibonacci_extension;HHVM_GET_MODULE(fibonacci)

如果有還有其他函數接著定義

Page 34: 實戰 Hhvm extension   php conf 2014

register extenstionstatic class FibonacciExtension : public Extension { public: FibonacciExtension() : Extension("fibonacci") {} virtual void moduleInit() {

HHVM_FE(fibonacci);

loadSystemlib(); }} s_fibonacci_extension;HHVM_GET_MODULE(fibonacci)

讀取HNI

Page 35: 實戰 Hhvm extension   php conf 2014

implement function

static int64_t HHVM_FUNCTION(fibonacci, int64_t n) { return n<2?n:HHVM_FN(fibonacci)(n-2) + HHVM_FN(fibonacci)(n-1);}

Page 36: 實戰 Hhvm extension   php conf 2014

implement function

static int64_t HHVM_FUNCTION(fibonacci, int64_t n) { return n<2?n:HHVM_FN(fibonacci)(n-2) + HHVM_FN(fibonacci)(n-1);}

函數回傳值型態

Page 37: 實戰 Hhvm extension   php conf 2014

implement function

static int64_t HHVM_FUNCTION(fibonacci, int64_t n) { return n<2?n:HHVM_FN(fibonacci)(n-2) + HHVM_FN(fibonacci)(n-1);}

函數名稱

Page 38: 實戰 Hhvm extension   php conf 2014

implement function

static int64_t HHVM_FUNCTION(fibonacci, int64_t n) { return n<2?n:HHVM_FN(fibonacci)(n-2) + HHVM_FN(fibonacci)(n-1);}

參數型態定義

Page 39: 實戰 Hhvm extension   php conf 2014

implement function

static int64_t HHVM_FUNCTION(foo, int64_t n, const String &n2) { // ...}

如果有多個參數接著定義

Page 40: 實戰 Hhvm extension   php conf 2014

型態對應PHP Type C++ Parameter

TypeC++ Return

Typevoid N/A void

bool bool bool

int int64_t int64_t

float double double

string const String & String

array const Array & Array

resource const Resource & Resource

object const Object & Object

mixed const Variant & Variant

Page 41: 實戰 Hhvm extension   php conf 2014

以上官方文件

都可以查到

Page 42: 實戰 Hhvm extension   php conf 2014

但是

Page 43: 實戰 Hhvm extension   php conf 2014

也只能查到這些了

Page 44: 實戰 Hhvm extension   php conf 2014

如果要知道更多

Page 45: 實戰 Hhvm extension   php conf 2014

RTFSC

Page 46: 實戰 Hhvm extension   php conf 2014
Page 47: 實戰 Hhvm extension   php conf 2014

接下來要踩地雷了

Page 48: 實戰 Hhvm extension   php conf 2014

Native Class

Page 49: 實戰 Hhvm extension   php conf 2014

HNI<?hhclass foo { protected ?mixed $bar; <<__Native>> public function __construct(mixed $bar): void; <<__Native>> public function getBarNative(): ?mixed; public function getBar():?mixed { return $this->bar; }}

Page 50: 實戰 Hhvm extension   php conf 2014

register extenstionstatic class FooExtension : public Extension { public: FooExtension() : Extension("foo") {} virtual void moduleInit() { HHVM_ME(foo, __construct); HHVM_ME(foo, getBarNative); loadSystemlib(); }} s_foo_extension;HHVM_GET_MODULE(foo)

Page 51: 實戰 Hhvm extension   php conf 2014

register extenstionstatic class FooExtension : public Extension { public: FooExtension() : Extension("foo") {} virtual void moduleInit() { HHVM_ME(foo, __construct); HHVM_ME(foo, getBarNative); loadSystemlib(); }} s_foo_extension;HHVM_GET_MODULE(foo)

註冊 foo__construct

Page 52: 實戰 Hhvm extension   php conf 2014

implement class method

static void HHVM_METHOD( __construct, const Variant &bar) { this_->o_set("bar", bar, "foo");}

Page 53: 實戰 Hhvm extension   php conf 2014

implement class method

static void HHVM_METHOD( __construct, const Variant &bar) { this_->o_set("bar", bar, "foo");}

對應 PHP 中的 $this

Page 54: 實戰 Hhvm extension   php conf 2014

implement class method

static void HHVM_METHOD( __construct, const Variant &bar) { this_->o_set("bar", bar, "foo");}

存入成員變數

Page 55: 實戰 Hhvm extension   php conf 2014

implement class method

static void HHVM_METHOD( __construct, const Variant &bar) { this_->o_set("bar", bar, "foo");}

$this->bar

Page 56: 實戰 Hhvm extension   php conf 2014

implement class method

static void HHVM_METHOD( __construct, const Variant &bar) { this_->o_set("bar", bar, "foo");}

$this->bar = $bar

Page 57: 實戰 Hhvm extension   php conf 2014

implement class method

static void HHVM_METHOD( __construct, const Variant &bar) { this_->o_set("bar", bar, "foo");}

指定目前的 context 為 foo

Page 58: 實戰 Hhvm extension   php conf 2014

implement class method

static Variant HHVM_METHOD(getBarNative) { return this_->o_get("bar", false, "foo");}

Page 59: 實戰 Hhvm extension   php conf 2014

implement class method

static Variant HHVM_METHOD(getBarNative) { return this_->o_get("bar", false, "foo");}

$this->bar

Page 60: 實戰 Hhvm extension   php conf 2014

implement class method

static Variant HHVM_METHOD(getBarNative) { return this_->o_get("bar", false, "foo");}

如果讀取 $this->bar

發生錯誤時是否要丟出 error

Page 61: 實戰 Hhvm extension   php conf 2014

implement class method

static Variant HHVM_METHOD(getBarNative) { return this_->o_get("bar", false, "foo");}

指定目前的 context 為 foo

Page 62: 實戰 Hhvm extension   php conf 2014

Type Casting

Page 63: 實戰 Hhvm extension   php conf 2014

Type Castingvar.toBoolean();

var.toDouble();

var.toString();

var.toInt64();

var.toArray();

Page 64: 實戰 Hhvm extension   php conf 2014

Object Access

Page 65: 實戰 Hhvm extension   php conf 2014

Object AccessC++ PHPobject.o_get(...) $object->...

object.o_set(...) $object->xxx = xxx

object.instanceof(class) object instanceof class

Page 66: 實戰 Hhvm extension   php conf 2014

String Access

Page 67: 實戰 Hhvm extension   php conf 2014

String AccessC++ PHPstring = “hello ” + “world” $string = “hello ” . ”world”

string += “foo” $string .= “foo”

string1 == string2 $string1 == $string2

string[1] $string[1]

string.substr(1, 2) substr($string, 1, 2)

string.size() strlen($string)

Page 68: 實戰 Hhvm extension   php conf 2014

Array Access

Page 69: 實戰 Hhvm extension   php conf 2014

Array AccessVariant var = array[1];

Variant var = array[String(“key”)];

Page 70: 實戰 Hhvm extension   php conf 2014

Array AccessC++ PHParray.set(1, var) $array[1] = $var

array.set(String(“key”), var) $array[“key”] = $var

array.append(var) $array[] = $var

array = make_packed_array(1, 2, “val”) $array = [1, 2, “val”]

array = Array::Create() $array = []

Page 71: 實戰 Hhvm extension   php conf 2014

Resource

Page 72: 實戰 Hhvm extension   php conf 2014

Resource data declarenamespace HPHP {

class InternalResourceData : public SweepableResourceData { public: virtual const String& o_getClassNameHook() const { return classnameof(); } DECLARE_RESOURCE_ALLOCATION(InternalResourceData) CLASSNAME_IS("InternalResourceData") InternalResourceData(FILE *file); virtual ~InternalResourceData(); FILE *getHandler();

private: FILE *file; };

}

Page 73: 實戰 Hhvm extension   php conf 2014

Resource data declarenamespace HPHP {

IMPLEMENT_OBJECT_ALLOCATION(InternalResourceData) InternalResourceData::InternalResourceData(FILE *file) { this->file = file; }

InternalResourceData::~InternalResourceData() { fclose(file); }

FILE *InternalResourceData::getHandler(){ return file; }

}

Page 74: 實戰 Hhvm extension   php conf 2014

Resource usagestatic Resource HHVM_FUNCTION(open_file, const String &filename) { FILE *file = fopen(filename.c_str(), "r"); Resource resource(NEWOBJ(InternalResourceData(file))); return resource;}

static String HHVM_FUNCTION(read_file, const Resource &resource) { FILE * file; InternalResourceData *resource_data = resource.getTyped<InternalResourceData>(); file = resource_data->getHandler(); // ...}

Page 75: 實戰 Hhvm extension   php conf 2014

Reference Counting

Page 76: 實戰 Hhvm extension   php conf 2014

Variables

Value$aref count = 1

$a = “some value”;

Page 77: 實戰 Hhvm extension   php conf 2014

Variables

Value$aref count = 2

$b = $a;

$b

Page 78: 實戰 Hhvm extension   php conf 2014

Variables

Value$aref count = 1

$b = null;

$b

Page 79: 實戰 Hhvm extension   php conf 2014

Variables

Value$aref count = 0

$a = null;

$b

Page 80: 實戰 Hhvm extension   php conf 2014

Variables

Value$aref count = 0

$a = null;

$b

delete value

Page 81: 實戰 Hhvm extension   php conf 2014

HHVM Variables

Variable ValueObject ObjectDataString StringDataArray ArrayData

Resource ResourceData

Page 82: 實戰 Hhvm extension   php conf 2014

Increase referenceObject var = some_object;

Object *var = new Object(some_object);

ObjectDara *value = some_object->get();

value->incRefCount();

Page 83: 實戰 Hhvm extension   php conf 2014

Decrease referenceObject *var = new Object(some_object);

delete var;

ObjectDara *value = some_object->get();

value->decRefAndRelease();

Page 84: 實戰 Hhvm extension   php conf 2014

HHVM密(ㄉ一ˋ)技(ㄌㄟˊ)

Page 85: 實戰 Hhvm extension   php conf 2014

HHVM Extension 第三方 Library

set callback

Page 86: 實戰 Hhvm extension   php conf 2014

HHVM Extension 第三方 Library

call callback

Page 87: 實戰 Hhvm extension   php conf 2014

HHVM Extension 第三方 Library

call callback

接著就GG了...Crash

Page 88: 實戰 Hhvm extension   php conf 2014

都是 they 的錯gcc -O2

Page 89: 實戰 Hhvm extension   php conf 2014

因為gcc -O2 預設開啟

omit-frame-pointer

Page 90: 實戰 Hhvm extension   php conf 2014

導致 HHVM rbp 指標出錯

Page 91: 實戰 Hhvm extension   php conf 2014

解決方法

Page 92: 實戰 Hhvm extension   php conf 2014

重新編譯第三方套件

Page 93: 實戰 Hhvm extension   php conf 2014

gcc 加上

-fno-omit-frame-pointer

Page 94: 實戰 Hhvm extension   php conf 2014

但請放棄這個念頭

Page 95: 實戰 Hhvm extension   php conf 2014

請改用神秘的

Page 96: 實戰 Hhvm extension   php conf 2014

JIT::VMRegAnchor _;

Page 97: 實戰 Hhvm extension   php conf 2014

VMRegAnchor

static void HHVM_FE(someFunction) { JIT::VMRegAnchor _; //then call 3rd party library;}

在呼叫第三方library之前加上這段就OK了。

Page 98: 實戰 Hhvm extension   php conf 2014

取得Global Variable

Page 99: 實戰 Hhvm extension   php conf 2014

取得Global VariableArray global(get_global_variables()->asArrayData());

Array _SERVER = global[StaticString("_SERVER")].toArray();

Array _GET = global[StaticString("_GET")].toArray();

Array _POST = global[StaticString("_POST")].toArray();

Page 100: 實戰 Hhvm extension   php conf 2014

取得 Constant

Page 101: 實戰 Hhvm extension   php conf 2014

取得 Constant#if HHVM_API_VERSION >= 20140829L //HHVM 3.3.0 #include "hphp/runtime/ext/std/ext_std_misc.h"#else // HHVM 3.2.0 #include "hphp/runtime/ext/ext_misc.h"#endif

Variant some_conatant = HHVM_FN(constant)(StaticString("SOME_CONSTANT"));

Page 102: 實戰 Hhvm extension   php conf 2014

呼叫 PHP 的某個函數

Page 103: 實戰 Hhvm extension   php conf 2014

呼叫 PHP 的某個函數

vm_call_user_func(StaticString("printf"), make_packed_array("%s %s", "hello", "world"));

printf(“%s %s”, “hello”, “world”);

Page 104: 實戰 Hhvm extension   php conf 2014

或是直接

call native function

Page 105: 實戰 Hhvm extension   php conf 2014

hphp/runtime/ext/*.h這裡幾乎實作了所有php的函數

Page 106: 實戰 Hhvm extension   php conf 2014

Call native function#include "hphp/runtime/ext/std/ext_std_variable.h"

HHVM_FN(print_r)(var); //print_r($var);

Page 107: 實戰 Hhvm extension   php conf 2014

還有更多地雷由您來踩

Page 108: 實戰 Hhvm extension   php conf 2014

有問題嗎?

Page 109: 實戰 Hhvm extension   php conf 2014

Thanks