In-depth understanding of the PHP kernel (1), in-depth understanding of the php kernel _ PHP Tutorial

Source: Internet
Author: User
Deep understanding of the PHP kernel (1) and deep understanding of the php kernel. In-depth understanding of the PHP kernel (1), in-depth understanding of the php kernel as a simple and powerful language, PHP can provide a lot of language features applicable to the Web. Starting from practice, I deeply understand the principles of weak type variables (I) and PHP kernel

As a simple and powerful language, PHP can provide many language features applicable to the Web. Starting from practice, after exploring the principle of weak type variables, this article will continue to guide you to understand the php kernel in depth.

Recently, when I spoke with a netizen, I raised a very strange question. That is, after a reference is added to an operation, it is found that the performance is 10 thousand times slower. In my mind, referencing is a very error-prone issue, especially the reference in PHP, which has many traps. Because I have studied the source code of this piece of PHP before, so I can clearly parse what the reference is like. I hope I can thoroughly understand this problem after reading this article. If you have any questions or questions, please leave a message.

Let's take a look at a piece of code:

class RefferTest{ private $data; private $testKey; function __construct() {  $key = "hello";  $this->data[$key] = range(0, 10000);  $this->testKey = $key; } function reffer($key) {  $reffer = &$this->data[$key];  return count($reffer); } function noreffer($key) {  return count($this->data[$key]); } function test() {  $t1 = microtime(true);  for ($i = 0; $i < 5000; $i++)  {   $this->reffer($this->testKey);  }  $t2 = microtime(true) - $t1;  var_dump("reffer: " . round($t2, 4));  $t1 = microtime(true);  for ($i = 0; $i < 5000; $i++)  {   $this->noreffer($this->testKey);  }  $t2 = microtime(true) - $t1;  var_dump("noreffer: " . round($t2, 4)); }}$test = new RefferTest();$test->test();

If you finish this code, you can say that for reffer and noreffer to have 10 thousand times worse performance, there is no need to look down the following. This blog is intended for beginners of PHP. You can run this code to try it. it is indeed 10 thousand times worse. Of course, the code of the problem that the netizen encountered is more complex than above. the code above is simplified to illustrate the problem. Maybe you have seen the problem from the code, but why. I think it is necessary to analyze it. In this way, PHP will not make the same mistake in the future.

To reduce replication, PHP adopts a copy on writer mechanism. I think this is a very common mechanism, and you must have heard of it. For example, the implementation of stl string in gcc adopts this mechanism. string assignment is not a real copy, and will be copied only when it is modified. Let's take the simplest example:

 $a = str_repeat("", );  $b = $a;  $a[] = "";

$ A is a very large string. if $ B = $ a is copied, it will consume a lot of memory and cpu. this is not cost-effective. in case, the following code does not modify $ a and $ B. copying is unnecessary. Of course, $ a is modified later. at this time, it must be copied. Otherwise, it is not logical. But now the question is, how do you know that $ a must have such a mark to copy the changes. The reference count is used. The reference count is also used for memory management.

The basic process is as follows:

1: Create a variable that can save 10000 strings of 0.

2: Create a variable symbol a, which references this variable. Note that the variable symbols and variables are not the same thing, and they are separated.

From the perspective of C language, PHP will probably accomplish the following:

  char *varname = "a";  size_t varname_len = strlen(varname);  zend_hash_add(EG(active_symbol_table), varname, varname_len + , &var, sizeof(zval*), NULL);

Active_symbol_table is a PHP symbol table in which all accessible variables are stored. it is a hash table. The var variable saves 10000 0 strings. It is the structure of zval. The Structure of zval is as follows:

typedef struct _zval_struct { zvalue_value value; zend_uint refcount; zend_uchar type; zend_uchar is_ref;} zval;typedef union _zvalue_value { long lval; double dval; struct {  char *val;  int len; } str; HashTable *ht; zend_object_value obj;} zvalue_value;

