• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
zval をダイエットしてみた
 

zval をダイエットしてみた

on

  • 3,978 views

 

Statistics

Views

Total Views
3,978
Views on SlideShare
592
Embed Views
3,386

Actions

Likes
1
Downloads
1
Comments
0

8 Embeds 3,386

http://sasezaki.hatenablog.com 1859
http://d.hatena.ne.jp 1428
https://twitter.com 66
http://feedly.com 26
http://digg.com 2
http://s.deeeki.com 2
http://www.feedspot.com 2
http://localhost 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    zval をダイエットしてみた zval をダイエットしてみた Presentation Transcript

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