PHP write-On-copy introduction (copy on write) _php tutorial

Source: Internet
Author: User
Tags php write
Before we start, we can look at a simple code:

Copy the Code code as follows:
$foo = 1;
$bar = $foo;
echo $foo + $bar;
?>

Execution of this code will print out the number 2. From the memory point of view to analyze this code "may" do this: allocate a piece of memory to the Foo variable, which stores a 1, and then allocate a piece of memory to the bar variable, also save a 1, and finally calculate the result output. In fact, we found that the Foo and bar variables, because of the same value, could use the same piece of memory completely, thus saving a 1 of memory usage and eliminating the computational overhead of allocating memory and managing memory addresses. Yes, many systems that involve memory management implement this same value shared memory policy: copy-on-write

Most of the time, we have inscrutable fears about their concepts because of some terminology, but in fact, their basic principles are often very simple. This section describes the implementation of this strategy when writing in PHP:

There are a lot of scenarios for copy on Write, also abbreviated as cow, for example, in Linux, which optimizes memory usage in process replication, and has similar applications in various programming languages such as STL for C + +, and so on. Cow is a commonly used optimization method that can be categorized as: Resource delay allocation. Resources are used only when resources are really needed, and write-time replication typically reduces resource usage.

Note: In order to save space, the following unified use of cow to represent "copy-on-write";

Defer optimization of memory replication

As mentioned earlier, the cow in PHP can be simply described as: If you assign a value to a variable by assigning it to it, you do not request new memory to hold the value saved by the new variable, but simply use a counter to share the memory. A new space is requested to hold the value content to reduce memory consumption only if the value of one of the references to the variable changes. PHP is cow for memory optimization in many scenarios. For example: multiple assignments of variables, function parameter transfer, and in the function body to modify the arguments and so on.

Let's look at a memory-viewing example to make it easier to see the obvious role of cow in memory usage optimization:

Copy the Code code as follows:
$j = 1;
Var_dump (Memory_get_usage ());

$tipi = Array_fill (0, 100000, ' php-internal ');
Var_dump (Memory_get_usage ());

$tipi _copy = $tipi;
Var_dump (Memory_get_usage ());

foreach ($tipi _copy as $i) {
$j + = count ($i);
}
Var_dump (Memory_get_usage ());

-----Execution Results-----
$ PHP t.php
Int (630904)
Int (10479840)
Int (10479944)
Int (10480040)

The above code typically highlights the role of cow, when the array variable $tipi is assigned to $tipi_copy, the memory usage does not increase by half immediately, and there is no significant change in looping through the $tipi_copy, where $tipi_copy and $ The data for the tipi variable points to the same piece of memory without copying.

That is, even if we do not use a reference, a variable is assigned a value, so long as we do not change the value of the variable, it will not be used for the new memory to hold the data. From this we can easily think of some cow can be very effective to control the memory use of the scene: just use the variable to calculate and rarely modify it, such as the transfer of function parameters, large array of copying and so on, etc. do not need to change the value of the variable.

Copy the value of the separation change

Multiple variables of the same value share the same block of memory does save memory space, but the value of the variable will change, if in the above example, point to the same memory value has changed (or may change), you need to change the value of "separate", the "separate" operation is "copy".

In PHP, the Zend engine, in order to distinguish whether the same zval address is shared by multiple variables, introduces Ref_count and is_ref two variables to identify:

Copy the Code code as follows:
Ref_count and is_ref are defined in the ZVAL structure (see chapter I, first section)
Is_ref identifies whether the user uses & 's mandatory reference;
Ref_count is a reference count that identifies how many variable references to this zval, that is, the auto-reference of cow, which is destroyed when 0;
For more information about these two variables, jump reading: Chapter Sixth: Assignment of variables and implementation of destruction.
Note: This shows that $a = $b; $b with $a =&; There is no difference in the use of memory in PHP (value does not change);

Let's change the example two slightly: what happens if the value of $copy changes? :

Copy CodeThe code is as follows:
$tipi = Array_fill (0, 3, ' php-internal ');
Array_fill is no longer used here to populate, why?
$tipi [0] = ' php-internal ';
$tipi [1] = ' php-internal ';
$tipi [2] = ' php-internal ';
Var_dump (Memory_get_usage ());

$copy = $tipi;
Xdebug_debug_zval (' tipi ', ' Copy ');
Var_dump (Memory_get_usage ());

$copy [0] = ' php-internal ';
Xdebug_debug_zval (' tipi ', ' Copy ');
Var_dump (Memory_get_usage ());

-----Execution Results-----
$ PHP t.php
Int (629384)
Tipi: (refcount=2, is_ref=0) =array (0 = (refcount=1, is_ref=0) = ' php-internal ',
1 = (refcount=1, is_ref=0) = ' php-internal ',
2 = (refcount=1, is_ref=0) = ' php-internal ')
Copy: (refcount=2, is_ref=0) =array (0 = (refcount=1, is_ref=0) = ' php-internal ',
1 = (refcount=1, is_ref=0) = ' php-internal ',
2 = (refcount=1, is_ref=0) = ' php-internal ')
Int (629512)
Tipi: (refcount=1, is_ref=0) =array (0 = (refcount=1, is_ref=0) = ' php-internal ',
1 = (refcount=2, is_ref=0) = ' php-internal ',
2 = (refcount=2, is_ref=0) = ' php-internal ')
Copy: (Refcount=1, is_ref=0) =array (0 = (refcount=1, is_ref=0) = ' php-internal ',
1 = (refcount=2, is_ref=0) = ' php-internal ',
2 = (refcount=2, is_ref=0) = ' php-internal ')
Int (630088)

