今天原本想着了解下php的垃圾回收机制,看了下php手册里的描述,大体了解了垃圾回收机制的原理,想着本身写代码去测试下,是否是跟手册里说的是同样的。而后就有了这篇文章。php
按照手册的实例代码敲了下,发现了神奇的问题,结果不同啊!git
$a = "new String"; xdebug_debug_zval( 'a' );
手册告诉咱们的结果是:github
a: (refcount=1, is_ref=0)='new string'
我本身的结果:数组
a: (interned, is_ref=0)='new String'
这个是什么东东?
原来个人PHP
版本是7.1
,可是手册上是5.3
的。那我明白了,PHP7
在垃圾回收机制上作了优化。若是我是大牛,我就去看源码了,惋惜我不是!因此咱只能查资料了,找了大半天,发现不少标题都是PHP7垃圾回收机制的文章,可是里面的内容确仍是PHP5的垃圾回收机制的内容,要么就是直接上源码!这。。。我要是能看懂源码,还须要你去复制一遍吗?
通过坚持不懈的搜索,查找到了这篇文章---PHP7中zval的变化安全
原文:
In PHP 7 a zval can be reference counted or not. There is a flag in the zval structure which determined this.学习
There are some types which are never refcounted. These types are null, bool, int and double.测试
There are other types which are always refcounted. These are objects, resources and references.优化
And then there are types, which are sometimes refcounted. Those are strings and arrays.ui
For strings the not-refcounted variant is called an “interned string”. If you’re using an NTS (not thread-safe) PHP 7 build, which you typically are, all string literals in your code will be interned. These interned strings are deduplicated (i.e. there is only one interned string with a certain content) and are guaranteed to exist for the full duration of the request, so there is no need to use reference counting for them. If you use opcache, these strings will live in shared memory, in which case you can’t use reference counting for them (as our refcounting mechanism is non-atomic). Interned strings have a dummy refcount of 1, which is what you’re seeing here.this
For arrays the not-refcounted variant is called an “immutable array”. If you use opcache, then constant array literals in your code will be converted into immutable arrays. Once again, these live in shared memory and as such must not use refcounting. Immutable arrays have a dummy refcount of 2, as it allows us to optimize certain separation paths.翻译:
在PHP7中,zval结构体中有一个标志来决定zval是否能被引用计数。
像null,bool,int,double这些变量类型永远不会被引用计数(这个地方可能有些不太严谨,鸟哥的博客中写道PHP7中zval的类型共有18种,其中IS_LONG,IS_DOUBLE,IS_NULL,IS_FALSE,IS_TRUE不会使用引用计数)。
像object,resources,references这些变量类型老是会使用引用计数。
然而,像array,strings这些变量类型有时会使用引用计数,有时则不会。
不使用引用计数的字符串类型被叫作“interned string(保留字符串)”。若是你使用一个NTS(非线程安全)的PHP7来构建,一般状况下,代码中的全部字符串文字都将是限定的。这些保留字符串都是不可重复的(即,只会存在一个含有特定内容的保留字符串)。它会一直存在直到请求结束时才销毁,因此也就无需进行引用计数。若是使用了 opcache 的话,保留字符会被存储在共享内存中,在这种状况下,没法使用引用计数(由于咱们引用计数的机制是非原子的)。保留字符串的伪引用计数为1。
对于数组来讲,无引用计数的变量称为“不可变数组”。若是使用opcache,则代码中的常量数组文字将转换为不可变数组。一样的,他们存在于共享内存中,所以不得使用引用计数。不可变数组的伪引用数为2,由于它容许咱们优化某些分离路径。
PHP7的垃圾回收机制已经作过了优化。当有人问咱们PHP垃圾回收机制的时候,咱们不能再按手册上解释的那样去回答,而是要分版本去解释,固然,这篇只是简单的解释了PHP7中zval的变化,暂时没有办法去深刻的解释PHP7的垃圾回收机制。主要缘由仍是咱的技术水平还有待提升,源码解释那部分看的云里雾里的,还须要更多时间去学习,之后会看懂了再来填这个坑吧。这篇文章主要先作个mark。固然也但愿有能力的大佬看到的话,能够指教一下我