在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。
複製****如下:
function binsearch(&$arr, $key, $value)
else if ($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。
那麼怎麼解釋上面這個問題呢?
實際上,函式的引數引用是這樣進行的。
複製****如下:
$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 elseif value item else return false 在這裡,mid 採用了先減後加的方法計算,目的是為了防...
PHP 引用是個壞習慣
這篇文章,寫的比較早,有一些錯誤的說法,我表示非常歉意。一些 沒有經過嚴格的測試,以後寫部落格一定要非常謹慎。因為可能會對一些人產生誤導。在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。function binsearch arr key ...
PHP 引用是個壞習慣
這篇文章,寫的比較早,有一些錯誤的說法,我表示非常歉意。一些 沒有經過嚴格的測試,以後寫部落格一定要非常謹慎。因為可能會對一些人產生誤導。在寫php 程式的時候,很多人在傳遞引數的時候,喜歡用乙個引用。特別是在乙個陣列非常的大的時候,更是喜歡加。function binsearch arr key ...