Introduction to PHP when writing (copy on write) _php tips

Source: Internet
Author: User
Tags memory usage zend

Before we begin, we can look at a simple piece of code:

Copy Code code as follows:

<?php//Case A
$foo = 1;
$bar = $foo;
echo $foo + $bar;
?>

Executing this code will print out the number 2. From the memory point of view to analyze this code "may" is done: allocate a piece of memory to the Foo variable, which stores a 1, and then allocate a piece of memory to bar variables, also save a 1, and finally calculate the result output. In fact, we found that Foo and bar variables, because of the same value, could use the same piece of memory, which saved a 1 of memory usage, and also eliminates the computational overhead of allocating memory and managing memory addresses. Yes, a lot of systems that involve memory management implement this same value shared memory policy: write-time replication

Most of the time, we have inscrutable fear of 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:

Write-time replication (copy on Write, also abbreviated as COW) has a lot of scenarios, such as the optimization of memory usage in process replication in Linux, in various programming languages, such as C + + STL, and so on have similar applications. Cow is a commonly used optimization method, which can be categorized as: Resource delay allocation. When you really need to use resources to consume resources, write-time replication can often reduce resource consumption.

Note: In order to save space, the following will unify the use of cow to denote "write-time duplication";

Delaying optimization of memory replication

As mentioned earlier, the cow in PHP can be simply described as: If you assign a value to a variable without applying for new memory to hold the value of the new variable, but simply by a counter to share the memory, Apply new space only if one of the references points to a change in the value of the variable to save the value content to reduce the memory footprint. In many scenarios, PHP is cow for memory optimization. For example: A variable of multiple assignments, function parameter transfer, and in the function body to modify the actual parameters.

Let's look at an example of memory, which makes it easier to see the obvious role of cow in memory usage optimization:

Copy Code code as follows:

<?php//Case II
$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 use of memory does not immediately increase by half, in the cycle of the enumeration $tipi_copy also did not occur significant changes, where $tipi_copy and $ The data for the tipi variable points together to the same memory, but not replicated.

That is, even if we do not use a reference, a variable is assigned, so long as we do not change the value of the variable, the new application memory is not used to store the data. From this we can easily think of some cow can be very effective to control the memory use of the scene: only the use of variables to calculate and rarely modify the operation, such as the transfer of function parameters, large array of replication, etc. do not need to change the variable value of the case.

Copy the value of a separated 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, the value of the same memory has changed (or may change), you need to "separate" the value of the change, the "separation" of the 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 for identification:

Copy Code code as follows:

Ref_count and is_ref are defined in the ZVAL structure (see chapter I, first section)
Is_ref identification is not a mandatory reference for users to use &;
Ref_count is a reference count that identifies the number of variable references to this zval, that is, cow's automatic reference, which is destroyed when 0;
For more on these two variables, jump read: Chapter Sixth: The assignment of variables and the realization of destruction.
Note: This shows that $a = $b; $b with $a =&; There is no difference in the use of PHP memory (the value does not change);

Here's a little change in example two: What happens if the value of the $copy changes? :

Copy Code code as follows:

<?php//Case Three
$tipi = Array_fill (0, 3, ' php-internal ');
Here no longer uses Array_fill to fill, 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 cow memory "sharing" and does not generate memory replication;

Cow granularity for the zval structure, from PHP variables are all based on zval, so the scope of the cow is all variables, and for the zval structure of the collection (such as groups and objects, etc.), when the need to replicate memory, the complex object decomposed into the smallest granularity to deal with. This allows you to modify a part of an in-memory complex object without having to "detach" all the elements of the object into a single copy of the memory;

Copy Code code as follows:

Array_fill () also uses a cow strategy to populate the array, which may affect the demo of this example, and readers who are interested 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 install Xdebug extensions, you can also use Debug_zval_dump () instead. Reference: http://www.php.net/manual/zh/function.debug-zval-dump.php

Implementing Write-time replication

Read the above three examples, I believe you can also understand the principle of cow in PHP: Php cow based on reference count Ref_count and is_ref implementation, more than one variable pointer, will be Ref_count plus 1, on the other hand minus 1, reduce to 0 on the destruction; One more mandatory quote and IS_REF plus 1, minus 1.

Here's a more typical example:

Copy Code code as follows:

<?php//Case IV
$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

We know that when the $foo is assigned, the value of the $foo variable is directed only by the $foo variable, as described in the previous face variable chapter. When the value of $foo is assigned to $bar, PHP does not copy the memory to the $bar, but it points $foo and $bar to the same address. The reference count is incremented by 1, which is the new 2. Then, we change the value of the $bar, and if you want the memory that the $bar variable points to, then the $foo value will change accordingly. This is not the result we want. As a result, the PHP kernel copies the memory and updates its value to the assigned value: 2 (This operation is also known as the variable detach operation), while the original $foo variable points to the memory only $foo point, so the reference count is updated to: Refcount=1.

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




Figure 6.6 & Operator-generated memory replication separation >

From this example, you can see that PHP is an easy problem handling for & operators: when $beauty =& $pan; , the two variables are essentially reference types, causing the seemingly common variable $pan to behave the same as the & $pan in some internal processing, especially with reference variables in the array elements, which can easily cause problems. (See the final example)

Most of the work of PHP is text processing, and variable is the carrier, the use of different types of variables throughout the life cycle of PHP, Variable cow strategy reflects the Zend engine on the variable and its memory processing, can refer to the source file related content:

Copy 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, please use the reference & carefully

References and references to variables mentioned earlier and references in PHP are not the same thing, references are similar to pointers in C, they can access the same content through different flags, 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 the compatibility of the choice of temporary not repair, or some use of the scene is relatively small. Only try to avoid these pitfalls in PHP. For example, the following example.

Because reference operators can cause PHP's cow strategy to be optimized, using references also requires a clear understanding of the behavior of the reference to avoid misuse and to prevent bugs that are more difficult to understand. If you think you know enough about references in PHP, try to explain the following example:

Copy Code code as follows:

<?php
$foo [' love '] = 1;
$bar = & $foo [' Love '];
$tipi = $foo;
$tipi [' love '] = ' 2 ';
echo $foo [' love '];

This example will eventually output 2, and you will be amazed at how $tipi affects $foo, $bar variable reference operations, $foo[' love '] pollution into a reference, which Zend no memory replication separation from $tipi[' love ' changes.

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.