ホームページ  >  記事  >  バックエンド開発  >  変数分離/参照の PHP 原則の簡単な分析 (変数分離)_PHP チュートリアル

変数分離/参照の PHP 原則の簡単な分析 (変数分離)_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-21 14:59:44705ブラウズ

まず、zval の構造を確認しましょう:

コードをコピーします コードは次のとおりです:

struct _zval_struct {
refcount;
/* アクティブ型 */
zend_uchar is_ref;
} ;


refcount フィールドと is_ref フィールドを導入したことはありません。PHP が長期にわたって実行されるサーバーサイド スクリプト インタープリターであることはわかっています。したがって、そのためには、効率とリソース使用量が非常に重要な尺度になります。言い換えれば、PHP は次のコードを考慮してください。 ?php
$var = "laruence";
$var_dup = $var;
unset($var);
?> コードの最初の行は文字列変数を作成し、サイズが の文字列変数に適用します。 9 バイトのメモリ。文字列「laruence」と NULL (/0) 終端を保持します。 2 行目は、新しい文字列変数を定義し、変数 var の値をこの新しい変数に「コピー」します。
3 行目は変数 var の設定を解除します
このようなコードは、私たちの日常的なスクリプトで非常に一般的です。PHP がメモリを再割り当てし、変数の割り当てごとにデータをコピーする場合、上記のコードは 18 バイトのメモリ空間に適用する必要があります。上記のコードが実際にスペースの 2 つのコピーに適用する必要がないことは簡単にわかります。笑、PHP 開発者もそれを見たことがあるでしょう:
PHP の変数が使用されると前に述べました。symbol_table に格納されているシンボル名は zval に対応して実装されます。たとえば、上記のコードの最初の行では、値「var」が zval 構造体を指すポインタに対応して、symbol_table に格納され、変数値「laruence」「」がこの zval に保存されます。上記のコードの場合、「var」と「var_dup」に対応するポインターが同じ zval を指すようにできることは想像に難しくありません。
PHP もこれを行います。この時点で、これまで導入していなかった zval 構造体に refcount フィールドを導入する必要があります。
refcount は、その名前が示すように、現在の zval への参照の数を記録します。
たとえば、コードの場合:


コードをコピーします

コードは次のとおりです:


$var = 1;
$var_dup = $var;
?>
最初の行は整数変数を作成します。変数値は 1 です。 このとき、整数1を保存するzvalのrefcountは1です。 2 行目では、新しい整数変数が作成され、この変数も先ほど作成した zval を指し、この zval の refcount が 1 ずつ増加します。このとき、この zval の refcount は 2 です。 PHP は、このプロセスを理解するのに役立つ関数 debug_zval_dump を提供します:


コードをコピーします

コードは次のとおりです:

$var = 1;
debug_zval_dump($var);
$ var_dup = $ var;
debug_zval_dump($var);?> 出力: long(1) refcount(2)
long(1) refcount(3


気になる方は、var の refcount は 1 でなければなりませんか?
単純な変数の場合、PHP は値渡しであることを知っています。つまり、debug_zval_dump($var) が実行されると、$var が値によって debug_zval_dump に渡され、これにより、変数が割り当てられるときに var の refcount が 1 ずつ増加します。変数を指定すると、zval の refcount が 1 ずつ増加します。ここで、記事の冒頭のコードを振り返ってみましょう。unset($var) の最後の行が実行された後はどうなるでしょうか。はい、refcount は 1 減りますか? 上記のコード:


コードをコピーします


コードは次のとおりです:

$var = "laruence";
$var_dup = $var ;
unset($var);
debug_zval_dump($var_dup) ;
?> 出力: string(8) "laruence" refcount(2
しかし、以下のコードはどうでしょうか?



コードをコピー

コードは次のとおりです:


$var = "ラルエンス" ;

$var_dup = $var;
$var = 1;
?>

明らかに、このコードが実行された後も、$var_dup の値は「laruence」のままであるはずですが、これはどのように達成されるのでしょうか?
これは PHP のコピーオンライトメカニズムです。
変数を変更する前に、PHP はまず変数の refcount をチェックします。refcount が 1 より大きい場合、実行が到達したときに、PHP は上記のコードに対して別のルーチンを実行します。最初の 3 行で、PHP は $var が指す zval の refcount が 1 より大きいことを検出し、次に PHP は新しい zval をコピーし、元の zval の refcount を 1 減らして、$var と zval を分離するようにsymbol_table を変更します。 $var_dup (分離) 。この仕組みは、いわゆるコピー オン ライト(コピー オン ライト)です。
コードのテスト:
コードをコピーします コードは次のとおりです:

$var = "laruence";
$var_dup = $var;
$var = 1;
debug_zval_dump( $var) ;
debug_zval_dump($var_dup);
?>

出力:
long(1) refcount(2)
string(8) "laruence" refcount(2


これで、変数を使用してコピーする場合、PHP は実際には内部的にコピーせず、同じポインタ構造を使用してコピーすることがわかりました。可能な限りオーバーヘッドを節約するにはどうすればよいでしょうか?
コードをコピーします コードは次のとおりです:

$var = "laruence";
$ var_ref = &$var;
$var_ref = 1;
?>

このコードが終了すると、$var も間接的に 1 に変更されます。このプロセスが呼び出されます (書き込み時に変更: 書き込み時に変更)。このコピーには分離が必要ないことをご存知ですか?
この時点で zval の is_ref フィールドが使用されます:
上記のコードの場合、2 行目が実行された後、$var で表される zval が 2 になり、is_ref が設定されます。
3 行目に達すると、PHP はまず var_ref で表される zval の is_ref フィールドをチェックします。それが 1 の場合、一般的なロジックは次のとおりです。
コードをコピーします。 コードは次のとおりです:

if((*val)->is_ref || (*val)->refcount<2){


しかし、問題は再び起こります。次のコードですか?


コードをコピーします
コードは次のとおりです: $var = "laruence";
$var_dup = $ var;
$var_ref = &$var;
? >


上記のコードには、書き込み時のコピー用の変数 $var と $var_dup のペア、および書き込み時の変更メカニズム用の変数 $var と $ のペアがありますが、この状況はどのように機能しますか?
2行目が実行されると、前述のように、$var_dupと$varは同じzvalを指しており、refcountは2です。
3行目が実行されると、PHPは、操作対象のzvalのrefcountが大きいことを検出します1 より大きい場合、PHP は分離を実行し、$var_dup を分離し、$var と $var_ref を書き込み時の変更に関連付けます。つまり、refcount=2、is_ref=1;
このような分析の後、debug_zval_dump に結果を生成させることができます。そのrefcountは1です:



コードをコピーします
コードは次のとおりです: $var = "laruence";
$var_dup = &$var ;
debug_zval_dump ($var);
?>

出力:
string(8) "laruence" refcount(1


読者の皆さん、詳しい理由は少し分析すれば分かるので割愛します。;)
今回はPHPの変数を紹介しました分離機構 、次回は引き続き拡張機能のPHPスクリプトでパラメータを送受信する方法を紹介していきます。




http://www.bkjia.com/PHPjc/328119.html

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/328119.html技術記事まず、zval の構造を確認します。次のようにコードをコピーします。 struct _zval_struct { /* 変数情報 */ zvalue_value value; /* value */ zend_uint refcount...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。