In this example, we can find the following features:

$copy = $tipi; This basic assignment triggers the cow memory "share" without generating a memory copy;

The granularity of cow is zval structure, the variables in PHP are all based on zval, so the scope of cow is all variables, and for zval structures (such as arrays, objects, etc.), complex objects are decomposed into minimal granularity when they need to replicate memory. This allows a part of a complex object in memory to be modified without having to "separate" all the elements of the object into a copy of the memory;

Copy the Code code as follows:
Array_fill () fills the array with a cow strategy that may affect the demonstration of this example, and interested readers can read: the implementation of Php_function (Array_fill) in the $PHP _src/ext/standard/array.c.

Xdebug_debug_zval () is a function in the xdebug extension that outputs reference information for variables within Zend. If you do not have the Xdebug extension installed, you can also use Debug_zval_dump () instead. Reference: http://www.php.net/manual/zh/function.debug-zval-dump.php

Implementing Write-time replication

After reading the above three examples, I believe you can also understand PHP cow implementation principle: PHP cow based on the reference count Ref_count and is_ref implementation, more than one variable pointer, will ref_count plus 1, minus 1, minus 0 to destroy; One more forced reference &, Is_ref plus 1, minus 1.

Here's a more typical example:

Copy the Code code as follows:
$foo = 1;
Xdebug_debug_zval (' foo ');
$bar = $foo;
Xdebug_debug_zval (' foo ');
$bar = 2;
Xdebug_debug_zval (' foo ');
?>
-----Execution Results-----
Foo: (Refcount=1, is_ref=0) =1
Foo: (refcount=2, is_ref=0) =1
Foo: (Refcount=1, is_ref=0) =1

Following the introduction of the previous variables section, we know that when $foo is assigned, the value of the $foo variable is only pointed to by the $foo variable. When the value of $foo is assigned to $bar, PHP does not copy the memory to $bar, but instead points $foo and $bar to the same address. At the same time, the reference count increases by 1, which is the new 2. Then we change the value of the $bar, and if we need the memory that the $bar variable points directly to, then the value of $foo will change as well. This is not the result we want. The PHP kernel then copies a copy of the memory and updates its value to an assignment: 2 (This operation is also known as a variable-detach operation), while the original $foo variable points to only $foo points, so the reference count is updated to: Refcount=1.

It looks simple, but the actual situation is much more complex because of the presence of the & operator. See the following example:




Figure 6.6 & Operator-induced memory Replication separation >

From this example, we can see that PHP has a problem-prone handling of the & operator: when $beauty =& $pan; , two variables are essentially reference types, resulting in seemingly ordinary variable $pan, which is the same as & $pan behavior in some internal processing, especially when using reference variables in array elements, which can easily cause problems. (see the last example)

PHP Most of the work is to do text processing, and variables are vectors, the use of different types of variables throughout the life cycle of PHP, Variable Cow strategy also embodies the Zend engine on variables and memory processing, in particular, can refer to the source file related content:

Copy the Code code as follows:
Zend/zend_execute.c
========================================
Zend_assign_to_variable_reference ();
Zend_assign_to_variable ();
Zend_assign_to_object ();
Zend_assign_to_variable ();

And the use of the following macro definitions
Zend/zend.h
========================================
#define Z_REFCOUNT (z) z_refcount_p (& (z))
#define Z_SET_REFCOUNT (z, RC) z_set_refcount_p (& (z), RC)
#define Z_ADDREF (z) z_addref_p (& (z))
#define Z_DELREF (z) z_delref_p (& (z))
#define Z_ISREF (z) z_isref_p (& (z))
#define Z_SET_ISREF (z) z_set_isref_p (& (z))
#define Z_UNSET_ISREF (z) z_unset_isref_p (& (z))
#define Z_SET_ISREF_TO (z, ISREF) z_set_isref_to_p (& (z), ISREF)

Finally, be cautious with quoting &

References and reference counts of the variables mentioned previously are not the same thing as references in PHP, similar to pointers in C, and they can all access the same content through different identifiers, but PHP references are simply variable aliases, without the flexibility and limitations of C directives.

PHP has a lot of unexpected behavior, some for historical reasons, can not break compatibility and choose to temporarily do not fix, or some of the use of the scene is relatively small. Only try to avoid these traps in PHP. For example, the following example.

Because the reference operator causes PHP's cow policy optimizations, the use of references also requires a clear understanding of the behavior of the reference before it can be misused, avoiding some of the more difficult-to-understand bugs. If you think you have enough knowledge of the references in PHP, you can try to explain the following example:

Copy the Code code as follows:
$foo [' love '] = 1;
$bar = & $foo [' Love '];
$tipi = $foo;
$tipi [' love '] = ' 2 ';
echo $foo [' love '];

This example will output 2 at the end, and everyone will be amazed at how $TIPI can affect $foo, $bar the reference operation of the variable, and turn the $foo[' love ' pollution into a reference, thus zend no modification of the $tipi[' love ' to produce a copy separation of the memory.

http://www.bkjia.com/PHPjc/769673.html www.bkjia.com true http://www.bkjia.com/PHPjc/769673.html techarticle before we start, we can look at a simple code: copy Code as follows: PHP//Example $foo = 1; $bar = $foo; echo $foo + $bar; Execute this code and print out the numbers ...

  • 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.