Slide 1

Slide 1 text

@hanhan1978 ソースコードから理解する PreloadとJITの話 PHP Conference Japan 2020/12/12

Slide 2

Slide 2 text

@hanhan1978 ● 富所 亮 ● 職業 ○ Webアプリケーションエンジニア ○ 雑用係 ● ブログ ○ https://blog.hanhans.net ● Yokohama North AM ○ https://anchor.fm/yokohama-north-am

Slide 3

Slide 3 text

興味のある方は... ※気が向いた時にやってます ... https://shadow-php.connpass.com/

Slide 4

Slide 4 text

秒でGDBデバッグ https://github.com/hanhan1978/shadow-php/wiki

Slide 5

Slide 5 text

本日のテーマ preloadとjitの肌感を掴む ● 謎の技術にせず、仕組みから理解 ● どれくらい速度向上するのか ● 本番環境での採用是非

Slide 6

Slide 6 text

PHP高速化の歴史

Slide 7

Slide 7 text

PHPはスクリプト言語 実行の大まかな流れ

Slide 8

Slide 8 text

PHPはスクリプト言語 実行の大まかな流れ ここで時間がかかる

Slide 9

Slide 9 text

PHPerが行ってきた解決策

Slide 10

Slide 10 text

中間コードキャッシュ コンパイル結果(OPCode)をメモリにキャッシュ

Slide 11

Slide 11 text

歴代の中間コードキャッシュ XCache 〜PHP5.6 eAccelarator 〜PHP5.6 Alternative PHP Cache (APC) PHP5.4 Zend Opcache PHP5.5〜 ※これらのツールを同居させると ShareMemory戦国時代になりSegFault

Slide 12

Slide 12 text

OPCacheがデファクトスタンダード PHP5.5以降は一択 そして、PHP7.4以降からOPCacheにさらなる高速化の仕組みが 導入されるようになった....ここから本題

Slide 13

Slide 13 text

余談1 稀によく見るうっかりさん。OPCache入ってない ※php -v ですぐ確認できるので、心当たりのある方は確認を

Slide 14

Slide 14 text

※OPcacheが入ってなくて良いことは一個もないです

Slide 15

Slide 15 text

PHPスクリプト実行の詳細

Slide 16

Slide 16 text

PHPはスクリプト言語 ● 実行時にコンパイル ● コンパイル&実行を繰返す

Slide 17

Slide 17 text

例えば

Slide 18

Slide 18 text

PHP実行の流れ

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

実行の詳細

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

中間コードキャッシュに よってコンパイルの過程 が省略される

Slide 24

Slide 24 text

具体例

Slide 25

Slide 25 text

ファイル構成

Slide 26

Slide 26 text

index.php

Slide 27

Slide 27 text

autoload.php

Slide 28

Slide 28 text

A.php

Slide 29

Slide 29 text

B.php

Slide 30

Slide 30 text

実行すると

Slide 31

Slide 31 text

実行すると autoloaderが2回呼び出されている

Slide 32

Slide 32 text

実行の流れ

Slide 33

Slide 33 text

4回のコンパイル

Slide 34

Slide 34 text

OPCacheが解決するもの 4回分のコンパイルがキャッシュで解決

Slide 35

Slide 35 text

計測

Slide 36

Slide 36 text

OPCache − ◯ Req / Sec 111.55 680.42 ※OPCacheの有効化によって、処理速度は約 6倍 Laravelの30秒ベンチマーク

Slide 37

Slide 37 text

高速化技術が達成すること 1. OPCache >> 2. OPCache preload >> 3. OPCache JIT >> ??? ??? ???

Slide 38

Slide 38 text

高速化技術が達成すること 1. OPCache >> コンパイル回数の軽減 2. OPCache preload >> 3. OPCache JIT >> ??? ???

Slide 39

Slide 39 text

OPCache preloadとは?

Slide 40

Slide 40 text

PHP7.4から追加 https://wiki.php.net/rfc/preload

Slide 41

Slide 41 text

● OPCacheの機能追加として提案 ● サーバー起動時に指定ファイルをコンパイル して、メモリに読込 ※一見すると、中間コードキャッシュと同じことをしているように見える

Slide 42

Slide 42 text

具体例

Slide 43

Slide 43 text

ファイル構成

Slide 44

Slide 44 text

preload.php

Slide 45

Slide 45 text

php.ini

Slide 46

Slide 46 text

実行すると

Slide 47

Slide 47 text

実行すると Class Aはautoloadされてない!!

Slide 48

Slide 48 text

実行の流れ

Slide 49

Slide 49 text

3回のコンパイル

Slide 50

Slide 50 text

● autoloadが省略される ● preload以外のファイルは opcache.validate_timestamp=0と同じ挙動 ● 直接のrequireはpreloadが活用されない

Slide 51

Slide 51 text

preloadソース v7.4.3

Slide 52

Slide 52 text

ext/opcache/ZendAccelarator.c - SAPI起動時に L4200 preload_load() - globalなデータ領域にpreloadしたクラス、ファイルの情報を登録 する - opcodes実行時のコンパイルに使われるのは、L1914 persistent_compile_file。これはpreloadの有無に依らない

Slide 53

Slide 53 text

