如下基於官網測試、整理:php
php的COW(copy-on-write 寫時複製)
參考官方:https://www.php.Xdebug安裝與...
Xdebug安裝與使用
測試環境php7.3下html
//調試可見 xdebug_debug_zval( 'a' ); $a = "new string"; //==> a: (refcount=1, is_ref=0)='new string' (length=10) $c = $b = $a; //==> a: (refcount=1, is_ref=0)string 'new string' (length=10) unset( $b, $c ); //==> a: (refcount=1, is_ref=0)='new string' (length=10) //複合類型 $a = array( 'meaning' => 'life', 'number' => 42 ); $a['self'] = &$a; /** ==> a: (refcount=2, is_ref=0) array (size=2) 'meaning' => (refcount=1, is_ref=0)string 'life' (length=4) 'number' => (refcount=0, is_ref=0)int 42 'self' => (refcount=2, is_ref=1) &array< ) **/ class Test{ public $a = 1; public $b = 'jksj'; function handle(){ echo 'hehe'; } } $test = new Test(); $test2 = new Test(); xdebug_debug_zval('test'); xdebug_debug_zval('test2'); /** test: (refcount=1, is_ref=0) object(Test)[1] public 'a' => (refcount=0, is_ref=0)int 1 public 'b' => (refcount=1, is_ref=0)string 'jksj' (length=4) test2: (refcount=1, is_ref=0) object(Test)[2] public 'a' => (refcount=0, is_ref=0)int 1 public 'b' => (refcount=1, is_ref=0)string 'jksj' (length=4) **/
變量容器在」refcount「變成0時就被銷燬。任何關聯到某個變量容器的變量離開它的做用域(好比:函數執行結束),或者對變量調用了函數 unset()時,」refcount「就會減1
清理變量容器的問題(Cleanup Problems)
-- 儘管再也不有某個做用域中的任何符號指向這個結構(就是變量容器),因爲數組元素「1」仍然指向數組自己,因此這個容器不能被清除 。由於沒有另外的符號指向它,用戶沒有辦法清除這個結構,結果就會致使內存泄漏。
-- 若是你要實現分析算法,或者要作其餘像一個子元素指向它的父元素這樣的事情,這種狀況就會常常發生。固然,一樣的狀況也會發生在對象上,實際上對象更有可能出現這種狀況,由於對象老是隱式的被引用。
-- 若是上面的狀況發生僅僅一兩次倒沒什麼,可是若是出現幾千次,甚至幾十萬次的內存泄漏,這顯然是個大問題。這樣的問題每每發生在長時間運行的腳本中,好比請求基本上不會結束的守護進程(deamons)或者單元測試中的大的套件(sets)中。後者的例子:在給巨大的eZ(一個知名的PHP Library) 組件庫的模板組件作單元測試時,就可能會出現問題。有時測試可能須要耗用2GB的內存,而測試服務器極可能沒有這麼大的內存。
-- 首先,咱們先要創建一些基本規則,若是一個引用計數增長,它將繼續被使用,固然就再也不在垃圾中。若是引用計數減小到零,所在變量容器將被清除(free)。就是說,僅僅在引用計數減小到非零值時,纔會產生垃圾週期(garbage cycle)。
-- 其次,在一個垃圾週期中,經過檢查引用計數是否減1,而且檢查哪些變量容器的引用次數是零,來發現哪部分是垃圾。
-- 當垃圾回收機制打開時,每當根緩存區存滿時,就會執行上面描述的循環查找算法。
當垃圾回收機制關閉時,若是根緩衝區存滿了可能根,更多的可能根顯然不會被記錄。那些沒被記錄的可能根,將不會被這個算法來分析處理。若是他們是循環引用週期的一部分,將永不能被清除進而致使內存泄漏。
php7.3 *zval 須要的內存再也不是單獨從堆上分配,再也不本身存儲引用計數。數字的引用計數refcount爲0,字符串、對象從1開始,數組從2開始,引用計數由其自身來存儲;自身引用型計數屬性與本來相同 展現爲:&array< 。當根緩存區存滿時,會執行gc_collect_cycles()實現自動回收。
官方 After testing, breaking up memory intensive code into a separate function allows the garbage collection to work. 推薦把
內存密集型代碼放到函數中,方便內存及時回收。算法
參考《PHP 手冊 ›語言參考 ›類與對象》數組
class a{ static protected $test="class a"; public function static_test(){ echo self::$test; echo static::$test; } } class b extends a{ static protected $test="class b"; } $obj = new b(); $obj->static_test(); // new a() => a a // Results class a // Results class b
當前類無繼承時,self 和 static 均指向本身。
有繼承時,self指向 預先/事先 靜態化的父類,static完成靜態化的本身。static的方式也被稱爲 延遲靜態綁定 。緩存
class staticparent { static $parent_only; static $both_distinct; function __construct() { static::$parent_only = 'fromparent'; static::$both_distinct = 'fromparent'; } } class staticchild extends staticparent { static $child_only; static $both_distinct; function __construct() { static::$parent_only = 'fromchild'; static::$both_distinct = 'fromchild'; static::$child_only = 'fromchild'; } } $a = new staticparent; echo 'Parent: parent_only=', staticparent::$parent_only, ', both_distinct=', staticparent::$both_distinct, "<br/>\r\n"; $a = new staticchild; echo 'Parent: parent_only=', staticparent::$parent_only, ', both_distinct=', staticparent::$both_distinct, "<br/>\r\n"; echo 'Child: parent_only=', staticchild::$parent_only, ', both_distinct=', staticchild::$both_distinct, ', child_only=', staticchild::$child_only, "<br/>\r\n"; //Parent: parent_only=fromparent, both_distinct=fromparent //Parent: parent_only=fromchild, both_distinct=fromparent //Child: parent_only=fromchild, both_distinct=fromchild, child_only=fromchild
這也是 延遲靜態綁定 運用的一個例子。服務器
參考腳本之家整理的2019最新的 php技巧php7