Posted at

HHVM/Hack 運用時の設定について


HHVMの設定について理解しよう!

HHVMを商用環境や、または導入にあたってただ使うだけでは障害発生時や、

パフォーマンスチューニング等の対応ができなくなってしまいます。

実際に導入するにあたって、設定の項目などをみていきます。


HHVM / PHP information

利用する方、している方はご存知のコマンドですが、一応・・。

PHPの場合は、CLIで次のコマンドでPHPの情報が表示されるのはみなさんご存知だと思います。

$ php -i

HHVMの場合は、以下のコマンドです。

$ hhvm --info

これから紹介していく項目の設定内容はこのコマンドで確認しながら進めていくといいでしょう。


PHP7互換モード

3.30以降のバージョンでは使うことがなくなると思いますが、

現在のHHVM環境でPHP7互換で動かしたい場合に指定します。

これを指定する場合は、HHVMのphp.iniに指定します。

PHP7のライブラリをどうしても使いたい、という時に利用するくらいです。

scalar型もPHP互換にできますが、Hackと同じではなく、あくまでPHPのものになります。

PHP7の互換を保ちつつ、scalar型はPHP7互換にしたくない場合などは下記の設定にするといいでしょう。

hhvm.php7.all = true

hhvm.php7.scalar_types = 0


Server Mode

HHVMはProxygenかFastCGIが選択できます。

それぞれの違いをみていきましょう。

ちなみに結構違います。


FastCGI

PHP環境に慣れていて、あまり環境を変えたくない場合はFastCGIの方が安全かもしれません。

FastCGIで動かしたい場合は、HHVMのphp.iniで下記の設定を記述します。

hhvm.server.port = 8080

hhvm.server.type = fastcgi

hhvm.server.port は、デフォルトだと80になりますので注意が必要です。

hhvm.server.type は、デフォルトはfastcgiではないため、こちらもPHP-FPM同様に利用したい場合は忘れずに指定してください。

nginxを利用する場合は、confは下記の様に記述しましょう。

    location ~ \.(hh|php)$ {

fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_read_timeout 120;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
include fastcgi_params;
}

PHPとそんなに変わりませんね


proxygen

コマンドでも簡単に利用できるサーバで、PHPのビルトインWebServerとは異なり、

Facebookが数年前にHTTPフレームワーク/サーバProxygenをオープンソース化したものです。

facebook/proxygen

Apache HTTP ServerなどのWebServerの代替というわけではありませんが、

アプリケーションサーバとして利用できるもの、と考えた方がいいでしょう。

例として、index.phpに次のコードを利用します。

<?hh // strict

<<__Entrypoint>>
function main(): void {
echo 'HHVM/Hack';
}

<<__EntryPoint>>はこれまでも紹介の中でも登場してきたAttributeです。

(HHVM3.30で <<__Entrypoint>>から<<__EntryPoint>>に)

これを実行すると main() が実行される、というものですね。

proxygenとしてコマンドで手っ取り早く動かしたい場合は、以下の様に実行できます。

$ hhvm -m server -p 8080 -d hhvm.server.source_root=/Path/To/HackProject/public -d hhvm.server.type=proxygen

ブラウザ等で http://127.0.0.1:8080 にアクセスしてみましょう。

Web Serverなしで稼働しているのがわかると思います。

次にHHVMのphp.iniでコマンドで指定したオプションと同じものを指定してHHVMを再起動させてみましょう。

hhvm.server.port = 8080

hhvm.server.source_root=/Path/To/HackProject/public

ブラウザからアクセスできるのが確認できます。


AdminServer

HHVMはproxygenで動作させると、HHVMのプロセス等を制御できるAdminServerが利用できます。(便利!)

これを利用するには、adminサーバ用のpasswordとportを指定しましょう。

hhvm.admin_server.port=9001

hhvm.admin_server.password=SomePassword

指定したportにアクセスすると、下記のものが利用できます。

/stop
stop the web server

instance-id
optional, if specified, instance ID has to match

/free-mem:
ask allocator to release unused memory to system

/prepare-to-stop:
ask the server to prepare for stopping

/flush-logs:
trigger batching log-writers to flush all content

/translate:
translate hex encoded stacktrace in 'stack' param

stack
required, stack trace to translate

build-id
optional, if specified, build ID has to match

bare
optional, whether to display frame ordinates

/build-id:
returns build id that's passed in from command line

/instance-id:
instance id that's passed in from command line

/compiler-id:
returns the compiler id that built this app

/repo-schema:
return the repo schema id used by this app

/ini-get-all:
dump all settings as JSON

/check-load:
how many threads are actively handling requests

/check-queued:
how many http requests are queued waiting to be handled

/check-health:
return json containing basic load/usage stats

/check-ev:
how many http requests are active by libevent

/check-pl-load:
how many pagelet threads are actively handling requests

/check-pl-queued:
how many pagelet requests are queued waiting to be handled

/check-sql:
report SQL table statistics

/check-sat
how many satellite threads are actively handling requests and queued waiting to be handled

/status.xml:
show server status in XML

/status.json:
show server status in JSON

/status.html:
show server status in HTML

/memory.xml:
show memory status in XML

/memory.json:
show memory status in JSON

/memory.html:
show memory status in HTML

/stats-on:
main switch: enable server stats

/stats-off:
main switch: disable server stats

/stats-clear:
clear all server stats

/stats-web:
turn on/off server page stats (CPU and gen time)

/stats-mem:
turn on/off memory statistics

/stats-sql:
turn on/off SQL statistics

/stats-mutex: turn on/off mutex statistics

sampling
optional, default 1000

/stats.keys:
list all available keys

from
optional, , or <-n> second ago

to
optional, , or <-n> second ago

/stats.kvp:
show server stats in key-value pairs

