Deep understanding of PHP kernel (i) _php instance

Source: Internet
Author: User
Tags php source code

PHP, as a simple and powerful language, can provide many web-applicable language features. Starting from the practice, after the weak type variable principle inquiry, this article continues to lead the thorough understanding PHP kernel.

Recently, and a netizen to communicate with, gave me a very strange question. That is, in one operation, after adding a reference, the discovery performance is 10,000 times times slower. In my mind, the reference is a very error-prone problem, especially in PHP, 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 exactly how it is, I hope, read this article, can thoroughly understand this problem. If you have any questions, or some questions you would like to know, you can leave a message for me.

Let's 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]);
  The function test () {$t 1 = microtime (true);
  for ($i = 0; $i < 5000 $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 < 5000 $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 for beginners of PHP. You can run this code and try it, it's 10,000 times times worse. Of course, the user encountered the problem of the code is more complex than above, the above code is I to illustrate the problem, deliberately simplified. You may have seen the problem in the code, but as for why. I think it is necessary to analyze it. In this way, in the future, when you use PHP, you will not make the same mistake.

PHP uses a copy on writer mechanism to reduce replication. I think, this is a very common mechanism, you must have heard. For example, the implementation of GCC's STL string is to adopt such a mechanism that the string assignment is not a true copy, and will be replicated at the time of modification. Let's start with the simplest example:

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

$a is a very large string, if the $b = $a, replication, it will cost a lot of memory and CPU, so it is not cost-effective, in case, the following code does not modify $a and $b that replication is not necessary. Of course, $a has been modified later, this time, must be replicated, otherwise it will not be logical. However, the question now, how to know, $a in the modification, to replicate it, must have such a mark. 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, you can save 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 completes 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 symbolic table of PHP, all the variables that can be accessed are inside this, and he is a hashtable. var, the variable, holds 10,000 0 of this string. And the structure of the zval, the structure of the 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 hold long, double, string, hash table (PHP Array), and objects. Which is the type of all PHP. Zval In fact is the Zvalue_value, added type and reference Is_ref, 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 footprint is very bad. Because, he is a variable is not the traditional C language of the variable, it added a lot of things.

OK, the first sentence is finished, here is the second sentence. The second sentence is very simple, will produce a new variable symbol B, put him into the active_symbol_table, but will not add a new variable, but only, refcount++. The assignment is done. As shown in figure:

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 on the C language level is exactly the same. We get the first law of PHP variables:

The first law of PHP variables: If two variables point to the same zval, then the two variables are undifferentiated. In other words, any action to a is symmetric to B. The symmetry here is so understandable. Is the mirror of you, not the equivalent. For example, a is assigned to a, and a will produce copy. Similarly, if you assign a value to B, you do the same thing, that is, B produces a copy. In other words, A and B behave the same way.

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

However, PHP is more than just copy on writer, and it has a reference problem. Introduce the concept of a reference, so that the problem becomes a little more complicated. Because, by quoting this tag, you don't need to copy the 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 opposites, they are unified and each has its own use. The so-called, the existence is reasonable.

OK, let's take a look at this contradiction, we only consider the case of two kinds of combinations. A variety of combinations are similar. Two combinations of words, that is, the assignment is in the front, the reference in the post.

Or the reference is in front, and the value is assigned to the post. We will discuss separately, first of all: is the assignment of the former, cited in the post.

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

$b = $a, is an assignment of the copy on writer behavior. and $c and $a are reference assignments. We assume that in the case above, we can use a zval representation, that is, no duplication is required, so this is the case:

According to our PHP variable first law, that is to say, the operation of the a,b,c is symmetrical, but it is very obvious that the operation of B to produce replication behavior, and a operation will not produce replication, operating behavior is not the same, and the first law contradictions. In other words, to make the above operation without contradiction, must be separated. The principle of separation is, who creates contradictions, who replicate. Clearly the third sentence, $c = & $a; In creating contradictions. Therefore, the process of copying internal variables is as follows:

The above situation is the value of the assignment before the case. In another case, the reference is previously assigned to the following value:

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

According to the first law of PHP variables, a,b,c must be separated to ensure that the law is correct. It can be found that B and a are obviously a group of people, that is, B and a are symmetric, they can point to the same zval, and C behaves differently from a,b, changing C needs to be replicated. See here, I think, if you understand, why the first, posted the code, that two count difference is so big, you should understand. When I and that netizen discussion, it finally said, that so, PHP design is not good, I completely can, $c first do not replicate, and so C was write, and then replicated. It seems that to understand a thing, or a difficult thing to think about that PHP first law bar. You can assume that without separation, C points to the same zval, so the behavior of C and A,b is the same, Is_ref = 1, so C does not replicate. The final internal execution can be shown in the following figure:

I used to mix this quote, 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.

Last but not least, it is also a recessive mistake.

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

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

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

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.