PHP 引用是個壞習慣

2021-05-23 12:22:50 字數 2061 閱讀 7493

在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。

function

binsearch(

& $arr

,  

$key

,  

$value

) elseif(

$value

>

$item

)  else

}return

false

;}

在這裡,$mid 採用了先減後加的方法計算,目的是為了防止整數的溢位。不是故意寫複雜了。

我用下面的**進行測試:

$data = array();

for ($i = 0; $i < 1000000; $i++)

var_dump(binsearch($data, "sq", 10000));

發現,binsearch 的時候,總是要花個 0.2s左右。理論上來說,100萬的資料,最多也就是迴圈20次。怎麼會這樣慢呢。

後來監控了一下記憶體,data 陣列 占用了 230m 的記憶體。而 binsearch 的時候,占用了60k 的記憶體。但是,理論上來說,binsearch

不應該占用如此多的記憶體。因為,我覺得,我已經用引用了,根本就沒有對data 的結構進行修改。

我也是百思不得其解,後來,我把引用引數去掉,居然 binsearch  只要 0.0002s ,看來是引用耗費了大量的cpu 資源。

php 內部遵循乙個copy on write 的原則。實際上這個引用是多餘的。

但是為什麼,加了引用速度會變慢呢?今天重點就談談這個問題。明白道理後,大家一定知道怎麼用引用了。

如果在binsearch 呼叫前,直接 $a = &$data,這個引用的速度會非常的快。看來肯定不是引用本身產生的問題。

這個問題,實際上涉及了zend 引擎如何管理php變數。

先看下面的問題:

<?php

function demo

(&$a

, &$b

) $a = 1

;$b = 2

;demo(

$a, 

$b);

$b = 3;

print $a;

?>

$a 輸出是多少呢?不錯,是2. 不過,我一開始覺得是3。

那麼怎麼解釋上面這個問題呢?

實際上,函式的引數引用是這樣進行的。(只是乙個猜想,有時間研究下php核心)

$tmp = $a;

$a1 = &$tmp;

$a = $tmp;

unset($a1, $tmp);

這裡,引用的實際上是乙個臨時變數。這個時候,$tmp 是帶引用屬性的,而$a 變數不是帶引用屬性的。

根據zend引擎管理記憶體的方法,在內部,不能用乙個zval 來表示,必須強制分離這個zval。

用這樣的理解方法,上面的問題就解決了。函式內部,不會改變函式外部的引用特性。這也是php

不贊成用 calltime_by_ref 的原因,而選擇上面如此低效的拷貝方法。

下面的分析,也能證明,在傳遞引數時,的確發生了拷貝。

在 binsearch 函式裡面。

$data[0] = 1;

這樣,就會發生一次$data 所在zval 的拷貝。記憶體使用量 就是 60k。和函式呼叫加引用一模一樣。

可能很多人會疑問,為什麼不是多了230m呢,這其實就是php的高明之處,陣列key 對應的是乙個zval的指標。(內部是乙個雜湊表)

所以,只要把這些指標複製一遍就就好了,資料不用複製。但是,100萬的php 雜湊表實際上要占用 50m 記憶體。為什麼只有60k呢。

在 binsearch 函式的外面,執行

$t = $data;

$t[0] = 1;

unset($t);

果然,多了60k 的記憶體。估計和php的記憶體管理機制有關係。

現在一切都明白了吧!今天,想了好幾個小時,才把這個問題想通,不敢獨享。

函式中的引用不是給你傳引數方便的,而是讓你實現,乙個函式,可以有多個返回值的,所以,最好不要畫蛇添足。

實際上,用引用它會降低效能。

PHP 引用是個壞習慣

在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。複製 如下 function binsearch arr,key,value else if value item else return false 在這裡,mid 採用了先減後加的方法計算...

PHP 引用是個壞習慣

這篇文章,寫的比較早,有一些錯誤的說法,我表示非常歉意。一些 沒有經過嚴格的測試,以後寫部落格一定要非常謹慎。因為可能會對一些人產生誤導。在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。function binsearch arr key ...

PHP 引用是個壞習慣

這篇文章,寫的比較早,有一些錯誤的說法,我表示非常歉意。一些 沒有經過嚴格的測試,以後寫部落格一定要非常謹慎。因為可能會對一些人產生誤導。在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。function binsearch arr key ...