from
optional, , or <-n> second ago

to
optional, , or <-n> second ago

agg
optional, aggragation: *, url, code

keys
optional, ,,,<:regex:>

url
optional, only stats of this page or URL

code
optional, only stats of pages returning this code

/xenon-snap:
generate a Xenon snapshot, which is logged later

/hugepage:
show stats about hugepage usage

/const-ss:
get const_map_size

/static-strings:
get number of static strings

/static-strings-rds:
... that correspond to defined constants

/dump-static-strings:
dump static strings to /tmp/static_strings

/random-static-strings:
return randomly selected static strings

count
number of strings to return, default 1

/dump-apc:
dump all current value in APC to /tmp/apc_dump

/dump-apc-prefix:
dump a key prefix contents from APC to /tmp/apc_dump_prefix

prefix
required, the prefix to dump

count
optional, the number of keys to dump, default 1

/dump-apc-info:
show basic APC stats

/dump-apc-meta:
dump meta information for all objects in APC to /tmp/apc_dump_meta

/advise-out-apc:
forcibly madvise out APC prime data

/random-apc:
dump the key and size of a random APC entry

count
number of entries to return

/treadmill:
dump treadmill information

/pcre-cache-size:
get pcre cache map size

/dump-pcre-cache:
dump cached pcre's to /tmp/pcre_cache

/dump-array-info:
dump array tracer info to /tmp/array_tracer_dump

/start-stacktrace-profiler:
set enable_stacktrace_profiler to true

/relocate:
relocate translations

random
optional, default false, relocate random subset

all
optional, default false, relocate all translations

time
optional, default 20 (seconds)

/vm-tcspace:
show space used by translator caches

/vm-tcaddr:
show addresses of translation cache sections

/vm-dump-tc:
dump translation cache to /tmp/tc_dump_a and /tmp/tc_dump_astub

/vm-namedentities:
show size of the NamedEntityTable

/thread-mem:
show memory usage per thread

/proxy:
set up request proxy

origin
URL to proxy requests to

percentage
percentage of requests to proxy

/load-factor:
get or set load factor

set
optional, set new load factor (default 1.0,valid range [-1.0, 10.0])

/queue-discount: get/set how much we discount the queue-length

set
optional, set discount value (default 0, valid range [0, 10000])

/warmup-status:
Describes state of JIT warmup. Returns empty string if warmed up.

/jemalloc-stats:
get internal jemalloc stats

/jemalloc-stats-print:
get comprehensive jemalloc stats in human-readable form

/jemalloc-prof-activate:
activate heap profiling

/jemalloc-prof-deactivate:
deactivate heap profiling

/jemalloc-prof-dump: dump heap profile

file
optional, filesystem path

/jemalloc-prof-request:
dump thread-local heap profile in the next request that runs

file
optional, filesystem path

たくさんありますね

HHVMにはapcなども搭載していますので、これらがこのAdminServerから確認したり操作ができる様になります。

指定したパスワードを利用して値を確認してみてください。

http://127.0.0.1:9002/dump-apc-info?auth=SomePassword

プロセス監視等に利用できますので商用環境に導入する場合は必ず利用しましょう。


商用ではTypecheckerをオフにしよう

商用ではTypecheckerをオフにするといいでしょう!

hhvm.hack.lang.look_for_typechecker = false

開発時にオフにしてはいけません!

*HHVMのphp.iniで設定します。


JIT関連

JITそのものは hhvm.jit で設定できます。

稼働させるサーバのスペックに合わせてJIT関連の設定をすることをお勧めします。

JIT Settings


Repo Authoritative

いわゆるソースコードをコンパイルして動かすモードです。

JITだけで早くするよりは、併用して効果があると言われていますが・・!

最初に紹介した下記のコードを利用してみましょう。


index.php

<?hh // strict

<<__Entrypoint>>
function main(): void {
echo 'HHVM/Hack';
}


このコードを どこか任意のディレクトリに配置し、そのディレクトリを対象にコンパイルします。

$ hhvm --hphp -t hhbc -v AllVolatile=true --input-dir /Path/To/HackProject/public

コンパイルすると、デフォルトで何も設定していない状態であれば /tmp配下のディレクトリに hhvm.hhbcファイルが出力されます。

このファイルをphp.iniで指定し、Repo Authoritativeを利用する様にします。

hhvm.server.source_root=/Path/To/HackProject/public

hhvm.repo.authoritative=true
hhvm.repo.central.path=/tmp/hphp_dWMuXm/hhvm.hhbc

この状態で再起動し、ブラウザからアクセスします。

画面上には HHVM/Hack が表示されているはずです。

さらにindex.phpの内容を変更し、アクセスし直してください。

コンパイルしたファイルから読んでいるため、index.phpを編集しても変更されません。

ちなみにHello Worldくらいであればそこまで大きく変わりません。

多少捌けてる様に見えますが、おそらく誤差です。


hhvm.hhbc

Document Length:        9 bytes

Concurrency Level: 20
Time taken for tests: 0.010 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 18600 bytes
HTML transferred: 1000 bytes
Requests per second: 9920.63 [#/sec] (mean)
Time per request: 2.016 [ms] (mean)
Time per request: 0.101 [ms] (mean, across all concurrent requests)
Transfer rate: 1801.99 [Kbytes/sec] received


通常の実行

Document Length:        9 bytes

Concurrency Level: 20
Time taken for tests: 0.011 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 18400 bytes
HTML transferred: 900 bytes
Requests per second: 8906.31 [#/sec] (mean)
Time per request: 2.246 [ms] (mean)
Time per request: 0.112 [ms] (mean, across all concurrent requests)
Transfer rate: 1600.35 [Kbytes/sec] received

今回は導入時に利用できるものを中心に紹介しました。

色々いじり倒してみましょう