Submit Search
PHP7の内部実装から学ぶ性能改善テクニック
•
24 likes
•
17,724 views
Yoshio Hanawa
Follow
Developers Summit 2015 KANSAI (2015/9/4) 発表資料
Read less
Read more
1 of 64
Download now
Downloaded 30 times
More Related Content
PHP7の内部実装から学ぶ性能改善テクニック
1.
A remarkable improvement
on data structure in PHP7 PHP7の内部実装から学ぶ 性能改善テクニック hnw Developers Summit 2015 KANSAI (2015/9/4)発表資料
2.
自己紹介 ❖ @hnw ❖ 勤務先:KLab株式会社 ❖
カレーとバグが大好物 ❖ PHP歴15年 ❖ PHPや周辺エクステンションにバグレポ・PR多数
3.
アジェンダ ❖ さいきんのPHP7 ❖ PHP7の新機能 ❖
PHP7って速いの? ❖ どこがボトルネック? ❖ PHP7のデータ構造
4.
まずはアンケート
5.
普段PHPを 書いている方?
6.
実際にPHP7を 試したことがある方?
7.
❖ さいきんのPHP7 ❖ PHP7の新機能 ❖
PHP7って速いの? ❖ どこがボトルネック? ❖ PHP7のデータ構造
8.
PHP7? ❖ PHP 5.6.xの次のバージョンがPHP
7.0.0 ❖ PHP6はスキップ ❖ 約10年ぶりのメジャーバージョンアップ
9.
さいきんのPHP7 ❖ 予定通りalphaバージョン、betaバージョンをリリース ❖ 現在最新はPHP
7.0.0 RC1 ❖ 11月に正式版リリース予定
10.
PHP7、どれくらい変わる? ❖ PHP7で採択されたRFCは48個 ❖ 参考:PHP
5.6は17個、PHP 5.5は20個 →普段のマイナーバージョンアップよりは変化が大きい
11.
PHPのRFCシステム ❖ 新機能の導入にはRFCと呼ばれる説明ページが必要 ❖ 提案内容や変更による影響などを書く ❖
MLで議論後、投票によって採用・不採用が決まる ❖ 過半数または2/3以上の同意が必要(内容による) ❖ スピード感は無いが、十分機能している印象 ❖ 議論を追うのに非常に便利
12.
PHP7で変わらないこと ❖ PHPは言語仕様の変更に対して非常に保守的 ❖ PHP7でも後方互換性は重視されている ❖
移行コストは十分低いはず
13.
❖ さいきんのPHP7 ❖ PHP7の新機能 ❖
PHP7って速いの? ❖ どこがボトルネック? ❖ PHP7のデータ構造
14.
致命的エラーが例外になった ❖ PHP5までの致命的エラー ❖ エラーハンドリングできず、即座に終了していた ❖
PHP7の致命的エラー ❖ Errorという新しい例外になった ❖ トップレベルに到達すると今まで通りのエラーになる →ユニットテストで致命的エラーから復帰できる
15.
??演算子の新設 ❖ nullでなければその値を、nullなら右オペランドを返す ❖ isset()と同様に未定義値に対しても使える ❖
ようやくisset()地獄から解放されるぞ!
16.
無名クラスの導入 ❖ クラス定義と同時にインスタンス化できる構文を導入 ❖ その場限りのインスタンスを作りたいときに便利
17.
AST(抽象構文木)の導入 ❖ 解釈フェーズが 1段増えた ❖ 難しい文法が導入 できるようになった ❖
opcodeの最適化を 行うようになった Zend VM opcode Parser Lexer token PHP Zend VM opcode Parser Lexer token PHP Opcode Compiler AST PHP 5 PHP 7
18.
返り値のタイプヒントをサポート ❖ 関数の返り値に型が指定できるようになった ❖ 抽象クラスやインターフェースで指定すると便利
19.
スカラ型のタイプヒントをサポート ❖ 以下の型が引数・返り値で指定できるようになった ❖ int型 ❖
float型 ❖ string型 ❖ bool型 ❖ 議論が続いていたが、ついに決着
20.
非推奨だった機能を廃止 ❖ PHP5.6までに非推奨になった機能をPHP7で廃止 ❖ ereg関数(preg関数使ってね) ❖
mysql関数(mysqli関数かPDO使ってね) ❖ その他
21.
アジェンダ ❖ さいきんのPHP7 ❖ PHP7の新機能 ❖
PHP7って速いの? ❖ どこがボトルネック? ❖ PHP7のデータ構造
22.
PHP7は速いらしい ❖ 「PHP5より倍速い」 ❖ 「HHVMとほぼ互角」 ❖
ホントに?
23.
PHP7の性能(1) Zeevのブログ記事(2014/7)より
24.
PHP7の性能(2) DmitryのZendCon 2014での発表(2014/10)より
25.
PHP7の性能(3) RasmusのFluent 2015での発表(2015/4)より
26.
PHP7の性能(4) ❖ 性能改善を積み重ねてきたことがわかる
27.
速くなりすぎ? ❖ PHP7は確かに速い ❖ 約1年間で2倍の高速化(WordPressで比較) ❖
今までも性能改善をサボっていたわけじゃない ❖ 過去10年間(PHP5.0→5.6)で2倍の高速化 ❖ 5.4以降は頭打ちの感さえあった
28.
何があったのか? ❖ メジャーバージョンアップならではの大手術 ❖ 基本的なデータ構造の変更 ❖
高速化チームの裁量が大きかった ❖ RFC「Move the phpng branch into master」 ❖ 様々なアイデアを約1年間に渡って実現
29.
❖ さいきんのPHP7 ❖ PHP7の新機能 ❖
PHP7って速いの? ❖ どこがボトルネック? ❖ PHP7のデータ構造
30.
性能改善に「銀の弾丸」はない ❖ 性能改善:ボトルネックを順につぶしていく作業 ❖ 一発で改善、みたいなことは滅多にない ❖
ボトルネック以外の箇所をいくら改善してもムダ ❖ ボトルネックを見つけるところからスタート
31.
PHP7チームが見つけたボトルネック ❖ PHP5でベンチマークテストしてみた ❖ メモリアロケーション・ハッシュ操作の時間
30% ❖ 内部関数の実行時間 30% ❖ VMの実行時間 30% ❖ その他 10%
32.
PHP7チームが見つけたボトルネック ❖ PHP5でベンチマークテストしてみた ❖ メモリアロケーション・ハッシュ操作の時間
30% ❖ 内部関数の実行時間 30% ❖ VMの実行時間 30% ❖ その他 10% この辺は今までチューニングしてきた
33.
PHP7チームが見つけたボトルネック ❖ PHP5でベンチマークテストしてみた ❖ メモリアロケーション・ハッシュ操作の時間
30% ❖ 内部関数の実行時間 30% ❖ VMの実行時間 30% ❖ その他 10% ほぼ手つかず、改善の余地ありそう
34.
メモリ周りがボトルネック候補 ❖ 具体的に何をすればいいのか? ❖ 普段のチューニングとは違う知識が必要
35.
Q. 何がボトルネック? ❖ N次元行列の行列積の実行時間(C言語で記述)
36.
行列積(擬似コード)
37.
Q. 何がボトルネック? ❖ 急に5倍ほど遅くなっている ?
38.
答: L3キャッシュミス ❖ 行列全体がキャッシュに乗り切らなくなった →CPUコアは余裕があるのにメモリで待たされる ❖
行列積の計算では同じ要素のreadがN回発生 ❖ 2回目以降キャッシュヒットするかどうかの差
39.
キャッシュの階層構造 L3 cache L1 cache L2
cache CPU core memory L1 cache L2 cache CPU core ❖ 一般に、上位キャッシュほど速くて小さい
40.
メモリの遅さ ❖ CPU 1クロックサイクル:0.3ns ❖
L1キャッシュヒット:1.2ns ❖ L2キャッシュヒット:3ns ❖ L3キャッシュヒット:12ns ❖ メモリアクセス:60-100ns 雑に言うと、メモリアクセス1回の間に演算300回できる
41.
メモリの遅さ ❖ メモリアクセスはボトルネックになりやすい ❖ CPUに対して相対的に遅い ❖
キャッシュを有効に使えるかどうかが重要 ❖ 上位キャッシュのヒット率アップ→性能改善 ❖ 例:データ構造のムダを削る
42.
キャッシュライン ❖ キャッシュは「キャッシュライン」単位で行われる ❖ キャッシュラインサイズ:64bytesなど ❖
連続したメモリ領域が一度にキャッシュされる ❖ 同時に使うデータは近いメモリ領域に置くと有利
43.
メモリ関連の最適化 ❖ キャッシュヒット率を向上 ❖ 可能な範囲でデータサイズを削る ❖
キャッシュラインを意識 ❖ 同時に使うデータは近いメモリ領域に配置する PHP7でも、このような最適化が行われている
44.
❖ さいきんのPHP7 ❖ PHP7の新機能 ❖
PHP7って速いの? ❖ どこがボトルネック? ❖ PHP7のデータ構造
45.
データ構造の変更 ❖ PHP7では性能改善のためデータ構造を見直した ❖ PHPの変数(zval) ❖
文字列(zend_string) ❖ 配列(HashTable / Bucket)
46.
PHP5のzval(int型) ❖ 未使用領域が多い (intの場合24bytes中10bytes) ❖ 必ずポインタ参照 ❖
参照カウンタを持つ、コピーオンライト
47.
PHP7のzval(int型) ❖ 計16bytes ❖ 参照カウントしない、代入では常にコピー
48.
PHP7のzvalへの評価 ❖ メモリ上のムダな隙間を減らす変更 ❖ ポインタ参照が1段減った ❖
int型・float型・bool型でコピーオンライト廃止 →サイズ削減によりキャッシュヒット率向上
49.
PHP5のzval(string型) ❖ 文字列長と文字列本体が別の領域になっている pointer refcount type
unusedis_ref unused pointer to zval string length string characters zval
50.
PHP7のzval(string型) ❖ 文字列長と文字列本体を連続領域に配置 ❖ 参照カウントあり、同じ文字列は使い回す string
characters flags pointer type reservedflags refcount type gc_info hash_value string length zend_string zval
51.
PHP7の文字列への評価 ❖ 文字列長と文字列本体を連続領域に配置 →キャッシュラインを意識した変更
52.
ねんがんの配列をてにいれたぞ! ❖ PHP7から、「本物の配列」が導入されました ! 「いままで配列なかったの?」 「はい」
53.
配列とは ❖ (典型的には)連続するメモリ領域を確保する ❖ インデックスは0から連続する数字 ❖
読み書きが高速 リンゴ バナナ トマト ニンジン 0 1 2 3
54.
連想配列とは ❖ 文字列をキーにできる ❖ そこそこ読み書きも速い(配列よりは遅い) "apple" 0 "banana"
"carrot" 1 2 3 4 5 6 7 キーのハッシュ値を計算 "apple"=>リンゴ"banana"=>バナナ "tomato"=>トマト "tomato" "carrot"=>ニンジン
55.
PHP5の配列 ❖ PHP5までは連想配列しか無かった ❖ $array[1]でも連想配列アクセスしていた ❖
配列より複雑な構造、キャッシュに優しくない
56.
PHP5の配列 nTableSize nNextFreeElement HashTable nTableMask nNumOfElements pListTail arBuckets unused pInternalPointer pListHead pDestructor nApp lyCo unt persi stent bAppl yProte ction unused h nKeyLength unused pData pDataPtr pListNext pListLast pNext pLast arKey Bucket zval pointer to
Bucket (Bucket *)[] pointer to Bucket pointer to Bucket pointer to Bucket Another(Bucket*) whichisinthesamehashbin
57.
PHP7の配列 ❖ PHP7から配列と連想配列が別の構造になった ❖ 配列のときはハッシュテーブルが省略される ❖
内部で自動的に選択される ❖ 配列・連想配列のデータは連続領域に置かれる
58.
PHP7の配列 arData flagsrefcount type gc_info zend_array u
nTableMask nNumUsed nNumOfElements nTableSize nInternalPointer nNextFreeElement pDestructor zval Bucket[] h (hash value) key (キーへのポインタ) h key 0 1 h key 2 zval zval ❖ 他言語の配列と同じ構造 (数字キーのみの場合)
59.
PHP7の配列への評価 ❖ 配列と連想配列の区別ができた ❖ 配列のときのムダが減った ❖
データが連続領域に置かれるようになった ❖ 1要素あたりデータサイズ減少(72bytes→32bytes) →キャッシュヒット率・キャッシュラインを意識した変更
60.
PHP7の新データ構造 ❖ 3つともキャッシュを意識したデータ構造 ❖ 性能面でインパクトの大きい変更 ❖
「PHPなかなかやるじゃん」
61.
PHP7の新データ構造 ❖ 3つともキャッシュを意識したデータ構造 ❖ 性能面でインパクトの大きい変更 ❖
「PHPなかなかやるじゃん」 ❖ 他の言語では以前から採用されている ❖ Python、Ruby、JavaScriptエンジン
62.
性能改善の面白さ ❖ 隣接領域の知識が役立つことがある ❖ 言語処理系ならCPUやメモリの知識 ❖
Webアプリならミドルウェア・ネットワークの知識
63.
まとめ ❖ PHP7は高速、PHP5.6の倍程度の性能 ❖ オシャレな新機能を採用 ❖
現代のCPUに合わせたデータ構造変更を行った ❖ データサイズ削減(キャッシュヒット率向上) ❖ 連続領域にデータを配置(キャッシュラインを意識)
64.
ご静聴 ありがとう ございました
Download