Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

zval をダイエットしてみた

  • Login to see the comments

zval をダイエットしてみた

  1. 1. Reducing size of zval structure zvalをダイエット してみた hnw 第五回闇PHP勉強会 (2014/3/15)
 発表資料
  2. 2. 自己紹介 ❖ @hnw! ❖ 勤務先:KLab株式会社! ❖ カレーとバグが大好物! ❖ 好きなdouble値:NaN
  3. 3. 発想 ❖ NaN boxingってカッコいい! ❖ doubleの一部にポインタや整数を詰め込む技! ❖ PHPにも応用できないか?! ❖ サイズ減らす点だけなら真似できそうだ! ❖ やってみた
  4. 4. アジェンダ ❖ PHPのzval概要! ❖ zvalをダイエットする! ❖ さらなるダイエットへの道
  5. 5. ❖ PHPのzval概要! ❖ zvalをダイエットする! ❖ さらなるダイエットへの道
  6. 6. PHPの変数を考える ❖ C:静的型付け言語! ❖ コンパイル時に型が決まる! ❖ 変数に型情報をつける必要が無い! ❖ PHP:動的型付け言語! ❖ 実行時まで型が決定できない! ❖ 変数値と型情報のペアを持ち回る必要がある
  7. 7. PHPの変数 ❖ C言語レベルでは、zval構造体で管理されている typedef struct _zval_struct zval; ! struct _zval_struct { zvalue_value value; /* 変数値 */ zend_uint refcount__gc; /* 参照カウンタ */ zend_uchar type; /* 変数型 */ zend_uchar is_ref__gc; /* 参照渡しされたか */ };
  8. 8. zvalのtypeに入る値 ❖ 変数型ごとに異なるtype値が定義されている #define IS_NULL 0 #define IS_LONG 1 #define IS_DOUBLE 2 #define IS_BOOL 3 #define IS_ARRAY 4 #define IS_OBJECT 5 #define IS_STRING 6 #define IS_RESOURCE 7 #define IS_CONSTANT 8 #define IS_CONSTANT_ARRAY 9 #define IS_CALLABLE 10
  9. 9. 変数値に対応する共用体 ❖ 全ての変数型に対応する値を格納できる typedef union _zvalue_value { long lval; /* intとboolとresource */ double dval; /* float */ struct { char *val; /* 文字列 */ int len; /* 文字列長 */ } str; /* string */ HashTable *ht; /* array */ zend_object_value obj; /* object */ } zvalue_value;
  10. 10. zvalざっくり概要 ❖ zval:PHPの変数1個に対応する構造体! ❖ メンバ変数! ❖ 型は何か! ❖ 値は何か! ❖ 参照カウンタ! ❖ 参照渡しされたか
  11. 11. ❖ PHPのzval概要! ❖ zvalをダイエットする! ❖ さらなるダイエットへの道
  12. 12. zvalのサイズ減=高速化? ❖ 仮説:zvalのサイズを減らすとPHPが性能アップする! ❖ zvalのサイズって減らす余地あるのかしら?
  13. 13. zvalのサイズ ❖ 64bit環境では24byteになる typedef struct _zval_struct zval; ! struct _zval_struct { zvalue_value value; /* 128bit、変数値 */ zend_uint refcount__gc; /* 32bit、参照カウンタ */ zend_uchar type; /* 8bit、変数型 */ zend_uchar is_ref__gc; /* 8bit、参照渡しされたか */ }; /* 196bit */
  14. 14. _zvalue_valueのサイズ typedef union _zvalue_value { long lval; /* 64bit */ double dval; /* 64bit */ struct { char *val; /* 64bit */ int len; /* 32bit */ } str; /* 128bit */ HashTable *ht; /* 64bit */ zend_object_value obj; /* 128bit */ } zvalue_value; ! typedef struct _zend_object_value { zend_object_handle handle; /* 32bit */ const zend_object_handlers *handlers; /* 64bit */ } zend_object_value; /* 128bit */ ! typedef unsigned int zend_object_handle;
  15. 15. 64bit環境のzvalはスカスカ ❖ zval構造体の内訳! ❖ 変数値に96bit(12byte)! ❖ 参照カウンタ・その他で32bit+9bit! ❖ 実質18byteだが、alignmentの都合で24byte消費! ❖ 9bit節約すれば16byteにできるはず
  16. 16. zvalダイエット図解 _zvalue_value refcount__gc unused unused type is_ref__gc ❖ 現状:24byte消費(64bit環境)
  17. 17. zvalダイエット図解 ❖ これで16byteにできないか? _zvalue_value refcount__gc type is_ref__gc
  18. 18. zvalダイエットの方針 ❖ _zvalue_valueの「あまり」に参照カウンタを詰める! ❖ 参照カウンタを32bitから23bitに減らす! ❖ 浮いた9bitに変数型とis_ref_gcを詰める
  19. 19. zvalダイエットの実装 ❖ _zval_structを構造体から共用体に変更! ❖ 詰めて使うための工夫! ❖ 基本的にzval関連のマクロを修正するだけでよい! ❖ Z_TYPE_P()とかZ_ADDREF_P()とか! ❖ 行儀の悪い箇所もあるので、チマチマ修正! ❖ https://github.com/hnw/php-src/tree/PHP-5.5.9-smallzval
  20. 20. zvalダイエットの結果 ❖ make testが99%以上通る程度には動いた!! ❖ ベンチマークテストを動かしてみた! ❖ sizeof(zval)は24→16に減った! ❖ 性能面:ほぼ同じか少し遅い印象…! ❖ 消費メモリ量:zvalのサイズ減による寄与はわずか
  21. 21. ❖ PHPのzval概要! ❖ zvalをダイエットする! ❖ さらなるダイエットへの道
  22. 22. 失敗の原因を考える(1) ❖ 個別に速度測定! ❖ zvalのallocationは速くなった! ❖ zval同士の値のコピーは少し遅くなった! ❖ 参照カウンタへのアクセスも少し遅くなった! ❖ 仮説1:差し引きゼロ! ❖ データの持ち方が複雑すぎる?
  23. 23. 失敗の原因を考える(2) ❖ そもそも、zvalはポインタ渡しされることが多い! ❖ zvalのallocationやcopyが少ないとすれば、
 サイズ減をしても生きない! ❖ 仮説2:「変数のサイズ減=性能向上」がPHPでは成り 立たない
  24. 24. ポインタ渡しの功罪 ❖ 「大きい構造体を値渡しするのはダメ」という常識! ❖ (少なくとも昔は)Cの入門書に書いてあった! ❖ いまやポインタ64bit時代! ❖ 参照渡しのコストが相対的に増大! ❖ PHPは値渡しを避けすぎて無駄なコストを払っている?! ❖ 64bit環境だとzvalはポインタサイズの高々3倍
  25. 25. Copy-on-write の功罪 ❖ PHPの変数コピーは「Copy-on-write」! ❖ PHP上の代入・値渡し=実装上はポインタ渡し! ❖ 必要があるときだけコピーする! ❖ コピーは最低限になる! ❖ 変数の代入のたびに参照カウンタの増減が必要! ❖ 値渡しより、メモリへのwriteはむしろ増える?
  26. 26. まとめ(一部妄想) ❖ PHPのzvalをダイエットしたが効果は無かった! ❖ PHPの「Copy-on-write」は現代のCPUでは生きない?! ❖ 基本型を値渡しすれば高速化の道もあるのでは! ❖ (zval *)にNaN boxingでint/doubleを入れたい! ❖ zvalのまま使ってる場所の始末が非現実的かも…
  27. 27. ご静聴 ありがとう ございました

×