Deep understanding of PHP kernel (i), in-depth understanding of PHP kernel _php tutorial

Source: Internet
Author: User
Tags php source code

Deep understanding of the PHP kernel (i), in-depth understanding of the PHP kernel


As a simple and powerful language, PHP provides many of the language features that are available to the Web. From the practice, after the weak type variable principle research, this article continues to lead everybody to understand the PHP kernel deeply.

Recently, when I was talking to a netizen, I raised a very strange question. That is, after adding a reference to an operation, you find that performance is 10,000 times times slower. In my mind, the reference is a very error-prone problem, especially PHP inside the reference, there are a lot of traps. Because, previously specialized in this piece of PHP source code, so, I can be more clear to parse the reference in the end is what it is, hope, read my article, can thoroughly understand the problem. If you have any questions, or have some questions you would like to know, you can leave a message for me.

Take a look at the code first:

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 () {  $t 1 = microtime (true);  for ($i = 0; $i <, $i + +)  {   $this->reffer ($this->testkey);  }  $t 2 = Microtime (True)-$t 1;  Var_dump ("Reffer:". Round ($t 2, 4));  $t 1 = microtime (true);  for ($i = 0; $i <, $i + +)  {   $this->noreffer ($this->testkey);  }  $t 2 = Microtime (True)-$t 1;  Var_dump ("Noreffer:". Round ($t 2, 4)); }} $test = new Reffertest (); $test->test ();

If you finish this code, can say, in order to Reffer and Noreffer will be 10,000 times times worse performance, then there is no need to look down. This blog is aimed at the novice of PHP. You can run this code to try it, and it's really 10,000 times times worse. Of course, the user encountered the problem of the code is more complex than the above, the above code is I to illustrate the problem, deliberately simplified. Maybe you've seen the problem in the code, but as for why. I think it is necessary to analyze it. This way, in the future, when using PHP, you will not make the same mistake.

In order to reduce replication, PHP uses 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 the STL string for GCC is the mechanism by which the string assignment is not a real copy, and it is copied when it is modified. Let's start with a simple example:

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

$a is a very large string, if $b = $a, to replicate, it consumes a lot of memory and CPU, it is very not cost-effective, in case the following code does not modify $ A and $b that replication is not necessary at all. Of course, $a has been modified in the back, this time, it must be copied, otherwise it is not logical. However, the question now, how to know, $a at the time of modification, to copy it, must have such a token. The method is to use reference counting. The reference count is also used for memory management.

The basic process is this:

1: Create a variable that can hold 10,000 0 of such a string.

2: Create a variable symbol A, which refers to this variable. Note that variable symbols and variables are not the same thing, and the two are separate.

If from the C language point of view, PHP probably complete such a thing:

  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 symbol table for PHP, all the variables that can be accessed are in this, and he is a hash table. var is a variable that holds 10,000 0 of this string. and 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 un Ion _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 hold a long, double, string, hash table (PHP Array), and there is an object. That is, all of the PHP types. Zval is actually the zvalue_value, which adds the type and reference Is_ref, the reference count RefCount three functions. This is the normal variable in PHP. If you use PHP to do larger things, you will find that memory consumption is very serious. It's because he's a variable that's not the traditional C-language variable, it adds a lot of stuff.

Well, the first sentence is complete, and here is the second sentence. The second sentence is very simple, will produce a new variable symbol B, add him to active_symbol_table, but will not add a new variable, but just, refcount++. The assignment is complete.

First of all we should note that a, B is just a symbol, he is a key in the Active_symbol_table table, there is a pointer to a zval, so, A and B in the C language level is exactly the same. We get the first law of the PHP variable:

PHP variable The First law: If two variables point to the same zval, then the two variables are no different. In other words, any action on a is symmetrical relative to B. The symmetry here is understood in this way. Is you in the mirror, not the same. For example, a is assigned a value and a copy is generated. Similarly, if you assign a value to B, you do the same thing, that is, B produces a copy. In other words, the behavior of A and B is the same.

The third sentence, when writer occurs, PHP will determine whether RefCount is greater than 2, if more than 2, then copy the Zval, and then, the original Zval refcount--。 This is all copy on writer, you must think that all of this you are very familiar with, you know.

However, PHP is not simply a copy on writer, it has a reference problem. Introduce the concept of references, so that the problem becomes somewhat more complicated. Because, referring to this tag means that you do not need to copy when you are writer. In this way, the original variable is modified. This is a paradox from the philosophy that we used to learn in school. They are opposites, and they are unified, each with its own uses. The so-called, existence is reasonable.

OK, let's take a look at this contradiction, we only consider two combinations of situations. A variety of combinations are similar. In both combinations, it is the assignment before the reference.

Or the reference is before, the assignment is in the back. We will discuss it separately, first of all: is the assignment in front, quoted in the latter case.

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

$b = $a, which is the assignment of the copy on writer behavior. The $c and $a are reference assignments. We assume that in the case above, we can say with a zval, that is, there is no need to replicate, so here's the case:

According to the first law of our PHP variables, that is to say, the operation of A,b,c is symmetric, but it is very obvious that the operation of B should produce copy behavior, while the operation of a does not produce duplication, the operation behaves differently, and the first law contradicts. In other words, to make the above operation is not contradictory, must be separated. The principle of separation is that who creates contradictions and who replicates. Clearly the third sentence, $c = & $a; In creating contradictions. Therefore, the replication process for internal variables is as follows:

The above condition is assigned before, and referenced in the latter case. Another case is that the reference is previously assigned in the following:

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

According to the first law of PHP variables, a,b,c must be separated in order to guarantee the correctness of the law. It can be found that B and a are obviously a bunch of people, that is, the operations of B and a are symmetrical, they can point to the same zval, and the behavior of C is not the same as a, change C needs to be copied. See here, I think, if you understand, why just start, posted out of the code, the two count difference so big, you should understand. When I discussed with that netizen, it finally said, that way, PHP design is not good, I can, $c first do not copy, and so on C was write, and then copy. It seems that to understand a thing, or a difficult thing, think about the first law of PHP. You can assume that no separation is done, C points to the same zval, so C and a, B behave the same, and are is_ref = 1, so C does not replicate. The last kind of internal execution can be expressed as:

I used to confuse the reference, and now you can use that first law to analyze all the situations. PHP Kernel Analysis of the article, I will write some later, if you want to understand some aspects of PHP, you can give me a message.

Finally, it is also an implicit mistake.

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

Here, there are no references displayed, but a reference is hidden here. PHP automatically creates a code that references a global variable $bigarray, which is very slow if you use count here. It is best to refer directly to the $global array.

The following article will give you an in-depth understanding of PHP kernel Two SAPI inquiry, I hope you continue to pay attention to OH.

http://www.bkjia.com/PHPjc/1069346.html www.bkjia.com true http://www.bkjia.com/PHPjc/1069346.html techarticle in-depth understanding of the PHP kernel (a), in-depth understanding of PHP core PHP as a simple and powerful language, can provide a lot of web-appropriate language features. Based on the practice, the principle of the weak type variable is ...

  • Related Article

    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.