首頁  >  文章  >  後端開發  >  php變數之寫時複製機制

php變數之寫時複製機制

不言
不言原創
2018-04-14 13:44:411377瀏覽

這篇文章主要介紹了用php變數寫時複製機制,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

轉載自LYC的部落格

程式設計思想雖然可以共用,不過語言間的差異還是比較明顯的,只是使用者之間沒有意識到而己,而了解其中的差異對於編寫程式以及把握效能還是有好處的。下面我們來介紹下PHP的一個很重要的機制copy on write,我們先以最簡單的變數來介紹這個機制,在說這個之前,筆者先來介紹下弱類型是怎麼實現的。

大家都知道,PHP是由C實現的,但C是強型別語言,PHP怎麼做到弱型別語言。一起來看下,PHP變數在C語言底層的程式碼,

typedef struct _zval_struct zval;
typedef unsigned int zend_uint;
ypedef unsigned char zend_uchar;
struct _zval_struct {
    zvalue_value value;      /*注意这里,这个里面存的才是变量的值*/
    zend_uint refcount__gc;  /*引用计数*/
    zend_uchar type;        /* 变量当前的数据类型 */
    zend_uchar is_ref__gc;   /*变量是否引用*/};typedef union _zvalue_value {    long lval;      /*PHP中整型的值*/
    double dval;    /*PHP的浮点数值*/
    struct {     
        char *val;        int len;
    } str;               /*PHP的字符串*/
    HashTable *ht;     /*数组*/
    zend_object_value obj;  /*对象*/} zvalue_value;

本人加了點註釋,大家可以發現,其實我們在PHP用的變量,低層是一個結構體zval,裡面的zvalue_value結構體其實是個聯合體,這個聯合體才是實際存放著PHP的變數值,下面我們以實際的PHP程式碼範例來表示整個工作過程,注意上面的引用計數。先來看C語言的,首先是非函數部分,函數部分下一章節來講

int i = 4;  //alloca方式在内存中分配空间,这个变量在内存中的栈区
int j = i;   //alloca方式在内存中分配空间,并且将原先内存空间里面的数据复制到新的内存空间中,这个变量在内存的栈区
int j = 5;  //不分配内存空间,对变量j所在的栈区空间的数据进行修改

來看PHP部分的

$i = 4;   //内核创建一个zval指针,并且为其以堆的方式开辟空间,让指针指向这个空间,将zval中的成员引用计数置为1,类型标记为整形,
并且申请一个zvalue_value指针,同样以堆的方式以其开辟空间,同时将该联合体中的lval赋值为4,并且在symbal_table的hash表中记录变量i和zval指针的映射关系
$j = $i;   //没有在申请内存空间,在zval的成员中引用计数标记为
2$j = 5;   //内核重新创建zval指针,重复下上面的步骤,我就不重复说明了,重点是将旧的zval引用计数标记为1

從這個地方發現幾個重要點

  1. 所有的php變數開闢的記憶體空間都是在堆中,無論是臨時變數或全域變量,只是php的臨時變數記錄在active_symbal_table表中,全域變數記錄中symbal_table表中

  2. php幹嘛比C慢。多做了這麼多事,能不慢嗎?

  3. 當php類似

    #i這種變數賦值時,是沒有記憶體開銷的,也就是你賦值個幾萬個,也只是引用計數變成幾萬而己,這個和C語言是不一樣的。而當變數的值改變時,才會進行重新開啟記憶體空間,這個機制我們稱為寫入時複製機制

額外細節部分,當php核心發現,int的數值溢位時,也就是超出整型的範圍時,自動轉換為float,有興趣的讀者可以自己寫個很大的整數,但是不能超出float取值範圍,看看var_dump資料型別是什麼。

最後部分:php物件部分因為預設是引用方式的,所以就是賦值完,再改變物件的成員變量,也不會啟用寫時複製的,如以下

class Test {
     public $var = 999;
}$test1 = new Test();$test2 = $test1;  //只是引用计数加1而己,没有开辟新的内存空间
$test2->var = 1000;echo $test1->var;  //此时的值也为1000
$test3 = clone $test1;  //这个才是正在重新开辟新的内存空间

相關推薦:

PHP變數參考與非引用效能比較

php變數取代的方法實例總結 

#

以上是php變數之寫時複製機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn