参照による値の受け渡しのマイナス面

歌詞なしで、直接: リンクを使用して値を渡すと、パフォーマンスが低下します 。 スクリプトは変数のコピーを渡すのではなく、変数自体を渡すと考えています。これに基づいて、これはより速く動作するはずだと結論付けています。 悲しいかな、これは誤りです。 理由を理解するために、Zend Engineが値を処理する方法を理解しましょう。



変数を操作する場合、Zend Engineプロセッサは、参照カウント、記録中のコピーを使用した値システムを実装します。 これは、 多くの変数が同じ値を指すことができることを意味します 。 ただし、多数のメモリブロックは消費されません。 例を考えてみましょう:



  1. <?php $a = array(1, 2, 3, 4, 5); $b = $a; ?>



  2. <?php $a = array(1, 2, 3, 4, 5); $b = $a; ?>



  3. <?php $a = array(1, 2, 3, 4, 5); $b = $a; ?>



  4. <?php $a = array(1, 2, 3, 4, 5); $b = $a; ?>





変数$ bには変数$ aの値割り当てられますが、データ自体はどこにもコピーされません! 代わりに、変数$ bは 、変数$ aが保存されているメモリ内の同じ場所を指すように変換されます。 最初に割り当てられたデータの保存場所に保存します(この場合、これは値を持つ配列です)。 プロセッサは配列にマークを付け、参照カウンターを2に増やします。 別の例を考えてみましょう:



  1. <?php
  2. $ a = array(1、2、3、4、5);
  3. $ b = $ a;
  4. $ a [] = 6;
  5. print_r($ a);
  6. print_r($ b);
  7. ?>


変数の値が同じであることを誰も期待していないことを願っていますか? :)冗談。 では、メモリ内の1つの場所へのリンクについて話していたらどうなりましたか? 配列の変更を開始すると、Zend Engineプロセッサは$ aバージョンと$ bバージョンを分離しました 。 プロセッサが複数のリンクがある値によって書き込み操作を検出するとすぐに、データがコピーされます-他のリンクと接続されていない別のメモリにある同じ値が作成されます。 また、記録中のコピー手順が完了した後にのみ、操作が続行されます。 このタイムリーな複製により、副作用なしで生産性が向上します。 そして、不必要なデータのコピーを除外したおかげです!



ただし、上記のすべてが「なぜ参照による送信が悪なのか」という質問に対する答えを提供するわけではありません。



第一に、それは役に立たない リンクカウントメカニズムのおかげで、変数を参照で渡す必要はありません。 プロセッサ自体は、わずかな機会に不必要なコピーを回避します。



第二に、プロセッサ...ですので、例をよく見てみましょう。 コードにコンテンツを印刷する関数を追加します。



  1. <?php
  2. 関数prepareArr(&$ arr){
  3. 印刷回数($ arr)* 2;
  4. }
  5. $ a = array(1、2、3、4、5);
  6. $ b = $ a;
  7. prepareArr($ a);
  8. ?>


プロセッサが$ a配列をprepareArr()関数に渡すと、値(配列)を参照渡しする必要があると判断します。 次に、参照カウントが1より大きいことを発見します(この例では2です)。 $ a配列の値は参照によって渡され、関数が行う変更が$ bに影響を与えることはないため、プロセッサーは$ aおよび$ b配列に対して別々のコピーを作成します。 変数の値を関数に渡すとき、Zengエンジンは単純に参照カウントを増やすことができます。



ナノ最適化だと思いますか? たぶん、しかし、参照によって値を渡すとき、この操作のパフォーマンスの30%を失います 。 また、使用するデータ量が多いほど、操作の速度は低下します。



たとえば、50,000回の繰り返しのループで最後の例を実行すると、0.4538291秒になります。 同じスクリプトですが、リンクを使用せずに、0.3090010秒で実行されます。 30%速くなりました。 データ量を6.5 kbに増やすと、5000回の反復からのサイクルの実行は19.7765129秒になります。 7.3865049秒。 それに応じて。 あなたが推測した最後の図は、リンクを使用せずに関数を実行した結果です。



パフォーマンス上の理由から、参照渡しの値を使用することはお勧めしません。 リンクの使用は、機能的な観点から意味がある場合にのみ正当化されます。



All Articles