Zvalue_value is a union that can save long, double, string, hash table (PHP Array), and object. That is, all PHP types. Zval is actually three functions for zvalue_value: type, is_ref, and refcount. This is a common variable in PHP. If you use PHP to compare large objects, you will find that the memory usage is very high. It is because a variable is not the variable of the traditional C language, and it adds a lot of things.

Okay. The first sentence is complete. The second sentence is as follows. The second sentence is very simple. it will generate a new variable symbol B, and add it to active_symbol_table, but it will not add a new variable, but only refcount ++. The assignment is complete.

First of all, we should note that a and B are just a symbol. they are a key in the active_symbol_table table and all have a pointer pointing to a zval. therefore, a and B are completely consistent in the C language. Let's get the first law of PHP variables:

The first law of PHP variables: if two variables point to the same zval, there is no difference between the two variables. That is to say, any operation on a is symmetric to B. The symmetry here is understood in this way. It is you in the mirror, not equivalent. For example, if a is assigned a value, a will generate a copy. Similarly, if B is assigned a value, the same operation is performed, that is, B generates a copy. That is to say, the behavior of a and B is the same.

Third, when writer occurs, PHP will judge whether refcount is greater than 2. if it is greater than 2, copy zval and then copy the original zval refcount --. This is all about copy on writer. you must think that you are very familiar with all of this.

However, PHP is not just as simple as copy on writer, but also has a reference problem. Introduce the concept of reference, so that the problem becomes more complicated. Because, referencing this mark means that you do not need to copy it during writer. In this way, the original variable will be modified. From the philosophy we used to learn in school, this is a contradiction. They are opposite and unified, and each has its own use. The so-called existence is reasonable.

Well, let's take a look at this contradiction. we only consider the combination of the two. Multiple combinations are similar. If the two combinations are used, the value is first, and the value is referenced later.

Or the reference is before, and the value is after. We will discuss them separately. let's first look at the situation where the assignment is prior and the reference is later.

  $a = ;   $b = $a;   $c = &$a;

$ B = $ a, which is a value assignment for the copy on writer behavior. While $ c and $ a are reference assignment values. We assume that we can use a zval representation in the above case, that is, we do not need to copy the data. The situation is as follows:

According to our first law of PHP variables, that is to say, the operations of a, B, and c are symmetric, but obviously, copying operations of B is required, operation a will not be copied, and the operation behavior is different, which is in conflict with the first law. That is to say, to ensure that the above operations are not in conflict, they must be separated. The principle of separation is who creates conflicts and who replicates. Obviously, the third sentence is $ c = & $. Therefore, the internal variable replication process is as follows:

In the above case, the assignment is prior, and the reference is later. Another case is that the reference is assigned after:

 $a = ;   $b = &$a;   $c = $a;

According to the first law of PHP variables, a, B, and c must be separated to ensure that the law is correct. We can find that B and a are obviously a group of people. that is to say, the operations of B and a are symmetric. they can point to the same zval, while c's behavior is different from that of a and B, to change c, you need to copy it. Here, I think, if you understand, why is the difference between the two count codes posted at the beginning so big. When I discussed it with that netizen, it finally said that, in this case, PHP is not well designed. I can do it. $ c will not copy it first, and c will be written, then copy. It seems that it is still difficult to understand one thing. think about the first law of PHP. You can assume that c points to the same zval without separation. Therefore, c and a and B have the same behavior, which is is_ref = 1. Therefore, c will not perform replication. The last internal execution can be expressed as follows:

I used to confuse this reference. now, you can use the first law to analyze all the situations. I will write some articles about PHP kernel analysis later. if you want to learn more about some aspects of PHP, leave a message for me.

It is also a hidden error.

function count_bigarray(){ global $bigarray; return count($bigarray);}

No reference is displayed, but a reference is hidden. PHP automatically creates a code that references the global variable $ bigarray. if you use count here, the efficiency will be very slow. It is recommended that you reference it directly through the $ GLOBAL array.

The following article will introduce you to the SAPI exploration of php kernel 2. I hope you will continue to pay attention to it.

Kernel (1), a deep understanding of php kernel as a simple and powerful language, PHP can provide many language features applicable to the Web. Starting from practice, follow the weak type variable principle...

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.