M1 Macでarm64のHomebrewとPHPBrewでPHP8.0の環境作ってベンチながす

本記事は、[サムザップ Advent Calendar 2020 #1](https://qiita.com/advent-calendar/2020/sumzap1) の12/6の記事です。

※2021/1/12 追記：pharを有効でインストール可能に！

# はじめに

MacBookAir(M1)でPHP8.0のベンチをとるはなしです

ただ、せっかくのApple Siliconなので、ARMネイティブのPHP8.0の環境をつくりたいとおもいます

M1 Macの開発環境のお話であれば、すでに@shibukawaさんの「[M1 Macの開発環境](https://qiita.com/shibukawa/items/797b7cbb7e530842e6f7)」の記事があがっています

ですが、自分が慣れ親しんでいるHomebrewとPHPBrewの環境にこだわってみました

（ちなみに、[HomebrewのApple Silicon対応](https://github.com/Homebrew/brew/issues/7857?ref=dtf.ru)は日々アップデートされ、改善されているので、この記事でエラーを回避している部分も、記事を読んでいただくタイミングでは解決済みかもしれません）

# まずはHomebrew

Apple Siliconの場合 /opt/homebrew 配下にインストールします(推奨されている）

```bash
$ cd /opt
$ sudo mkdir homebrew
$ sudo chown $USER:admin homebrew
$ curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
```

PATHを設定します

.zshrc

```bash
export PATH=/opt/homebrew/bin:/usr/local/bin:$PATH
```

# つぎにPHPBrew

こちらも /opt/phpbrew 配下にインストールします

```bash
$ curl -L -O https://github.com/phpbrew/phpbrew/releases/latest/download/phpbrew.phar
$ chmod +x phpbrew.phar
$ sudo mkdir -p /opt/phpbrew
$ sudo chown $USER:admin /opt/phpbrew
$ sudo mkdir /opt/phpbrew/bin
$ mv phpbrew.phar /opt/phpbrew/bin/phpbrew
```

初期化

```bash
$ /opt/phpbrew/bin/phpbrew init --root=/opt/phpbrew
```

PATHを設定します

.zshrc

```bash
[[ -e ~/.phpbrew/bashrc ]] && source ~/.phpbrew/bashrc

export PATH=/opt/homebrew/bin:/opt/phpbrew/bin:/usr/local/bin:$PATH
```

# PHPのビルドに必要なライブラリのインストール

まず

```bash
$ xcode-select --install
```

次に、HomebrewをつかってPHPのビルドに必要なライブラリをインストールします

```bash
$ brew install curl mhash bzip2 oniguruma libzip libxml2 libiconv libxslt
```

# PHP8.0のビルド！

次のエラーが回避できずvariantsの変更で対応しました

```shell-session
PEAR package PHP_Archive not installed: generated phar will require PHP's phar extension be enabled.
make: *** [ext/phar/phar.phar] Bus error: 10
```
ーーー
※2021/1/12追記：解決
（phpenvでも同じエラーになるので、同様に```--with-external-pcre```を指定すれば解決します）

次のパッケージをbrewでいれて

```
$ brew install pcre2
```
オプションでpcreを指定

```
$ phpbrew install 8.0.0 +default +mysql -- --with-external-pcre=$(brew --prefix pcre2)
```
これでvariantsでpearとpharを除外しなくてもOKになります
ーーー

おまじないをして（xsltのエラーが出たので）、いざビルド

(variantsでpharとpearを除外しています)

```bash
$ export LDFLAGS="-L/opt/homebrew/opt/libxslt/lib"
$ export CPPFLAGS="-I/opt/homebrew/opt/libxslt/include"
$ export PKG_CONFIG_PATH="/opt/homebrew/opt/libxslt/lib/pkgconfig"
$ phpbrew install 8.0 +default -phar -pear
```

PHP8.0に切り替えて確認

```bash
$ phpbrew use php-8.0.0
$ php -v
PHP 8.0.0 (cli) (built: Dec  4 2020 01:10:49) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies

$ lipo -archs `which php`
arm64
```

ちゃんとPHP8.0になっているのとarm64でコンパイルされたのを確認できました！

# いざベンチマーク

ベンチマークはこちらを使用

[php/php-src](https://github.com/php/php-src/blob/master/Zend/bench.php)

検証機は「MacBook Air 2020 M1」です

### (1)まずは、MacにプリインストールされているPHP7.3.22から

```bash
$ php -v
WARNING: PHP is not recommended\nPHP is included in macOS for compatibility with legacy software.\nFuture versions of macOS will not include PHP.
PHP 7.3.22-(to be removed in future macOS) (cli) (built: Oct 30 2020 00:19:07) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.22, Copyright (c) 1998-2018 Zend Technologies

$ lipo -archs `which php`
x86_64 arm64e
```

ベンチ実行

```bash
$ php bench.php
simple             0.033
simplecall         0.009
simpleucall        0.020
simpleudcall       0.021
mandel             0.082
mandel2            0.092
ackermann(7)       0.020
ary(50000)         0.002
ary2(50000)        0.002
ary3(2000)         0.036
fibo(30)           0.073
hash1(50000)       0.005
hash2(500)         0.006
heapsort(20000)    0.020
matrix(20)         0.018
nestedloop(12)     0.046
sieve(30)          0.012
strcat(200000)     0.003
------------------------
Total              0.499
```

### (2)つぎにPHP8.0(JIT オフ)

```bash
$ phpbrew use php-8.0.0
$ php -v
PHP 8.0.0 (cli) (built: Dec  4 2020 01:10:49) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies

$ lipo -archs `which php`
arm64
```

ベンチ実行

```bash
$ php bench.php 
simple             0.024
simplecall         0.006
simpleucall        0.018
simpleudcall       0.021
mandel             0.079
mandel2            0.084
ackermann(7)       0.019
ary(50000)         0.002
ary2(50000)        0.002
ary3(2000)         0.032
fibo(30)           0.071
hash1(50000)       0.004
hash2(500)         0.006
heapsort(20000)    0.018
matrix(20)         0.016
nestedloop(12)     0.031
sieve(30)          0.012
strcat(200000)     0.003
------------------------
Total              0.448
```

### (3)最後にPHP8.0(JIT オン)

まずは JITをオンにする（参考「[PHPBrewでPHP8を入れる](https://zenn.dev/sapi_kawahara/articles/20201127-php8-settings)」）

~/.phpbrew/php/php-8.0.0/etc/php.iniを編集

コメントをはずす

```bash
zend_extension=opcache
```

変更＆追記

```bash
opcache.enable_cli=1
opcache.jit=on
opcache.jit_buffer_size=100M
```

 JITがオンになったのを確認

ーーーー
2021/3/25 追記
確認方法が誤っていたので、正しい方法へ変更
ーーーー

```bash
$ php -v
PHP 8.0.0 (cli) (built: Dec  4 2020 01:10:49) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.0, Copyright (c), by Zend Technologies
$ php -i | grep jit
（ない）

$ lipo -archs `which php`
arm64
```

"with Zend OPcache v8.0.0" が表示されるようになりましたね
ただし、```php -i```でJITが有効になっているか確認すると、
ARMでは、JITを有効にできていませんでした
OPcacheだけ有効な状態です

ベンチ実行

```bash
$ php bench.php
simple             0.025
simplecall         0.010
simpleucall        0.009
simpleudcall       0.008
mandel             0.048
mandel2            0.070
ackermann(7)       0.018
ary(50000)         0.002
ary2(50000)        0.002
ary3(2000)         0.032
fibo(30)           0.060
hash1(50000)       0.004
hash2(500)         0.006
heapsort(20000)    0.016
matrix(20)         0.016
nestedloop(12)     0.031
sieve(30)          0.011
strcat(200000)     0.003
------------------------
Total              0.370
```

# 最後に

今回作った環境はとりあえずベンチマークをながすだけの環境になります

(phpbrewでPHP8.0に切り替えたあと、pharがないので、phpbrewコマンドが以降エラーになります)

~~正直ベンチマークの結果は、なんともいえず、まだPHP8.0のJITはARMよりもx86に最適化されているのかな？と思ってしまう結果でした~~
まだPHP8.0のJITはARMに対応されていませんでした

ただ、Apple SiliconのARMネイティブ環境を作るのは、なんだかワクワクしませんか？

（自分はワクワクしながら開発環境を整えています）

今回記事を書くにあたって、日々、Homebrewが改善されているくのを目の当たりにしました（昨日(12/2)までエラーが発生してインストールできないライブラリがいくつあったものの、今日(12/3)には改善されていました）

OSSの開発者の努力によって、Apple Siliconの開発環境は日々改善されています

感謝しかありません

この記事もみなさまのお役に少しでも立てたら幸いです

明日は@KoniroIrisの記事です！