First, let's review the structure of Zval:
Copy Code code as follows:
struct _zval_struct {
/* Variable Information * *
Zvalue_value value; /* Value * *
Zend_uint RefCount;
Zend_uchar type; /* Active type */
Zend_uchar Is_ref;
};
Where the RefCount and Is_ref fields we have never introduced, we know that PHP is a long-running server-side script interpreter. So for it, efficiency and resource occupancy rates are a very important measure, that is, PHP must try to describe the memory footprint, consider the following code:
Copy Code code as follows:
<?php
$var = "Laruence";
$var _dup = $var;
Unset ($var);
?>
The first line of code creates a string variable that requests a memory size of 9 bytes, holding the string "Laruence" and the end of a null (/0).
The second line defines a new string variable and "copies" the value of Var to the new variable.
The third line unset variable var
Such code is very common in our usual scripts, if PHP for each variable assigned to the memory, copy data, then the above code to apply for 18 bytes of memory space, and we can easily see that the above code in fact, there is no need to apply for two spaces, hehe, The developers of PHP also see:
As we've said before, variables in PHP are implemented with a symbol name stored in symbol_table, a zval, for example, for the first line of code, which stores a value "Var" in symbol_table, with a pointer to a ZVAL structure, The variable value "laruence" is stored in this zval, so it is not difficult to imagine that for the above code, we can completely let "var" and "Var_dup" corresponding to the pointer to the same zval on it.
PHP does the same, and this time we need to introduce the RefCount fields in the zval structure that we haven't covered before.
RefCount, as the name suggests, records the current count of Zval being referenced.
For example, for code:
Copy Code code as follows:
<?php
$var = 1;
$var _dup = $var;
?>
The first line creates an integer variable with a value of 1. At this point, the refcount of the Zval, which holds the plastic 1, is 1.
The second line creates a new shape variable, and the variable points to the zval you just created, and adds 1 to the refcount of this zval, at which point the refcount of this zval is 2.
PHP provides a function to help us understand this process debug_zval_dump:
Copy Code code as follows:
<?php
$var = 1;
Debug_zval_dump ($var);
$var _dup = $var;
Debug_zval_dump ($var);
?>
Output:
Long (1) refcount (2)
Long (1) refcount (3
If you're surprised, the refcount of Var should be 1?
We know that for simple variables, PHP wears parameters in the form of values. That is, when the Debug_zval_dump ($var) is executed, the $var passes the value to Debug_zval_dump, which leads to the RefCount plus 1 of Var, so as long as we can see that when the variable is assigned to a variable, The fact that it can lead to Zval's RefCount plus 1.
Now we look back at the code at the beginning of the article, what happens when the last line of unset ($var) is executed? Yes, both RefCount minus 1, on the code:
Copy Code code as follows:
<?php
$var = "Laruence";
$var _dup = $var;
Unset ($var);
Debug_zval_dump ($var _dup);
?>
Output:
String (8) "Laruence" RefCount (2
But what about the following code?
Copy Code code as follows:
<?php
$var = "Laruence";
$var _dup = $var;
$var = 1;
?>
Obviously after this code executes, $var _dup value should still be "laruence", then how does this achieve?
This is the copy on write mechanism for PHP:
PHP before modifying a variable, will first look at the refcount of the variable, if the RefCount is greater than 1,php will perform a separate routine, for the above code, when executed to the third line, PHP found that $var point zval more than 1 refcount, Then PHP will copy a new zval out, reduce the original Zval RefCount by 1, and modify the symbol_table to make $var and $var_dup separate (separation). This mechanism is called copy on write.
Code Test on:
Copy Code code as follows:
<?php
$var = "Laruence";
$var _dup = $var;
$var = 1;
Debug_zval_dump ($var);
Debug_zval_dump ($var _dup);
?>
Output:
Long (1) refcount (2)
String (8) "Laruence" RefCount (2
Now we know that when we use variables to replicate, PHP is not a real copy, but rather a point to the same structure to save as much overhead as possible. So, what about the references in PHP?
Copy Code code as follows:
<?php
$var = "Laruence";
$var _ref = & $var;
$var _ref = 1;
?>
After this code is finished, the $var is also modified indirectly to 1, which is called (change on write: changes when writing). So how does ze know that this copy does not need to be separation?
This is the time to use the Is_ref field in Zval:
For the above code, when the second row is executed, the refcount of the Zval represented by the $var becomes 2 and the Is_ref is set at 1.
To the third line, PHP first check the VAR_REF representative of the Zval is_ref field, if 1, then do not separate, the general logic is as follows:
Copy Code code as follows:
if ((*val)->is_ref | | (*val)->refcount<2) {
Do not perform separation
...;//process
}
But the question is again, what about the following code?
Copy Code code as follows:
<?php
$var = "Laruence";
$var _dup = $var;
$var _ref = & $var;
?>
For the above code, there is a pair of copy on write variables $var and $var_dup, and a pair of variables on the write mechanism for $var and $var_ref, how does this work?
When the second line is executed, as previously said, $var _dup and $var point to the same zval, RefCount 2.
When the third line is executed, PHP discovers that the refcount of the zval to be manipulated is greater than 1, then PHP executes the separation, separates the $var_dup, and associates $var and $var_ref with the change on write. Namely, refcount=2, is_ref=1;
Based on this analysis, we can let debug_zval_dump out of the results of RefCount 1:
Copy Code code as follows:
<?php
$var = "Laruence";
$var _dup = & $var;
Debug_zval_dump ($var);
?>
Output:
String (8) "Laruence" RefCount (1
Detailed reasons, the reader you just a little analysis can be drawn, I will not take over. ;)
This time we introduced the PHP variable separation mechanism, next time I will continue to introduce if the PHP script in the extension received and outgoing parameters.