A deep understanding of PHP principles-Variable Separation/reference (Variables Separation)

Source: Internet
Author: User

In this section, we will continue to introduce the concepts of Variable Separation and reference in PHP:

First, let's review the structure of zval:

 
 
  1. struct _zval_struct {
  2.         /* Variable information */
  3.         zvalue_value value; /* value */
  4.         zend_uint refcount;
  5.         zend_uchar type; /* active type */
  6.         zend_uchar is_ref;
  7. }
    1. ;

We have never introduced the refcount and is_ref fields. We know that PHP is a long-running server-side script interpreter. So for it, efficiency and resource usage are a very important measure, that is, PHP must introduce the memory usage as much as possible, consider the following code:

 
 
  1. <?php
  2.    $var = "laruence";
  3.    $var_dup = $var;
  4.    unset($var);
  5. ?>

The first line of code creates a string variable, applies for a 9-byte memory, and saves the string "laruence" and the end of a null (/0.
The second row defines a new string variable and copies the VaR value to the new variable.
The third row unsets the variable VAR.

Such code is very common in our scripts. If php re-allocates the memory and copies the data for every variable assignment, therefore, the above code is required to apply for 18 bytes of memory space, and we can easily see that the above Code does not need to apply for two copies of space at all, PHP developers also see:

As we have mentioned before, the variables in PHP are implemented by a symbol name stored in symbol_table corresponding to a zval. For example, for the first line of code above, A value "Var" is stored in symbol_table, and a pointer pointing to a zval structure. The variable value "laruence" is stored in this zval, which is hard to imagine, for the above code, we can make the pointers corresponding to "Var" and "var_dup" point to the same zval.

PHP does the same. In this case, we need to introduce the refcount field in the zval structure that we have never introduced before.
Refcount, as its name implies, records the number of referenced zval values.
For example, for the Code:

 
 
  1. <?php
  2.    $var = 1;
  3.    $var_dup = $var;
  4. ?>

The first line creates an integer variable with a value of 1. In this case, the refcount of the zval that stores integer 1 is 1.
In the second row, a new integer variable is created. The variable also points to the created zval and adds the refcount of this zval to 1. At this time, the refcount of this zval is 2.
PHP provides a function to help us understand the debug_zval_dump process:

 
 
  1. <?php
  2.  $var = 1;
  3.  debug_zval_dump($var);
  4.  $var_dup = $var;
  5.  debug_zval_dump($var);
  6. ?>

Output:

 
 
  1. long(1) refcount(2)
  2. long(1) refcount(3

What if you are surprised that VaR's refcount should be 1?
We know that for simple variables, PHP uses parameters in the form of passing values. That is to say, when debug_zval_dump ($ var) is executed, $ var will be passed to debug_zval_dump by passing the value, that is, it will cause var refcount to add 1, so as long as we can see, after a variable is assigned to a variable, the fact that zval's refcount is added to 1 is sufficient.

Now let's look back at the code at the beginning of the article. What will happen after the last unset ($ var) line is executed? Yes, both the refcount minus 1, the code above:

 
 
  1. <?php
  2.    $var = "laruence";
  3.    $var_dup = $var;
  4.    unset($var);
  5.    debug_zval_dump($var_dup);
  6. ?>

Output:

 
 
  1. string(8) "laruence" refcount(2

But what about the following code?

 
 
  1. <?php
  2.    $var = "laruence";
  3.    $var_dup = $var;
  4.    $var = 1;
  5. ?>

Obviously, after this code is executed, the value of $ var_dup should be "laruence". How can this be implemented?
This is the copy on write mechanism of PHP:
Before modifying a variable, PHP will first check the refcount of the variable. If refcount is greater than 1, PHP will execute a separation routine. For the above Code, when the third line is executed, PHP finds that the refcount of zval pointed to by $ VaR is greater than 1, so PHP will copy a new zval and reduce the refcount of the original zval by 1, modify symbol_table to separate $ var from $ var_dup (separation ). This mechanism is called copy on write (copy at write time ).

Code test:

 
 
  1. <?php
  2.    $var = "laruence";
  3.    $var_dup = $var;
  4.    $var = 1;
  5.    debug_zval_dump($var);
  6.    debug_zval_dump($var_dup);
  7. ?>

Output:

 
 
  1. long(1) refcount(2)
  2. string(8) "laruence" refcount(2

Now we know that when using variable replication, PHP does not actually replicate internally, but uses the same structure to save as much overhead as possible. So how can we implement the reference in PHP?

 
 
  1. <?php
  2.    $var = "laruence";
  3.    $var_ref = &$var;
  4.    $var_ref = 1;
  5. ?>

After this code is complete, $ var is indirectly changed to 1. This process is called (change on write: change at write time ). So how does ZE know that Separation is not required for this replication?
In this case, the is_ref field in zval is used:
For the above Code, after the second line is executed, the refcount of zval represented by $ var changes to 2 and is_ref is set to 1 at the same time.
To the third line, PHP first checks the is_ref field of zval represented by var_ref. If it is 1, it is not separated. The general logic is shown as follows:

 
 
  1. If (* val)-> is_ref | (* val)-> refcount <2 ){
  2. // Do not execute Separation
  3. ...; // Process
    1. }

However, the problem arises again. What will happen to the following code?

 
 
  1. <?php
  2.    $var = "laruence";
  3.    $var_dup = $var;
  4.    $var_ref = &$var;
  5. ?>

For the above Code, there is a pair of copy on write variables $ var and $ var_dup, and a pair of change on write mechanism variables for $ var and $ var_ref, how does this happen?

When the second line is executed, $ var_dup and $ var point to the same zval, and refcount is 2.
When the third line is executed, PHP finds that the refcount of zval to be operated is greater than 1, PHP will execute Separation and separate $ var_dup, and associate $ var and $ var_ref with change on write. That is, refcount = 2, is_ref = 1;

Based on this analysis, we can let debug_zval_dump the result with refcount 1:

 
 
  1. <?php
  2.      $var = "laruence";
  3.     $var_dup = &$var;
  4.      debug_zval_dump($var);
  5. ?>

Output:

 
 
  1. string(8) "laruence" refcount(1

For detailed reasons, you only need to make a little analysis, and I will not go beyond the limit .;)

This time we introduced the PHP Variable Separation Mechanism. Next time I will continue to introduce how to receive and transmit parameters in the PHP script in the extension.

  • Address: http://www.laruence.com/2008/09/19/520.html
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.