hack/hhvm 入門

41
Hack/HHVM 入門 2014/05/02 社内勉強会資料 1

Upload: y-uti

Post on 05-Dec-2014

1.906 views

Category:

Technology


0 download

DESCRIPTION

プログラミング言語 Hack と、その仮想機械である HHVM の紹介です。勤務先の社内勉強会での発表資料に加筆したものです。

TRANSCRIPT

Page 1: Hack/HHVM 入門

Hack/HHVM 入門

2014/05/02 社内勉強会資料 1

Page 2: Hack/HHVM 入門

はじめにHack とは?◦ プログラミング言語である

◦ Facebook が作った

HHVM とは?◦ Hack プログラムを実行する VM である

$ /usr/bin/hhvm hello.hhHello, world!

2014/05/02 社内勉強会資料 2

Page 3: Hack/HHVM 入門

Hack はどんな言語?PHPの言語拡張◦ 型アノテーション

◦ ジェネリクス

◦ Null許容型

◦ コンテナ型

◦ etc.

したがって PHP のプログラムは Hack のプログラムでもある

$ /usr/bin/hhvm hello.phpHello, world!

2014/05/02 社内勉強会資料 3

Page 4: Hack/HHVM 入門

今日の話HHVM を使う◦ Yet another PHP interpreter として

プログラミング言語 Hack

2014/05/02 社内勉強会資料 4

Page 5: Hack/HHVM 入門

HHVMを使う

2014/05/02 社内勉強会資料 5

Page 6: Hack/HHVM 入門

メリットは?

2014/05/02 社内勉強会資料 6

速い

Page 7: Hack/HHVM 入門

ベンチマーク

2014/05/02 社内勉強会資料 7

17.9

3

14.0

0

20.1

9

15.8

1

15.1

0

12.5

4

13.7

7

10.6

4

2.1

6

14.1

3

1.9

2

2.2

1

9.3

7

7.7

2

2.8

1

5.4

5

#N

/A

10.5

3

5.7

0

2.4

8

0

5

10

15

20

25

PHP と HHVM の実行時間の比較 [秒]

PHP HHVM

The Computer Language Benchmarks Game

http://benchmarksgame.alioth.debian.org/各問題の PHP 最速コードを利用

Page 8: Hack/HHVM 入門

インストール手順Ubuntu Server 13.10◦ Hack のウェブサイトの情報どおり

◦ 現時点では素直に Ubuntu を使うのがオススメ◦ Debianでも大丈夫だろうと思うが試していない

CentOS 6.5◦ 試したが上手くいかなかった

◦ CentOSのパッケージが古すぎる◦ 公式から入れようとしたら binutilsのバージョン違いを解決できなかった

◦ hop5 という野良リポジトリから一応は入ったが Apache と連携できず

Windows / Macintosh / その他◦ 試していない

2014/05/02 社内勉強会資料 8

Page 9: Hack/HHVM 入門

Ubuntu Server 13.10ウェブサイトの手順どおり

◦ http://hhvm.com/blog/3203/nightly-packages

2014/05/02 社内勉強会資料 9

$ wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudoapt-key add -$ echo deb http://dl.hhvm.com/ubuntu saucy main | sudo tee /etc/apt/sources.list.d/hhvm.list$ sudo apt-get update$ sudo apt-get install hhvm-nightly

Page 10: Hack/HHVM 入門

動かすHello, world!

2014/05/02 社内勉強会資料 10

$ vi hello.hh<?hhprint "Hello, world!¥n";$ hhvm hello.hhHello, world!

$ vi hello.php<?phpprint "Hello, world!¥n";$ hhvm hello.phpHello, world!

Page 11: Hack/HHVM 入門

Apache との連携FastCGI (mod_fcgi)を使う◦ 電子書籍が参考になった

◦ 米林正明, Facebook発新プログラミング言語「Hack」スタートアップガイド

◦ https://gihyo.jp/dp/ebook/2014/978-4-7741-6445-8

◦ 400 円

2014/05/02 社内勉強会資料 11

$ sudo apt-get install libapache2-mod-fcgid$ cd /etc/apache2/mods-enabled$ sudo ln -s ../mods-available/proxy.load$ sudo ln -s ../mods-available/proxy_fcgi.load$ sudo ln -s ../mods-available/hhvm_proxy_fcgi.conf$ sudo service hhvm start$ sudo service apache2 restart

