The problem
As mentioned in the previous chapter, REFERENCE was a flag bit in PHP5, but since PHP7 we’ve changed it to a new type :IS_REFERNCE. However, reference is a very common application, so this change has brought a lot of changes, and also caused a lot of bugs when we did PHP7 development, because sometimes we forgot to deal with this type.
The simplest case is when dealing with various types, and from now on we have to think about new types. For example, in PHP7, such code forms are becoming common:
try_again:
swtich (Z_TYPE_P(zv)) {
case IS_TRING:
break;
case IS_ARRAY:
break; .case IS_REFERENCE:
zv = Z_REFVAL_P(zv); / / reference solution
goto try_again;
break;
}
Copy the code
If people write their own extensions, they can cause problems if they forget to consider this new type.
Why is that?
So with all the problems that this new type can cause, why did you make a reference a type at the time? Why not use a flag bit instead?
In short, we have to do it. -_# – Hashtable stores zval, so how can two ZVal share a value in a symbol table? For complex types such as strings, it seems possible to put a flag bit in the zend_refcounted structure to indicate that it was resolved by reference. However, the Change On Write version of that might be duplicated, but we know that in PHP7, the counted bits of the zend_ref_counted structure may not be counted. Some types are stored directly in zval, such as IS_LONG, but reference types are reference-counted. What about a zval that is IS_LONG and IS_REFERNCE?
To do this, we created this new genre:
As you can see, a reference is a new type :zend_reference. For a zval of IS_REFERNCE type, zval.value.ref is a pointer to Zend_reference that contains a reference count and a zval, The value of zval is stored in zval.value.ref->val. So for the IS_LONG reference, we use a zval of type IS_REFERNCE, which points to a zend_reference, which in zend_reference->val is a zval of type IS_LONG.
Change On Write
PHP uses reference counting for simple garbage collection. Consider the following code:
1. $val = "laruence";
2. $ref = &$val;
3. $copy = $val;
? >
Copy the code
Ref and ref and ref and val are references to the same zval. In PHP5, we indicated this by having a reference count of 2 and reference flag bit of 1. When copying val to val to copy(line 3), We find that $val is a reference with a count greater than 1, so produce Change on write, which is split. So we need to copy this zval.
In PHP7, the situation is much simpler, first generating an IS_REFERNCE type when the reference is assigned to $ref(line 2), Zend_reference = zval.value.ref->gc.refcount = 2
$copy = zval.value.ref->val; $copy = zval.value.ref->val; $copy = zval.value. Is the string value of laruence zval, then the reference count for the zval + 1, namely zval. Value. The ref – > val. Value. STR. Gc. Refcount to 2. There is no replication.
This solves the classic PHP5 problem described in the previous chapter. For example, when we run PHP7, we get the following result:
$ php-7.0/sapi/cli/php /tmp/1.php
Used 0.00021380008539
Used 0.00020173048281
Copy the code
You can see that there is no replication and therefore no performance issues.
The above content hopes to help you, more free PHP factory PDF, PHP advanced architecture video materials, PHP wonderful good article can be wechat search concerns: PHP open source community
2021 Jinsanyin four big factory interview real questions collection, must see!
Four years of PHP technical articles collation collection – PHP framework
A collection of four years’ worth of PHP technical articles – Microservices Architecture
Distributed Architecture is a four-year collection of PHP technical articles
Four years of PHP technical essays – High Concurrency scenarios
Four years of elite PHP technical article collation collection – database