(全棧須知)1.php理論點一

一、php垃圾回收與內存泄漏

如下基於官網測試、整理: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)
**/

a.引用次數

變量容器在」refcount「變成0時就被銷燬。任何關聯到某個變量容器的變量離開它的做用域(好比:函數執行結束),或者對變量調用了函數 unset()時,」refcount「就會減1

b.內存泄漏

清理變量容器的問題(Cleanup Problems)
-- 儘管再也不有某個做用域中的任何符號指向這個結構(就是變量容器),因爲數組元素「1」仍然指向數組自己,因此這個容器不能被清除 。由於沒有另外的符號指向它,用戶沒有辦法清除這個結構,結果就會致使內存泄漏。
-- 若是你要實現分析算法,或者要作其餘像一個子元素指向它的父元素這樣的事情,這種狀況就會常常發生。固然,一樣的狀況也會發生在對象上,實際上對象更有可能出現這種狀況,由於對象老是隱式的被引用。
-- 若是上面的狀況發生僅僅一兩次倒沒什麼,可是若是出現幾千次,甚至幾十萬次的內存泄漏,這顯然是個大問題。這樣的問題每每發生在長時間運行的腳本中,好比請求基本上不會結束的守護進程(deamons)或者單元測試中的大的套件(sets)中。後者的例子:在給巨大的eZ(一個知名的PHP Library) 組件庫的模板組件作單元測試時,就可能會出現問題。有時測試可能須要耗用2GB的內存,而測試服務器極可能沒有這麼大的內存。

c.回收週期

-- 首先,咱們先要創建一些基本規則,若是一個引用計數增長,它將繼續被使用,固然就再也不在垃圾中。若是引用計數減小到零,所在變量容器將被清除(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. 推薦把
內存密集型代碼放到函數中,方便內存及時回收。算法

二、面向對象之 this、self 和 static

參考《PHP 手冊 ›語言參考 ›類與對象數組

a.self 和 static

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的方式也被稱爲 延遲靜態綁定緩存

b.重載時的狀況

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

相關文章
相關標籤/搜索