php7垃圾回收機制淺析

今天原本想着瞭解下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。固然也但願有能力的大佬看到的話,能夠指教一下我

參考資料

PHP7中zval的變化

相關文章
相關標籤/搜索