Home >Backend Development >PHP Problem >What does reference counting in PHP mean?

What does reference counting in PHP mean?

醉折花枝作酒筹
醉折花枝作酒筹forward
2021-05-08 17:31:401811browse

This article will introduce you to PHP's reference counting. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.

What does reference counting in PHP mean?

What is reference counting

In PHP’s data structure, reference counting refers to each variable, in addition to saving their type and value , and also saves two additional contents, one is whether the variable is currently referenced, and the other is the number of references. Why do we need to save two more contents? For garbage collection (GC) of course.

In other words, when the number of references is 0, this variable is no longer used and can be recycled through GC to release the occupied memory resources.

No program can occupy memory resources indefinitely. Excessive memory usage often leads to a serious problem, that is, memory leaks. GC is the bottom layer of PHP that automatically completes the memory processing for us. Destroy, instead of having to free manually like C.

How to check the reference count?

We need to install the xdebug extension, and then use the xdebug_debug_zval() function to see the detailed information of the specified memory, such as:

$a = "I am a String";
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=0)='I am a String'

As can be seen from the above, this $a variable The content is a string like I am a String. The refcount in parentheses is the number of references, and is_ref indicates whether the variable is referenced. Let's see how these two parameters change through variable assignment.

$b = $a;
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=0)='I am a String'

$b = &$a;
xdebug_debug_zval('a');
// a: (refcount=2, is_ref=1)='I am a String'

When we perform a normal assignment, there is no change in refcount and is_ref, but when we perform a reference assignment, we can see that refcount becomes 2 and is_ref becomes 1. This means that the current \$a variable is assigned by reference, and its memory symbol table serves the two variables $a and $b.

$c = &$a;
xdebug_debug_zval('a');
// a: (refcount=3, is_ref=1)='I am a String'

unset($c, $b);
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=1)='I am a String'

$b = &$a;
$c = &$a;
$b = "I am a String new";
xdebug_debug_zval('a');
// a: (refcount=3, is_ref=1)='I am a String new'

unset($a);
xdebug_debug_zval('a');
// a: no such symbol

Continue to add a reference assignment to $c, and you can see that refcount will continue to increase. Then after unsetting $b and $c, refcount returns to 1. However, it should be noted that is_ref is still 1. That is to say, if this variable has been referenced, the is_ref will become 1, even if the referenced variable Even if it has been unset, the value remains unchanged.

Finally we unset $a, and the display is no such symbol. The current variable has been destroyed and is no longer a usable symbolic reference. (Note that variables in PHP correspond to the symbol table of memory, not the real memory address)

Object reference counting

is the same as ordinary type variables, and object variables are also used in the same way. counting rules.

// 对象引用计数
class A{

}
$objA = new A();
xdebug_debug_zval('objA');
// objA: (refcount=1, is_ref=0)=class A {  }

$objB = $objA;
xdebug_debug_zval('objA');
// objA: (refcount=2, is_ref=0)=class A {  }

$objC = $objA;
xdebug_debug_zval('objA');
// objA: (refcount=3, is_ref=0)=class A {  }

unset($objB);
class C{

}
$objC = new C;
xdebug_debug_zval('objA');
// objA: (refcount=1, is_ref=0)=class A {  }

However, it should be noted here that the symbol table of the object is an established connection. In other words, re-instantiating or modifying $objC to NULL will not affect the content of $objA. In this regard Knowledge: Is our previous object assignment a reference in PHP? It has been explained in the article. Ordinary assignment operations on objects are also symbol table assignments of reference types, so we do not need to add the & symbol.

Reference counting of arrays

// 数组引用计数
$arrA = [
    'a'=>1,
    'b'=>2,
];
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=0)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2
// )

$arrB = $arrA;
$arrC = $arrA;
xdebug_debug_zval('arrA');
// arrA: (refcount=4, is_ref=0)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2
// )

unset($arrB);
$arrC = ['c'=>3];
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=0)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2
// )

// 添加一个已经存在的元素
$arrA['c'] = &$arrA['a'];
xdebug_debug_zval('arrA');
// arrA: (refcount=1, is_ref=0)=array (
//     'a' => (refcount=2, is_ref=1)=1, 
//     'b' => (refcount=0, is_ref=0)=2, 
//     'c' => (refcount=2, is_ref=1)=1
// )

When debugging arrays, we will find two interesting things.

First, each element inside the array has its own separate reference count. This is also easier to understand. Each array element can be regarded as a separate variable, but the array is a hash set of these variables. If there are member variables in the object, the same effect will occur. When an element in the array is assigned to another variable by &, the refcount of this element will be increased without affecting the refcount of the entire array.

The second is that the default refcount of the array is 2. In fact, this is a new feature after PHP7. When the array is defined and initialized, the array will be converted into an immutable array (immutable array). In order to distinguish it from ordinary arrays, the refcount of this array starts from 2. When we modify any element in this array, the array will change back to a normal array, that is, refcount will change back to 1. You can try this yourself. As for why this is done, the official explanation is for efficiency. The specific principle may still need to be dug into the source code of PHP7 to know.

Things to note about memory leaks

In fact, PHP has already helped us with the GC mechanism at the bottom layer, so we don’t need to worry too much about the destruction and release of variables. However, we must pay attention to this. Elements in an object or array can be assigned to themselves. That is to say, assigning a reference to itself to an element becomes a circular reference. Then this object is basically unlikely to be automatically destroyed by GC.

// 对象循环引用
class D{
    public $d;
}
$d = new D;
$d->d = $d;
xdebug_debug_zval('d');
// d: (refcount=2, is_ref=0)=class D { 
//     public $d = (refcount=2, is_ref=0)=... 
// }

// 数组循环引用
$arrA['arrA'] = &$arrA;
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=1)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2, 
//     'arrA' => (refcount=2, is_ref=1)=...
// )

Whether it is an object or an array, if an ellipsis like... appears during printing and debugging, then there will be a circular reference in your program. In the previous article about object copying in PHP, we also talked about this circular reference problem, so this issue should be something we should always pay attention to in daily development.

Recommended learning: php video tutorial

The above is the detailed content of What does reference counting in PHP mean?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete