Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP 8 で WEB 以外の世界の扉 を叩く

sji
December 13, 2020

PHP 8 で WEB 以外の世界の扉 を叩く

PHP カンファレンス 2020 の発表資料

本番で使ったものにスタイルの修正 / リンクの追加など若干の手直しを入れています
本番でうまくデモが動かなかったので、後から録画を幾つか上げています
https://twitter.com/sji_ch/status/1337774274606555141
https://twitter.com/sji_ch/status/1337690042165149697
https://twitter.com/sji_ch/status/1337693697907933186

sji

December 13, 2020
Tweet

More Decks by sji

Other Decks in Programming

Transcript

  1. AGENDA なぜ PHP 7.5 ではなく 8 なのか JIT FFI PHP

    での並列並⾏処理 課題とまとめ
  2. ⾮同期通信 + Preloading + でマルチスレッド 解析スレッド 対象プロセス上での処理系の内部データのメモリアドレス を特定 PHP で処理系のバイナリデータをパース

    Linux のプロセス情報ファイルをパース FFI でシステムコールを呼んで対象プロセスのメモリを覗 き⾒ 処理系の内部データ構造を解釈してコールトレースを抜き 出す 集計出⼒スレッド FFI で GUI のウィンドウを描画 コールトレースの集計をとる JIT
  3. ⾮同期通信 + Preloading + でマルチスレッド 解析スレッド 対象プロセス上での処理系の内部データのメモリアドレス を特定 PHP で処理系のバイナリデータをパース

    Linux のプロセス情報ファイルをパース FFI でシステムコールを呼んで対象プロセスのメモリを覗 き⾒ 処理系の内部データ構造を解釈してコールトレースを抜き 出す 集計出⼒スレッド FFI で GUI のウィンドウを描画 コールトレースの集計をとる JIT
  4. RFC 作成⽇ Shorter Attribute Syntax Change 2020- 08-04 Don't automatically

    unserialize Phar metadata outside getMetadata() 2020- 07-07 Reclassifying engine warnings 2019- 08-27 Ensure correct signatures of magic methods 2020- 04-05
  5. RFC 作成⽇ Named Arguments 2020-05-05 Treat namespaced names as single

    token 2020-06-15 Saner string to number comparisons 2019-02-26 Saner numeric strings 2020-06-28
  6. RFC 作成⽇ Remove inappropriate inheritance signature checks on private methods

    2020- 04-16 Match expression v2 2020- 05-22 Attribute Amendments 2020- 05-11 Make sorting stable 2020- 05-12
  7. RFC 作成⽇ Locale-independent oat to string cast 2020-03- 11 Change

    Default PDO Error Mode 2020-03- 28 Stricter type checks for arithmetic/bitwise operators 2020-04- 02 Add str_starts_with() and str_ends_with() functions 2020-03- 25
  8. RFC 作成⽇ Validation for abstract trait methods 2020-02- 07 Add

    Stringable interface 2020-01- 15 Implement new DOM Living Standard APIs in ext/dom 2019-09- 15 Arrays starting with a negative index 2017-04- 20
  9. PHP 8.0 ⽤のブランチは 2019 年 1 ⽉ に出てる php-master-changes 2019-01-28

    https://qiita.com/sj-i/items/418282051c3c647e7aed#nikic- clear-news-upgrading-and-upgradinginternals
  10. メジャーバージョンリリース遍歴 バージョン リリース⽇ PHP 1 1995 年 6 ⽉ 8

    ⽇ PHP 2 1997 年 11 ⽉ 1 ⽇ PHP 3 1998 年 6 ⽉ 6 ⽇ PHP 4 2000 年 5 ⽉ 22 ⽇ PHP 5 2004 年 7 ⽉ 13 ⽇ PHP 7 2015 年 12 ⽉ 3 ⽇
  11. メジャーバージョンリリース遍歴 バージョン リリース⽇ PHP 1 1995 年 6 ⽉ 8

    ⽇ PHP 2 1997 年 11 ⽉ 1 ⽇ PHP 3 1998 年 6 ⽉ 6 ⽇ PHP 4 2000 年 5 ⽉ 22 ⽇ PHP 5 2004 年 7 ⽉ 13 ⽇ PHP 7 2015 年 12 ⽉ 3 ⽇ 全然定期的ではない
  12. "PHP 8 NEXT?" 2018 年 6 ⽉に、コア開発者の nikita さんが internals

    に投稿 「次のバージョン PHP 8 になりそうな雰囲気を感じてるんだけ ど、実際どうなの?」というメール https://externals.io/message/102378
  13. PHP 2^3 Zeev さんが話の流れに乗って ML へ投下した 8 への意気込みメ ール https://externals.io/message/102415

    次のメジャーバージョンでは JIT や FFI 、⾮同期処理や⻑時間実 ⾏スクリプトのサポートや preloading の機能を盛り込みたい
  14. PHP 2^3 Zeev さんが話の流れに乗って ML へ投下した 8 への意気込みメ ール https://externals.io/message/102415

    次のメジャーバージョンでは JIT や FFI 、⾮同期処理や⻑時間実 ⾏スクリプトのサポートや preloading の機能を盛り込みたい 7.3 のリリース後はPHP 8 に向けて開発⼒を集中したい
  15. PHP 2^3 Zeev さんが話の流れに乗って ML へ投下した 8 への意気込みメ ール https://externals.io/message/102415

    次のメジャーバージョンでは JIT や FFI 、⾮同期処理や⻑時間実 ⾏スクリプトのサポートや preloading の機能を盛り込みたい 7.3 のリリース後はPHP 8 に向けて開発⼒を集中したい 7.4 は 8 の準備で廃⽌予定機能⾮推奨化オンリーのスリムなリリ ースに
  16. 「次は PHP 8 」は残った 2018 年 11 ⽉、Nikita さんから "Branch

    off PHP-7.4 early" とい うメールが intenals へ 早めに 7.4 のブランチ切って master へ 8 向けの作業を⼊れて いけるようにする提案
  17. 「次は PHP 8 」は残った 2018 年 11 ⽉、Nikita さんから "Branch

    off PHP-7.4 early" とい うメールが intenals へ 早めに 7.4 のブランチ切って master へ 8 向けの作業を⼊れて いけるようにする提案 2019 年 1 ⽉ 28 に実際に PHP 7.4 のブランチが切られる
  18. 「次は PHP 8 」は残った 2018 年 11 ⽉、Nikita さんから "Branch

    off PHP-7.4 early" とい うメールが intenals へ 早めに 7.4 のブランチ切って master へ 8 向けの作業を⼊れて いけるようにする提案 2019 年 1 ⽉ 28 に実際に PHP 7.4 のブランチが切られる 同⽇に JIT の RFC ページが作られる
  19. 「次は PHP 8 」は残った 2018 年 11 ⽉、Nikita さんから "Branch

    off PHP-7.4 early" とい うメールが intenals へ 早めに 7.4 のブランチ切って master へ 8 向けの作業を⼊れて いけるようにする提案 2019 年 1 ⽉ 28 に実際に PHP 7.4 のブランチが切られる 同⽇に JIT の RFC ページが作られる この段階で FFI と Preloading は PHP 7.4 向けで受理済
  20. PHP 8 のための JIT のための PHP 7.4 の機能 JIT 実装は

    LuaJIT を参考にしたもの FFI も JIT との組み合わせを念頭に置きつつ LuaJIT にもとづいて 提案 Preloading も JIT / FFI との組み合わせも念頭に置きつつ提案 まだ完全な姿ではないがコマは揃ってきた
  21. PHP 8 のビジョン Zend / Dmitry さんの 7 年以上に渡る取り組みの成果が JIT

    とそ の周辺機能 既存のアプリケーションでさほどの性能向上が⾒られないと分か っていたにも関わらず断⾏された 何か強い明確なビジョンがある
  22. PHP 8 のビジョン Zend / Dmitry さんの 7 年以上に渡る取り組みの成果が JIT

    とそ の周辺機能 既存のアプリケーションでさほどの性能向上が⾒られないと分か っていたにも関わらず断⾏された 何か強い明確なビジョンがある つまり既存の PHP アプリケーションの枠内にはないことをやれ るようになること!
  23. JIT

  24. CPU バウンドな処理は JIT 向き JIT なしが 14 FPS くらい JIT

    あり(tracing JIT) が 35 FPS くらい JIT が得意な処理なので 2.5 倍くらい差が出る
  25. TRACING JIT と関数 JIT JIT には tracing JIT と function

    JIT のモードがある opcache.jit で切り替え デフォルトは tracing JIT こっちの⽅がたいてい速い、中⾝は少し複雑 2019 年 1 ⽉の RFC 当時はまだなかった 2020 年 3 ⽉頃に⼊った
  26. ⼿動最適化の結果まとめ JIT なし: 静⽌状態で約 50 FPS 、画⾯が動きはじめると約 35 FPS JIT

    あり: 静⽌状態で約 85 FPS 、画⾯が動きはじめると約 60 FPS JIT 有無での差は 1.7 倍程度に
  27. ⼿動最適化の結果まとめ JIT なし: 静⽌状態で約 50 FPS 、画⾯が動きはじめると約 35 FPS JIT

    あり: 静⽌状態で約 85 FPS 、画⾯が動きはじめると約 60 FPS JIT 有無での差は 1.7 倍程度に JIT で速くなる計算処理⾃体が減ったため?
  28. JIT についての現況まとめ CPU バウンドな処理はやはり速くなる、1.7 倍とか 2.5 倍とか tracing JIT と

    function JIT でも 1.5 倍程度の差が出るケースも まだまだ「⼈間が適当に書いても処理系が最適化してくれる」の 世界ではない ⼈間がしょぼい対応で速くする余地がある、JIT の今後の伸びし ろもありそう
  29. FFI

  30. FFI の使い⽅ $ffi = \FFI::cdef( 'int printf(const char * restrict

    format, ... );', // 'libc.so' /* libc は処理系とともに読み込まれているので不要 */ ); $ffi->printf('hello clang world');
  31. システムコール OS の機能を呼び出すための仕組み これまでの PHP は Web に特化した⾔語で、標準で全ての機能に アクセスすることはできない 例えば

    ioctl() でデバイスを直接操作するとか 例えば ptrace() や process_vm_readv() を使って別プロセスの挙 動を覗き⾒るとか php-pro ler はコレを利⽤
  32. FFI から演算⼦オーバーロードしてみる Z-Engine を利⽤ class A {} $refClass = new

    ReflectionClassEx(A::class); $handler = Closure::fromCallable([ObjectCreateTrait::class, '__init']); $refClass->setCreateObjectHandler($handler); $refClass->setCompareValuesHandler(fn (...$args) => 0); var_dump(new A() == 1); // true になる var_dump(new A() == 'string'); // true になる
  33. Z-ENGINE FFI を通じて PHP 処理系の内部機能へアクセスするためのライ ブラリ ライセンスが RPL 1.5 で少し縛りが強い

    PHP による演算⼦オーバーロード Re ection からの nal 外し https://github.com/lisachenko/z-engine
  34. GTK で PHP からウィンドウを作る include __DIR__ . '/../vendor/autoload.php'; const PHP_GTK_DEV_DEBUG

    = false; $gtk = PHPGtk::gtk(); $gtk->gtk_init($argc, $argv); $mainwin = $gtk->gtk_window_new(\Gtk\GtkEnum::GTK_WINDOW_TOPLEVEL); $gtk->gtk_widget_show_all($mainwin); $gtk->gtk_main();
  35. GTK で PHP からボタン押下時のコールバックを使う こんなコード追加だけでいける $button = $gtk->gtk_button_new_with_label('button'); $callback =

    function () { echo 'hello'; }; $gtk->g_signal_connect($button, 'clicked', $gtk->G_CALLBACK($callback), null); $gtk->gtk_container_add($gtk->GTK_CONTAINER($window), $button);
  36. GLADE で作った UI も使える Glade という GTK の GUI デザイナがある

    Glade で作った UI データも PHP から使える https://glade.gnome.org/
  37. 「PHP FFI 」 で GITHUB で検索 SFML SDL libpcap opencv

    https://github.com/djuhnix/phpml https://github.com/Sera mArts/f -sdl https://github.com/rtckit/php-pcap-f https://github.com/ghostjat/php_opencv
  38. THE FREE LUNCH WAS OVER 今どきの CPU はマルチコア、4 以上のコアも当たり前になって きた

    JIT でシングルスレッド性能を上げるだけでは⾜りない
  39. EXT-PTHREADS PHP Threads の略 POSIX スレッドの単なるラッパーではない どちらかというと Java っぽい雰囲気の API

    作者は krakjoe (Joe Watkins) さん phpdbg や pcov や apcu の作者でもある 2019 年に開発中⽌、PHP 7.4 以降への対応はしない → parallel へ https://github.com/krakjoe/pthreads
  40. PARALLEL の使い⽅ <?php $runtime = new \parallel\Runtime(); $future = $runtime->run(function(){

    for ($i = 0; $i < 500; $i++) echo "*"; return "easy"; }); for ($i = 0; $i < 500; $i++) { echo "."; } printf("\nUsing \\parallel\\Runtime is %s\n", $future->value());
  41. 別スレッドのグローバル変数が⾒えない $global_variable = ' ⾒える '; $runtime = new \parallel\Runtime();

    $future = $runtime->run(function(){ global $global_variable; return $global_variable ?? ' ⾒えない '; }); printf(" 別スレッドのグローバル変数は ", $future->value());
  42. CHANNEL $channel = new \parallel\Channel(); $runtime = new \parallel\Runtime(); $future

    = $runtime->run( function(\parallel\Channel $channel){ $message = $channel->recv(); echo $message; }, [$channel] ); $channel->send('message');
  43. ZEND の ND の⼈だって⾔っている Zend の nd の⽅の⼈も昔同じようなことを⾔っていた もしスレッドを実装するとしたら、⼀番良いの はそれぞれが⾃前のコンテキストを持ったワー

    カースレッドを⽣成できるようにして、データ 共有はしない(だからロックも要らない)奴だ ろうね。そしてスレッド間でメッセージパッシ ングする API を提供する。 -- Andy Gutmans ( ) https://externals.io/message/47701#47729
  44. 他⾔語でも近いノリの話がある D ⾔語はデフォルトでスレッド間のデータが⾮共有 ただし immutable なデータは共有できる The D Programming Language

    という本にちょっと載ってる https://www.informit.com/articles/article.aspx?p=1609144 http://dusers.dip.jp/modules/wiki/?Articles%2FTDPL%20- %20Concurrency%20in%20D%2F1
  45. なぜ PARALLEL が⽣まれたのか https://blog.krakjoe.ninja/2019/02/parallel-php-next- chapter.html While aware, there was nothing

    driving me to write another API, until recently when Zend made their intention to merge the JIT they have been working on for years into PHP. Just think for a moment what it would mean to be able to execute machine code in parallel in user land PHP ...
  46. なぜ PARALLEL が⽣まれたのか: 訳 pthreads と 別の並列処理 API を作りたい、みたいなのはしばら くなかった

    Zend の⼈たちが年⽉を費やして作ってきた JIT のマージに向け て動くまではね ちょっと考えてみてほしい これはつまりユーザランドの PHP によって機械語のコードを並 列実⾏できるってことだよね?
  47. JIT + PARALLEL のデモ 再度ファミコンエミュレータを改修 描画スレッドと CPU / PPU で描画する内容を計算するスレッド

    を分ける 前のフレームを描画しきる前に描画内容の計算が終わった場合、 そのフレームの描画をスキップ
  48. JIT + PARALLEL のデモ 再度ファミコンエミュレータを改修 描画スレッドと CPU / PPU で描画する内容を計算するスレッド

    を分ける 前のフレームを描画しきる前に描画内容の計算が終わった場合、 そのフレームの描画をスキップ JIT だと計算スレッドが 300 FPS くらい出る
  49. AMPHP + PSALM ⼩話 実は psalm に amphp をサポートする機能 @psalm-yield

    というも のがあり、Promise に付いてる Promise<T> を yield すると T が返ってくるものとして型解析 本当は amphp のループ外で使ったら別の値が来るかもしれな い、のだが、そこは無視
  50. JIT は発展途上 速くはなっても JIT エンジン界ではまだまだ新参者 The Computer Language Benchmarks の多くのベンチマークでま

    だ Node には結構負けてる PHP 8 の今後に期待 tracing JIT 導⼊(約 1 年)での性能向上実績もある https://benchmarksgame- team.pages.debian.net/benchmarksgame/fastest/php.html
  51. スレッドもまだ発展途上 Union サポートが完全ではない opcache.jit=1205 + preload じゃないと SEGV 起こしたり opcache.jit=1205

    + preload でも SEGV 起こすケースも krakjoe さんを応援しよう! Patreon も GitHub スポンサーもあるよ! https://www.patreon.com/krakjoe
  52. FFI もまだ発展途上 LuaJIT で⼊ってるような C を越えるレベルの最適化はまだない When FFI Function Calls

    Beat Native C でもそのうち⼊る筈、PHP でも C に勝てる⽇が来るか? https://nullprogram.com/blog/2018/05/27/
  53. 公式の⾮同期サポートはまだ amphp の trowski さんが 3 代⽬ Fiber RFC に最近取り組んでる

    かつて頓挫した Fiber RFC の落胤である ext-async の後継 8.x へのコア⼊りを⽬指している筈 https://github.com/amphp/ext- ber
  54. PHP と PHPER の進化 PHP 4 にはまともなオブジェクト指向機能さえなかった 今は成熟したオブジェクト指向機能もあれば静的型検査のエコシ ステムもある PHP

    プログラマもこれらの機能に習熟してきた Web なら「それ PHP でもできるし、PHP で別にいいじゃない」 と⾔える
  55. PHP と PHPER の新たな挑戦 PHP で FFI もマルチスレッドも⾮同期処理もある程度できるよ うになってきた JIT

    まで⼊った ⾔語とエコシステムとしては準備が整ってきている しかし PHP プログラマの⽅はどうか 「Web 以外だって PHP でも別にいいじゃない」と⾔えるのか