Copy Code code as follows:
Function Binsearch (& $arr, $key, $value)
{
$low = 0;
$high = count ($arr);
while ($low <= $high) {
$mid = Floor ($low + ($high-$low)/2);
$item = $arr [$mid] [$key];
if ($item = = $value) {
return $mid;
else if ($value > $item) {
$low = $mid + 1;
} else {
$high = $mid-1;
}
}
return false;
}
In this case, the $mid uses the first subtraction method to calculate, in order to prevent the overflow of integers. Not deliberately write complicated.
I use the following code to test:
Copy Code code as follows:
$data = Array ();
for ($i = 0; $i < 1000000; $i + +)
{
$data [] = Array ("sq" => $i * 2);
}
Var_dump (Binsearch ($data, "sq", 10000));
found that when the binsearch, always to spend a 0.2s or so. In theory, 1 million of the data, that is, the cycle is 20 times. How could it be so slow?
Later, the memory was monitored, and the data array consumed 230M of memory. While Binsearch, it takes up 60K of memory. But, theoretically, binsearch
Should not occupy so much memory. Because, I think, I have used the reference, there is no change in the structure of data.
I am also baffled, and later, I took the reference parameters removed, incredibly binsearch as long as 0.0002s, it seems that the reference cost a lot of CPU resources.
PHP internally follows the principle of a copy on write. In fact, this reference is superfluous.
But why does adding a reference speed slow? Today we will focus on this issue. After understanding the reason, we must know how to use the reference.
If you $a = & $data directly before the Binsearch call, the reference will be very fast. It does not seem to be a question of the citation itself.
This problem actually involves how the Zend engine manages PHP variables.
Let's look at the following questions:
Copy Code code as follows:
<?php
Function demo (& $a, & $b) {$a =& $b;}
$a = 1;
$b = 2;
Demo ($a, $b);
$b = 3;
Print $a;
?>
What is the output of $a? Yes, it's 2. But at first I thought it was 3.
So how do you explain the above problem?
In fact, the parameter reference of a function is done this way.
Copy Code code as follows:
$tmp = $a;
$a 1 = & $tmp;
$a = $tmp;
unset ($a 1, $tmp);
Here, the reference is actually a temporary variable. At this point, the $tmp is a reference attribute, and the $a variable is not a reference attribute.
Depending on how the Zend engine manages memory, it cannot be represented internally by a zval, which must be forcibly detached from the zval.
With this method of understanding, the above problem is solved. Inside a function, the reference attribute outside the function is not changed. This is also PHP
Not in favor of the reason of Calltime_by_ref, but choose the above so inefficient copy method.
The following analysis also proves that a copy does occur when the parameter is passed.
Inside the Binsearch function.
$data [0] = 1;
In this way, a copy of the $data's zval occurs once. The amount of memory used is 60K. is exactly the same as the reference to the function call.
Maybe a lot of people will doubt, why not more 230M, this is actually the smart of PHP, array key corresponds to a zval pointer. (internal is a hash table)
So just copy these pointers over and over again, and the data doesn't have to be copied. However, 1 million of the PHP hash table actually consumes 50M of RAM. Why is it only 60K.
On the outside of the Binsearch function, run
Copy Code code as follows:
$t = $data;
$t [0] = 1;
Unset ($t);
Sure enough, more 60K of RAM. Estimation is related to the memory management mechanism of PHP.
Now it's all clear! Today, think for several hours, just put this problem figured out, dare not to enjoy alone.
The reference in the function is not for you to pass the parameter convenient, but let you realize, a function, can have multiple return value, so, it is best not to gild the lily.
In fact, referencing it can degrade performance.