I am following a tutorial & reading through some articles on how variables are stored in PHP using zval (zend value) container. Most of those articles seem to be following & getting information from the documentation on php.net doc. I got curious about how zval
struct is implemented in PHP's core, so I opened up the source code from PHP8 & it looks different than what those articles or the php.net are stating. For example, in php.net it states that zval
container contains refcount
and is_ref
but those two are not part of the source code when I look at it in PHP8. So after some digging, I found out that refcount
& is_ref
were part of zval
struct back in PHP5 but then changed in PHP7 which introduced performance optimizations including better memory management.
This is the struct code for zval
from PHP5:
struct _zval_struct {
zvalue_value value;
zend_uint refcount__gc;
zend_uchar type;
zend_uchar is_ref__gc;
};
This is what it looks like since PHP7 in PHP8:
struct _zval_struct {
zend_value value; /* value */
union {
uint32_t type_info;
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type, /* active type */
zend_uchar type_flags,
union {
uint16_t extra; /* not further specified */
} u)
} v;
} u1;
union {
uint32_t next; /* hash collision chain */
uint32_t cache_slot; /* cache slot (for RECV_INIT) */
uint32_t opline_num; /* opline number (for FAST_CALL) */
uint32_t lineno; /* line number (for ast nodes) */
uint32_t num_args; /* arguments number for EX(This) */
uint32_t fe_pos; /* foreach position */
uint32_t fe_iter_idx; /* foreach iterator index */
uint32_t property_guard; /* single property guard */
uint32_t constant_flags; /* constant flags */
uint32_t extra; /* not further specified */
} u2;
};
So I am trying to find some updated/relevant information about this and can't seem to find a good explanation that would include some illustrations on how it compares to PHP5 or is documentation on php.net still relevant? Does ref counting no longer matter since PHP7 or how does it handle the references now. Before it was relying on is_ref
to determine whether it should copy on write or simply point to the same zval
container. How does the copy on write mechanism work now?
For example:
$a = 1;
$b = $a;
This would in PHP5 have a single zval
container where both $x
& $y
symbols would be pointing to, it would only create a copy of the container if either $a
or $b
changed the value but since PHP7 from my understanding it will have two two zval
containers from the beginning since the value is a simple scalar type int
. When does it do copy on write
?
I don't know C language, which is why I'm having a hard time understanding whats going on by simply looking at the source code and the information I find online does not line up with the current state of PHP.