Page 12: Hack/HHVM 入門

確認するphpinfo()◦ HHVMでは単に HipHopと表示されるだけ

2014/05/02 社内勉強会資料 12

$ sudo vi /var/www/phpinfo.php<?phpphpinfo();$ curl http://localhost/phpinfo.phpHipHop

Page 13: Hack/HHVM 入門

詳細: HHVM サーバこんなプロセスが動いている

2014/05/02 社内勉強会資料 13

$ ps –ef | grep hhvm | 見やすいように切り貼り

/usr/bin/hhvm--config /etc/hhvm/server.ini--user www-data--mode daemon -vPidFile=/var/run/hhvm/pid

Page 14: Hack/HHVM 入門

詳細: サーバ設定

2014/05/02 社内勉強会資料 14

$ cat /etc/hhvm/server.ini; php options

pid = /var/run/hhvm/pid

; hhvm specific

hhvm.server.port = 9000hhvm.server.type = fastcgihhvm.server.default_document = index.phphhvm.log.level = Warninghhvm.log.always_log_unhandled_exceptions = truehhvm.log.runtime_error_reporting_level = 8191hhvm.log.use_log_file = truehhvm.log.file = /var/log/hhvm/error.loghhvm.repo.central.path = /var/run/hhvm/hhvm.hhbchhvm.mysql.typed_results = false

Page 15: Hack/HHVM 入門

詳細: Apache の Proxy 設定

2014/05/02 社内勉強会資料 15

$ cat /etc/apache2/mods-enabled/hhvm_proxy_fcgi.confProxyPassMatch^/(.*¥.(hh|php)(/.*)?)$ fcgi://127.0.0.1:9000/var/www/$1

Page 16: Hack/HHVM 入門

Symfonyを乗せてみるウェブサイトの説明どおりにインストール

◦ http://symfony.com/doc/current/quick_tour/the_big_picture.html

2014/05/02 社内勉強会資料 16

$ curl -sS https://getcomposer.org/installer | php$ ./composer.phar create-project symfony/framework-standard-edition /var/www/symfony/ ~2.4

いつもの設定

$ chmod 777 /var/www/symfony/app/{cache,logs}$ sudo vi /etc/hhvm/server.ini; php options

pid = /var/run/hhvm/piddate.timezone = Asia/Tokyo

Page 17: Hack/HHVM 入門

確認するhttp://localhost/symfony/web/app_dev.php/demo/hello/World

2014/05/02 社内勉強会資料 17

Page 18: Hack/HHVM 入門

PHP との互換性ウェブサイトの PHP 関数リファレンスを参照

◦ http://docs.hhvm.com/manual/en/phpfuncref.php

◦ 関数ごとに HHVM の対応状況が記載されている

2014/05/02 社内勉強会資料 18

Page 19: Hack/HHVM 入門

高速化のための約束トップレベルに処理を書かないこと◦ おそらく JIT の対象外

2014/05/02 社内勉強会資料 19

$ cat test1.hh<?hh

for($i=0;$i<10000000;++$i);

$ time hhvm test1.hh

real 0m1.410suser 0m1.371ssys 0m0.036s

$ cat test2.hh<?hhfunction test() {for($i=0;$i<10000000;++$i);}test();$ time hhvm test2.hh

real 0m0.186suser 0m0.147ssys 0m0.036s

実は最初のベンチマーク結果には嘘があります

Page 20: Hack/HHVM 入門

ベンチマーク (真実)

2014/05/02 社内勉強会資料 20

17.9

3

14.0

0

20.1

9

15.8

1

15.1

0

12.5

4

13.7

7

10.6

4

2.1

6

14.1

3

1.8

4 2

6.6

7

9.4

0

7.4

4

60.4

5

24.1

7

#N

/A

10.6

7

7.8

6

2.4

5

1.9

2

2.2

1

9.3

7

7.7

2

2.8

1

5.4

5

#N

/A

10.5

3

5.7

0

2.4

8

0

10

20

30

40

50

60

70

PHP と HHVM の実行時間の比較 [秒]

PHP PHP on HHVM HHVM

Page 21: Hack/HHVM 入門

プログラミング言語 Hack

2014/05/02 社内勉強会資料 21

