ホームページ  >  記事  >  php教程  >  参照カウント: PHP ソース コード分析 - 変数参照カウント、コピーオンライト (参照カウントとコピーオンライト)

参照カウント: PHP ソース コード分析 - 変数参照カウント、コピーオンライト (参照カウントとコピーオンライト)

WBOY
WBOYオリジナル
2016-06-21 08:50:221148ブラウズ

PHP 構文には、参照代入と非参照代入という 2 つの代入方法があります。
$a = 1;
$b = $a; // 非参照代入
$c = &$b; // 表面上は参照代入, 通常、次のように考えられます。「参照代入とは、2 つの変数が同じ変数 (実際には C の zval) に対応することを意味しますが、非参照代入とは、新しい変数 (zval) を直接生成し、同時に値をコピーすることを意味します」 。」
この種の考え方は、ほとんどの場合理解できます。 (#1)
ただし、場合によっては非常に非効率になります。たとえば: (#2)
function print_arr($arr){//非参照パス
print_r ($arr);
}
$test_arr = array(
"a" => "a",
"b" => "b",
"c" = > "c",
...
);// ここに比較的大きな配列
print_arr($test_arr);// 出力を実行するために print_arr 関数が初めて呼び出されるとき
print_arr($ test_arr);//出力を実行するために print_arr 関数が 2 回目に呼び出される
上記の理解 (#1) に従う場合、print_arr は 2 回実行され、これは非参照メソッドです。 $test_arr の新しい変数とまったく同じコピーが 2 つ生成されるため、非常に非効率的になります。
実際のコードが実行されているとき、2 つの新しい変数は生成されません。なぜなら、PHP カーネルはすでに最適化に役立っているからです。
それはどのように実装されますか?ここで、この記事の要点である参照カウントとコピーオンライトについて説明します。これは、参照カウントとコピーオンライトの 2 つのメカニズムを使用して最適化されます。
これら 2 つのメカニズムを紹介する前に、まず基本的な知識、つまり PHP の変数がカーネル内でどのように表現されるかを理解しましょう。
PHP で定義された変数は zval で表されます。zval の定義は Zend/zend.h で定義されます。
typedef struct _zval_struct zval;
typedef Union _zvalue_value {
long lval; value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; value */
zend_object_value obj;
} zvalue_value;
struct _zval_struct {
/* 変数情報 */
zvalue_value value */
zend_uint refcount; zend_uchar type; /* active type */
zend_uchar is_ref;
};
このうち、refcount と is_ref は、参照カウントとコピーオンライトの 2 つのメカニズムを実装するための基礎です。
refcount 現在の変数には参照カウントが格納されます。これは、zval が最初に作成されたときは 1 です。参照が追加されるたびに、refcount++ が追加されます。参照分離を行う場合は、refcount-- を実行します。
is_ref は、zval が参照状態であるかどうかを示すために使用されます。 zval は初期化すると 0 になり、参照ではないことを意味します。
$a;//a:refcount=1,is_ref=0,value=NULL;
$a = 1; //a:refcount=2,is_ref=0,value =1;
$b = $a; //a,b:refcount=3,is_ref=0,value=1;
$c = $a; ,is_ref=0,value=1;
$d = &$c; //a,b:refcount=3,is_ref=0,value=1; c,d:refcount=1, is_ref=1, value =1 上記のコードのコメントは、この行が実行されたときの refcount と is_ref の変化を示しています。
Copy on Write
Php 変数は、変数値の 1 つが参照カウントによって共有されることを示しています。変更されましたか?
変数を書き込もうとするときに、その変数が指す zval が複数の変数で共有されていることがわかると、Zend は ref_count が 1 の zval をコピーし、元の zval の refcount をデクリメントします。このプロセスが呼び出されます。 「ズヴァル分離」。 zend は書き込み操作が発生したときにのみコピー操作を実行することがわかり、コピー オン ライト (書き込み時コピー) とも呼ばれます。
参照変数の場合、要件は非参照型の要件と逆になります。参照によって割り当てられた変数はバンドルされている必要があり、1 つの変数を変更すると、バンドルされたすべての変数が変更されます。
$a=1;
$b=$a;実行時のメモリ構造図:
この記事へのリンク http://www.cxybl.com/html/wlbc /Php/20130113/36056.html



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。