对PHP内核的深入理解(1)

PHP作为一种简单而强大的语言,可以提供许多适用于Web的语言特性,从实践出发,遵循弱类型变量的原则,本文继续引导您理解PHP内核。

最近,我与网友交流的一个非常奇怪的问题,在一个操作中,添加一个引用后,发现性能慢一万倍。在我的心目中,引用是一个非常容易出错的问题,特别是在PHP中的参考,有很多陷阱。因为我有了这个PHP源代码之前,所以我可以清楚地解释它是什么,希望看完这篇文章后,我完全可以理解这个问题。如果你有任何问题,或者有一些你想知道的问题,你可以留言给我。

先看一段代码:


类reffertest
{
私人数据;
私人$测试结构;
__construct()函数
{
$ =hello;
$ < >数据{ $ } =范围(0, 10000);
美元->测试结构=美元关键;
}
功能推荐($键)
{
$推荐=美元->数据{ $关键};
返回计数($推荐);
}
功能noreffer($键)
{
返回计数($);
}
功能测试()
{
$ T1 =瞬时(真);
($ i = 0;$ i < 5000;$ + +)
{
美元->推荐(美元->测试结构);
}
$ T2 =瞬时(真)至T1;
Var_dump (reffer:. 圆($ T2,4);
$ T1 =瞬时(真);
($ i = 0;$ i < 5000;$ + +)
{
这noreffer(美元->美元->测试结构);
}
$ T2 =瞬时(真)至T1;
var_dump(noreffer:。圆($ T2,4);
}
}
为测试=新reffertest();
$测试>测试();


如果你完成的代码,你可以说它将为推荐和noreffer是差了一万倍,然后就不需要往下看。这个博客是针对PHP新手,你可以运行这个代码,试试吧,真的要坏一万倍。当然,网友符合代码比上面的更复杂的,和上面的代码是我简化为了解释这个问题,也许你已经看到的代码,这个问题但是,至于为什么,我想对它进行分析是很有必要的。这样,同样的错误不会在将来时使用了PHP。

为了减少复制,PHP使用作家机制的副本。我认为这是一个非常普遍的机制,你一定听说过它。例如,GCC字符串的实现是采用了这样的一个机制,字符串赋值是不真实的复制,它将修改的时间复制。让我们用最简单的例子开始:


美元= str_repeat(
美元=美元;
= $;


$ A是一个非常大的字符串。如果$ = $ A,它将花费大量的内存和CPU时,它被复制。这是非常不经济的。如果下面的代码不修改$和$,复制都是不必要的。当然,美元一直在后面修改,此时,它必须被复制,否则是不符合逻辑的。但现在的问题是,你怎么知道当美元是变化的,你要复制它,你必须有这样的一个标志,方法是使用引用计数,引用计数也被用来管理内存。

基本过程就是这样:

1:创建一个变量,可以节省10000的这样一个字符串0。

2:创建一个变量符号A,它指的是变量。注意变量符号和变量不是一回事,二者是分开的。

如果从C语言的角度来看,PHP可能会做这样的事情:


char * varname = ;
size_t varname_len = strlen(varname);
zend_hash_add(如(active_symbol_table),Varname,varname_len +瓦尔河,sizeof(zval *),null);


active_symbol_table是PHP的符号表,以及所有可以访问的变量是在这,他是一个哈希表。var变量,节省10000 0串。这是zval结构,和zval结构如下:


_zval_struct { typedef struct
zvalue_value价值;
zend_uint引用计数;
zend_uchar型;
zend_uchar is_ref;
zval };
_zvalue_value { typedef联盟
长的语句;
双dval;
struct {
字符*;
Int len;
STR };
哈希表* HT;
zend_object_value obj;
zvalue_value };


zvalue_value是一个联盟,可以保存长、双、字符串哈希表(PHP数组),和对象。这是所有PHP类型。其实Zval是zvalue_value,添加类型和引用is_ref,援引三计数引用计数的功能。这是PHP中常见的变量。如果你用PHP做更大的事情,你会发现,记忆是很重的。这是因为他的一个变量是不是传统的C语言的变量,并增加了很多东西。

第一个句子是完整的,下面是第二句。第二句很简单。这将产生一个新的变量符号B,他加入active_symbol_table,但它不会增加新的变量,但只是引用计数+ +。任务完成。如图:


首先,我们应该注意A,B只是一个符号。它是在active_symbol_table表的键。有一个指针指向一个变量,所以A和B是相同的C语言水平。我们得到的PHP变量的第一定律:

的PHP变量的第一法则:如果两个变量指向同一个变量,然后两个变量未。也就是说,在任何的操作是对称的B.这里的对称性也明白了。这是你在镜子里,不一样的。例如,一个是分配的,和一个产生复制。同样,如果B是分配的,同样的操作完成后,即产生一份B,A和B的行为都是相同的。

第三句话是:当作家时,PHP将决定如果引用计数大于2,如果大于2,然后复制机制,然后把原来的变量引用计数,这是整个副本的作家,你一定觉得这些都是你非常熟悉的,你知道的。

然而,PHP是不只是简单的复制的作家,但它也有一个参考问题。参考的概念引入使问题变得有些复杂,因为,在这个标志,它意味着当作家,你不需要复制它。这样,原来的变量被修改。从哲学上说,我们以前在学校经常学习,这是一对矛盾,它们是对立的,它们是统一的,各有其用。所谓的存在是合理的。

让我们看看这个矛盾。我们只考虑这两种组合,各种组合是相似的,这两种组合是在引用前后分配一个值。

或者,在引用之前,赋值是在后面,我们将分别讨论,首先,赋值之前,在后面引用。




=一美元;
美元=美元;
美元=美元;


B =美元美元是复制作家行为的任务。$ C和美元是参考的任务。我们认为,在上述的情况下,我们可以使用一个变量,那就是,你不需要复制,那样的话。


根据PHP变量的第一条定律,也就是说,a、b和c的操作是对称的,但很明显,b是基于复制而不是在操作上操作的。使用不同于第一法。也就是说,有在上述操作没有矛盾,而且必须分离。分离的原则是谁使矛盾和谁重复。这显然是第三句,$c =美元;在矛盾的制造。因此,该内部变量的拷贝过程如下:


上述情况是指在参考之前的任务,另一种情况是引用是在上一次作业之后:


=一美元;
美元=美元;
美元=美元;


根据PHP变量的第一定律,A、B和C必须分开,以确保这条定律是正确的。也就是说,B的操作,一个是对称的,它们可以指向同一个变量,而C的行为不同于A和B的转变需要复制的。看到这里,我想,如果你理解了,你为什么开始,你把两个数的差异,所以你应该明白,当我有了网友,最后说,在这种情况下,PHP设计的不好,我也完全可以不复制,$ C,和C写的,然后复制它。它似乎明白一件事一件很难的事情,想的PHP的第一法则。你可以认为没有分离,C点相同的变量,所以C和A,B的行为是相同的,is_ref = 1,所以C不会复制。最后内部执行可以在后续的表达ING图:


我曾经把这参考之前,现在,你可以用一定的规律来分析所有的situations.php内核分析的文章,我会写一些之后,如果你想了解PHP的一些方面,你可以留言给我。

最后一点是一个隐性错误。


count_bigarray()函数
{
全球bigarray美元;
返回计数($ bigarray);
}


在这里,没有资料显示,但参考是隐藏的here.php会自动创建一个代码引用全局变量bigarray美元,如果你使用计数,效率会很慢。最好是直接引用的全局数组。

下面的文章将给你一个深入了解PHP内核两SAPI的询问,希望您能继续关注它。