2014年1月20日 星期一

Zend VM: zend object, persistent zval 以及 persistent hash table

趁現在還有印象,筆記一下關於 Zend VM 內部的 persistency mechanism:

1. ALLOC_INIT_ZVAL 基本上就是 ALLOC_ZVAL 加上 INIT_ZVAL

2. MAKE_STD_ZVALALLOC_ZVAL 加上 INIT_PZVAL

3. INIT_PZVALINIT_ZVAL 的差異是 PZVAL 會將 refcount__gc 設置為 1 而 INIT_ZVAL 基本上只是將所有的欄位設置為 0。 所以 ALLOC_INIT_ZVAL 出來的 zval 如果沒有處理好,會被 gc 清掉。

4. zend object 不支援 persistent,其中一部分原因在於 object 基本上分為 zend_object 以及 zend_object_value, zend_object 是 persistent,但 zend_object_value 不是,且 object 本身的 properties 跟 handlers 都是使用 emalloc 申請來的,這些記憶體會在 request 結束的時候一起 free 掉。

5. HashTable 結構可以 allocate 成 persistent memory,其中幾例是 EG(persistent_list)EG(symbol_table). 基本上需先使用 pemalloc allocate persistent memory 再使用 zend_hash_init 初始化 HashTable 結構變數,其中最後一項參數 persistent 必須為 1,則 allocate bucket 時,bucket 本身的記憶體才會是 persistent。

6. zend_hash_copy 基本上是直接對 buckets 做拷貝的動作,所以 zval* 實際上還是同一個,只是在 copy_ctor_func 你可以透過 Z_ADDREF_P 來增加 reference counting。

7. 要對 HashTable 完全拷貝,只能另外自己寫 recursive copy function,對於 value 內的 zval* 得另外 allocate zval* 出來,這樣在 persistent_list 內才不會被 request 結束時的 clean up handler 清除掉。

8. 也就是說 object 沒有辦法 persistent 保留在程序中,在 APC 的作法,則是針對 object 去做 serialize。 沒錯就是那個 serialize 函數。

9. zval 基本上都是 copy on write,如果在 extension 內要明確的複製 zval 結構到新的記憶體空間,則必須使用 SEPARATE_ZVAL

10. 只要是 emalloc 來的記憶體,不管 refcount 是否大於 0,"幾乎" 都會在 RSHUTDOWN 時被清除掉。