Page 22: Hack/HHVM 入門

メリットは?

2014/05/02 社内勉強会資料 22

静的な型検査

すぐ炎上するので小さな声で言います

Page 23: Hack/HHVM 入門

Hack の言語機能ウェブサイトのリファレンス

◦ http://docs.hhvm.com/manual/en/hacklangref.php

◦ これを読めばだいたいわかる

2014/05/02 社内勉強会資料 23

Page 24: Hack/HHVM 入門

独習 Hackウェブサイトのチュートリアル

◦ http://hacklang.org/tutorial

◦ これをやればだいたいわかる

2014/05/02 社内勉強会資料 24

◦ エディタになっていて自由にコードを書ける

Page 25: Hack/HHVM 入門

独断と偏見による分類静的型に関する機能

◦ Type Annotation

◦ Generics

◦ Nullable

◦ Type Aliasing

さまざまな複合データ型

◦ Collections

◦ Vector, Map, Set, Pair

◦ Shapes

◦ Tuples

その他 (わりとどーでもいい)

◦ Hack Modes

◦ Async

◦ Continuations

◦ Traits / Trait Requirements

◦ Lambda Expressions

2014/05/02 社内勉強会資料 25

以下のスライドでは下線を引いた機能をピックアップして紹介

Page 26: Hack/HHVM 入門

Type Annotation

型を書くのは・・・◦ 関数定義の引数と戻り値

◦ クラスのメンバ変数

関数内部のローカル変数には型を書かない◦ 型を書かない != 型が付かない

◦ 書かなくても自動的に推論して型エラーを検出する

2014/05/02 社内勉強会資料 26

$ vi test.hh<?hhfunction add(int $a, int $b): int {$c = $a + $b;return $c;

}

Page 27: Hack/HHVM 入門

型検査の実行hh_clientを使う

2014/05/02 社内勉強会資料 27

$ touch .hhconfig$ hh_client checkNo errors!$ hh_client stop

◦ 裏側で hh_serverプロセスが起動し .hhconfig以下を監視するらしい

◦ hh_client stop で hh_serverプロセスを停止する

Page 28: Hack/HHVM 入門

型エラーの検出

◦ 関数の戻り値の型は intでなければいけない

◦ ところが、引数の $b が float なので $c は int + float = float である

◦ というわけで、戻り値の型が正しくないと文句を言っている

2014/05/02 社内勉強会資料 28

$ vi test.hh<?hhfunction add_error(int $a, float $b): int {$c = $a + $b;return $c;

}

$ hh_client check/.../test.hh:4:10,11: Invalid return type/.../test.hh:2:39,41: This is an int/.../test.hh:2:28,32: It is incompatible with a float

Page 29: Hack/HHVM 入門

型エラーの修正

◦ intval関数を入れることで $c の型が intになった

◦ 単に intにキャストする方法でも同じ

2014/05/02 社内勉強会資料 29

$ vi test.hh<?hhfunction add_error_fixed(int $a, float $b): int {$c = intval($a + $b);return $c;

}

$ hh_client checkNo errors!

Page 30: Hack/HHVM 入門

Nullable

◦ 型の先頭に ? を書くと null 許容型になる

このプログラムには型エラーがあります (次のスライドで説明)

2014/05/02 社内勉強会資料 30

$ vi test.hh<?hhfunction add_null(?int $a, int $b): int {$c = $a + $b;return $c;

}

Page 31: Hack/HHVM 入門

Nullable (型エラーの検出)

◦ $a は算術演算子 “+” で使われるので intか float でなければいけない

◦ ところが $a は null 許容型である

◦ というわけで、型のエラーだと文句を言っている

2014/05/02 社内勉強会資料 31

<?hhfunction add_null(?int $a, int $b): int {

$c = $a + $b;return $c;

}

$ hh_client check/.../test.hh:3:8,9: Typing error/.../test.hh:3:8,9: This is a num (int/float) because

this is used in an arithmetic operation/.../test.hh:2:19,22: It is incompatible with a nullable

type

Page 32: Hack/HHVM 入門

Nullable (型エラーの修正)

◦ null のときは 0を代入することで、演算の箇所での $a は intになった

◦ 三項演算子を使って書いても同じ

2014/05/02 社内勉強会資料 32