Zend/zend_execute_API.c - L1419 zend_fetch_class_by_name が未解決のクラス名に対して コールされる - zend_hash_findでコンパイル済みのクラスが発見されれば、それを 使う(preload) - それ以外は、autoloaderを使ってクラスの解決が行われて、ファイル が見つかればコンパイルされる ※要するにpreloadされるとautoloaderまで処理がいかずに解決できる

Slide 54

Slide 54 text

計測

Slide 55

Slide 55 text

Laravelの30秒ベンチマーク OPCache − ◯ ◯ Preload − − ◯ Req / Sec 111.55 680.42 774.14 ※preload有効化によって、処理速度は約 14%向上

Slide 56

Slide 56 text

高速化技術が達成すること 1. OPCache >> コンパイル回数の軽減 2. OPCache preload >> 3. OPCache JIT >> ??? ???

Slide 57

Slide 57 text

高速化技術が達成すること 1. OPCache >> コンパイル回数の軽減 2. OPCache preload >> autoloadの軽減 3. OPCache JIT >> ???

Slide 58

Slide 58 text

余談 Windows用PHPのpreload機能は7.4.2の時点で機能削除 https://www.php.net/manual/en/opcache.preloading.php

Slide 59

Slide 59 text

OPCache JITとは?

Slide 60

Slide 60 text

PHP8.0から追加 https://wiki.php.net/rfc/jit

Slide 61

Slide 61 text

ZendVMで実行するのではなく Native Codeを実行する

Slide 62

Slide 62 text

● 機械語実行により処理速度が最適化 ● 同様のことはpcre-jitやJS等でもおなじみ

Slide 63

Slide 63 text

実行の詳細

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

OPCodeをさらに機械語に変換 CPUで直接実行!!

Slide 67

Slide 67 text

● コード実行が最適化 ● JITコンパイルのオーバーヘッドは実行速度で 補填

Slide 68

Slide 68 text

JITソース v8.0.0

Slide 69

Slide 69 text

OPCacheが主に関わってくるソースコード JIT関連はopcache/jitに固まっているので 分かりやすい。

Slide 70

Slide 70 text

opcodeをx86のアセンブラに変換している zend_jit_x86.c

Slide 71

Slide 71 text

ext/opcache/jit/zend_jit.c - zend_jit_op_array において泥臭い変換処理が行われている - アーキテクチャ依存のコード変換なので未対応だと動作しない - LuaJIT由来のDynAsmを利用

Slide 72

Slide 72 text

JIT化される単位 - zend_jit_op_array はファイル毎に呼び出し - クラス単位、関数単位でopcodeの最適化が行われて、関数のIOを合わ せた形でZendVMの主処理と繋ぎ合わされる - 1ファイル1関数に全部の処理を入れたら、効果的に効きそう

Slide 73

Slide 73 text

計測

Slide 74

Slide 74 text

Laravelの30秒ベンチマーク OPCache − ◯ ◯ Preload − − ◯ Req / Sec 111.55 680.42 774.14 Req / Sec (JIT) − 696.57 812.93 ※JIT有効化によって、処理速度は約 2.5〜5%向上

Slide 75

Slide 75 text

モンテカルロ法を計測

Slide 76

Slide 76 text

円周率計算のベンチマーク OPCache − ◯ Sec 9.74 8.96 Sec (JIT) − 5.20 ※JIT有効化によって、処理速度は約 42%向上 100,000,000回試行の処理時間

Slide 77

Slide 77 text

高速化技術が達成すること 1. OPCache >> コンパイル回数の軽減 2. OPCache preload >> autoloadの軽減 3. OPCache JIT >> ???

Slide 78

Slide 78 text

高速化技術が達成すること 1. OPCache >> コンパイル回数の軽減 2. OPCache preload >> autoloadの軽減 3. OPCache JIT >> コード実行の最適化

Slide 79

Slide 79 text

JITの現状

Slide 80

Slide 80 text

● https://bugs.php.net/search.php?cmd=display&packa ge_name[]=opcache ● RedditのPHP系板 ● https://www2.slideshare.net/nikita_ppv/justintime-co mpiler-in-php-8 情報キャッチアップ

Slide 81

Slide 81 text

使用上の注意

Slide 82

Slide 82 text

● 内部の実行パスが変わる ● 開発も同じ設定にするのが吉 ● ファイル更新でopcache_clearとか...

Slide 83

Slide 83 text

phpunitで使うには これを設定しないと、コマンドライン実行時にopcache が動かない。

Slide 84

Slide 84 text

まとめ

Slide 85

Slide 85 text

高速化技術が解決すること 1. OPCache >> コンパイル回数の軽減 2. OPCache preload >> autoloadの軽減 3. OPCache JIT >> コード実行の最適化

Slide 86

Slide 86 text

仕組みを理解 適切なアプリケーションに適用 コレ大事!!

Slide 87

Slide 87 text

参考1 https://speakerdeck.com/hanhan1978/web-application-tuning-guildline

Slide 88

Slide 88 text

参考2 https://gist.github.com/hellerbarde/2843375 Network IOはメモリアク セスの5万倍遅い

Slide 89

Slide 89 text

リアルなウェブアプリのボトルネックは、大半 がDBアクセス CPU負荷の数%は全体のボトルネックでは 微々たるもの

Slide 90

Slide 90 text

本番投入はオススメしづらい... ISUCON用機能なのでは...