$ vi test.hh<?hhfunction add_null(?int $a, int $b): int {if ($a == null) {$a = 0;

}$c = $a + $b;return $c;

}

$ hh_client checkNo errors!

Page 33: Hack/HHVM 入門

Shape

2014/05/02 社内勉強会資料 33

$ vi test.hh<?hhtype person = shape('name' => string, 'age' => int);

function is_adult(person $p) : bool {return $p['age'] >= 20;

}

function test() {$taro = shape('name' => 'Taro', 'age' => 25);echo is_adult($taro) . "¥n";

}

◦ Key の値が固定された配列

◦ 右辺の型に person という名前を付けている (type aliasing; 後述)

Page 34: Hack/HHVM 入門

Shape (型エラーの検出)

◦ $no_nameには “name” フィールドが無い

◦ is_adult関数の引数 $p は person 型で “name” フィールドが定義済み

◦ というわけで、引数の型が正しくないと文句を言っている

2014/05/02 社内勉強会資料 34

function is_adult(person $p) : bool { ... }

function test() {$no_name = shape('age' => 25); // name が無い

echo is_adult($no_name) . "¥n";}

$ hh_client check/.../test.hh:10:17,24: Invalid argument/.../test.hh:9:14,18: The field 'name' is missing/.../test.hh:4:19,24: The field 'name' is defined

Page 35: Hack/HHVM 入門

Shape (初期化後の代入)

◦ 左は OK, 右は NG

◦ Shape のキーには定数文字列しか使えない

2014/05/02 社内勉強会資料 35

function test() {$taro = shape();$taro['name'] = 'Taro';$taro['age'] = 25;echo is_adult($taro)."¥n";

}

function test() {$taro = shape();$taro['na'.'me'] = 'Taro';$taro['age'] = 25;echo is_adult($taro)."¥n";

}

$ hh_client check/.../test.hh:10:9,19: Was expecting a constant string (for shape access)

Page 36: Hack/HHVM 入門

Type Aliasing

◦ 右辺のデータ型に左辺の別名を付ける

◦ プログラムが分かりやすくなる

2014/05/02 社内勉強会資料 36

$ vi test.hh<?hhtype point = shape('x' => int, 'y' => int);

function new_point(int $x, int $y) : point {return shape('x' => $x, 'y' => $y);

}

function get_x(point $p) : int { return $p['x']; }function get_y(point $p) : int { return $p['y']; }

Page 37: Hack/HHVM 入門

Type Aliasing (newtype)

◦ newtypeを使うと、ファイルの外側からは右辺が見えなくなる

◦ プログラムのモジュール化に役立つ

2014/05/02 社内勉強会資料 37

$ vi test.hh<?hhnewtype point = shape('x' => int, 'y' => int);

function new_point(int $x, int $y) : point {return shape('x' => $x, 'y' => $y);

}

function get_x(point $p) : int { return $p['x']; }function get_y(point $p) : int { return $p['y']; }

Page 38: Hack/HHVM 入門

Type Aliasing (型エラーの検出)

◦ point の実体が shape(‘x’ => int, …) だということは隠されている

◦ というわけで、$p はコンテナではなく point だと文句を言っている

2014/05/02 社内勉強会資料 38

<?hhrequire 'test.hh';

function main() : void {$p = new_point(1, 2);$p['x'] = 3;

}

$ hh_client check/.../main.hh:6:3,9: This is not a container, this is an object of type point/.../main.hh:5:38,42: You might want to check this out

Page 39: Hack/HHVM 入門

補足

2014/05/02 社内勉強会資料 39

Page 40: Hack/HHVM 入門

hh_clientと HHVMHHVM では実行開始時に型検査するわけではない◦ 関数の先頭で仮引数と実引数の型が合致しているか検査

◦ 関数を抜けるときに戻り値の型が合致しているか検査

hh_clientがエラーにするコードも HHVM では実行できる

2014/05/02 社内勉強会資料 40

$ cat type_error.hh<?hhfunction test($cond): int { return $cond ? 1 : 'foo'; }print test($argv[1]) . "¥n";$ hhvm type_error.hh 11$ hhvm type_error.hh 0Fatal error: Value returned from test() must be of type int, string given in /.../type_error.hh on line 3

Page 41: Hack/HHVM 入門

おわり

2014/05/02 社内勉強会資料 41