国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > PHP > 正文

淺談PHP源碼三十四:PHP5.3新增加的垃圾回收機(jī)制

2020-03-22 19:29:55
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
這篇文章主要介紹了關(guān)于淺談PHP源碼三十四:PHP5.3新增加的垃圾回收機(jī)制(Garbage Collection),有著一定的參考價(jià)值,現(xiàn)在分享給大家,有需要的朋友可以參考一下

淺談PHP源碼三十四:PHP5.3新增加的垃圾回收機(jī)制(Garbage Collection)
在之前的文章淺談PHP源碼三十三:PHP5.3新增加的垃圾回收機(jī)制(Garbage Collection)基礎(chǔ) 中有介紹了垃圾回收機(jī)制的一些基礎(chǔ)知識(shí)。今天我們看看其初始化,添加到垃圾緩沖區(qū)和垃圾回收的過(guò)程。
官方說(shuō)明文檔請(qǐng)猛擊Garbage Collection
中文版地址:http://docs.php.net/manual/zh/features.gc.php
【初始化】
在zend/zend_gc.c 121行有函數(shù)gc_init實(shí)現(xiàn)了gc的初始化,其代碼如下:

 ZEND_API void gc_init(TSRMLS_D){if (GC_G(buf) == NULL GC_G(gc_enabled)) {GC_G(buf) = (gc_root_buffer*) malloc(sizeof(gc_root_buffer) * GC_ROOT_BUFFER_MAX_ENTRIES);GC_G(last_unused) = GC_G(buf)[GC_ROOT_BUFFER_MAX_ENTRIES];gc_reset(TSRMLS_C);}}

第123行判斷是否為空和是否開啟了gc,如果都為真,則轉(zhuǎn)124行
第124行是直接調(diào)用malloc分配了10000個(gè)gc_root_buffer內(nèi)存。
第125行將html' target='_blank'>全局變量last_unused設(shè)置為gc緩沖區(qū)的結(jié)束位置。
第126行重置整個(gè)垃圾收集機(jī)制,其代碼從zend/zend_gc.c 88行開始,如下:

ZEND_API void gc_reset(TSRMLS_D){GC_G(gc_runs) = 0;GC_G(collected) = 0; #if GC_BENCHGC_G(root_buf_length) = 0;GC_G(root_buf_peak) = 0;GC_G(zval_possible_root) = 0;GC_G(zobj_possible_root) = 0;GC_G(zval_buffered) = 0;GC_G(zobj_buffered) = 0;GC_G(zval_remove_from_buffer) = 0;GC_G(zobj_remove_from_buffer) = 0;GC_G(zval_marked_grey) = 0;GC_G(zobj_marked_grey) = 0;#endif GC_G(roots).next = GC_G(roots);GC_G(roots).prev = GC_G(roots); if (GC_G(buf)) {GC_G(unused) = NULL;GC_G(first_unused) = GC_G(buf); GC_G(zval_to_free) = NULL;} else {GC_G(unused) = NULL;GC_G(first_unused) = NULL;GC_G(last_unused) = NULL;}}

第90~91行 設(shè)置gc運(yùn)行的次數(shù)統(tǒng)計(jì)(gc_runs)和gc中垃圾的個(gè)數(shù)(collected)為0。
第106~107行 設(shè)置雙向鏈表頭結(jié)點(diǎn)的上一個(gè)結(jié)點(diǎn)和下一個(gè)結(jié)點(diǎn)指向自己。

關(guān)于gc_enabled,默認(rèn)情況下是開啟的,可以在php.ini中配置。
其實(shí)現(xiàn)代碼在zend/zend.c 93行 如下:

STD_ZEND_INI_BOOLEAN( zend.enable_gc , 1 ,ZEND_INI_ALL,OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals)

初始化調(diào)用在zend/zend.c 79 行

 static ZEND_INI_MH(OnUpdateGCEnabled) /* {{{ */{OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); if (GC_G(gc_enabled)) {gc_init(TSRMLS_C);} return SUCCESS;}

【添加到垃圾緩沖區(qū)】
跟蹤PHP的源碼 zend/zend_execute_API.c 424行
[_zval_ptr_dtor] - [GC_ZVAL_CHECK_POSSIBLE_ROOT()] - [gc_zval_check_possible_root()] - [gc_zval_possible_root()]
其中在gc_zval_check_possible_root()函數(shù)中,僅對(duì)數(shù)組和對(duì)象執(zhí)行垃圾回收操作

gc_zval_possible_root函數(shù)的代碼如下:

ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC){if (UNEXPECTED(GC_G(free_list) != NULL  GC_ZVAL_ADDRESS(zv) != NULL  GC_ZVAL_GET_COLOR(zv) == GC_BLACK)  (GC_ZVAL_ADDRESS(zv) GC_G(buf) || GC_ZVAL_ADDRESS(zv) = GC_G(last_unused))) {/* The given zval is a garbage that is going to be deleted by * currently running GC */return;} if (zv- type == IS_OBJECT) {GC_ZOBJ_CHECK_POSSIBLE_ROOT(zv);return;GC_BENCH_INC(zval_possible_root); if (GC_ZVAL_GET_COLOR(zv) != GC_PURPLE) {GC_ZVAL_SET_PURPLE(zv); if (!GC_ZVAL_ADDRESS(zv)) {gc_root_buffer *newRoot = GC_G(unused); if (newRoot) {GC_G(unused) = newRoot- prev;} else if (GC_G(first_unused) != GC_G(last_unused)) {newRoot = GC_G(first_unused);GC_G(first_unused)++;} else {if (!GC_G(gc_enabled)) {GC_ZVAL_SET_BLACK(zv);return;zv- refcount__gc++;gc_collect_cycles(TSRMLS_C);zv- refcount__gc--;newRoot = GC_G(unused);if (!newRoot) {return;GC_ZVAL_SET_PURPLE(zv);GC_G(unused) = newRoot- prev;newRoot- next = GC_G(roots).next;newRoot- prev = GC_G(roots);GC_G(roots).next- prev = newRoot;GC_G(roots).next = newRoot; GC_ZVAL_SET_ADDRESS(zv, newRoot); newRoot- handle = 0;newRoot- u.pz = zv; GC_BENCH_INC(zval_buffered);GC_BENCH_INC(root_buf_length);GC_BENCH_PEAK(root_buf_peak, root_buf_length);}}

第132~140行 檢查zval結(jié)點(diǎn)信息是否已經(jīng)放入到結(jié)點(diǎn)緩沖區(qū),如果已經(jīng)放入到結(jié)點(diǎn)緩沖區(qū),則直接返回,這樣可以優(yōu)化其性能

第142~145行 處理對(duì)象結(jié)點(diǎn),直接返回,不再執(zhí)行后面的操作

第149行 判斷結(jié)點(diǎn)是否已經(jīng)被標(biāo)記為紫色,如果為紫色則不再添加到結(jié)點(diǎn)緩沖區(qū),此處在于保證一個(gè)結(jié)點(diǎn)只執(zhí)行一次添加到緩沖區(qū)的操作。

第150行 將結(jié)點(diǎn)的顏色標(biāo)記為紫色,表示此結(jié)點(diǎn)已經(jīng)添加到緩沖區(qū),下次不用再做添加

第153~157行 找出新的結(jié)點(diǎn)的位置,如果緩沖區(qū)滿了,則執(zhí)行垃圾回收操作。

第176~184行 將新的結(jié)點(diǎn)添加到緩沖區(qū)所在的雙向鏈表。

【垃圾回收過(guò)程】
在gc_zval_possible_root函數(shù)中,當(dāng)緩沖區(qū)滿時(shí),程序調(diào)用gc_collect_cycles函數(shù),執(zhí)行垃圾回收操作。從zend/zend_gc.c文件615行開始,其實(shí)現(xiàn)代碼如下:

 ZEND_API int gc_collect_cycles(TSRMLS_D){int count = 0; if (GC_G(roots).next != GC_G(roots)) {zval_gc_info *p, *q, *orig_free_list, *orig_next_to_free; if (GC_G(gc_active)) {return 0;GC_G(gc_runs)++;GC_G(zval_to_free) = FREE_LIST_END;GC_G(gc_active) = 1;gc_mark_roots(TSRMLS_C);gc_scan_roots(TSRMLS_C);gc_collect_roots(TSRMLS_C); orig_free_list = GC_G(free_list);orig_next_to_free = GC_G(next_to_free);p = GC_G(free_list) = GC_G(zval_to_free);GC_G(zval_to_free) = NULL;GC_G(gc_active) = 0; /* First call destructors */while (p != FREE_LIST_END) {if (Z_TYPE(p- z) == IS_OBJECT) {if (EG(objects_store).object_buckets EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].valid EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.refcount = 0 EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.dtor !EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].destructor_called) { EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].destructor_called = 1;EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.refcount++;EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.object, Z_OBJ_HANDLE(p- z) TSRMLS_CC);EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.refcount--;count++;p = p- u.next;} /* Destroy zvals */p = GC_G(free_list);while (p != FREE_LIST_END) {GC_G(next_to_free) = p- u.next;if (Z_TYPE(p- z) == IS_OBJECT) {if (EG(objects_store).object_buckets EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].valid EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.refcount = 0) {EG(objects_store).object_buckets[Z_OBJ_HANDLE(p- z)].bucket.obj.refcount = 1;Z_TYPE(p- z) = IS_NULL;zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(p- z), Z_OBJ_HT(p- z) TSRMLS_CC);} else if (Z_TYPE(p- z) == IS_ARRAY) {Z_TYPE(p- z) = IS_NULL;zend_hash_destroy(Z_ARRVAL(p- FREE_HASHTABLE(Z_ARRVAL(p- } else {zval_dtor( p- Z_TYPE(p- z) = IS_NULL;p = GC_G(next_to_free);} /* Free zvals */p = GC_G(free_list);while (p != FREE_LIST_END) {q = p- u.next;FREE_ZVAL_EX( p- p = q;GC_G(collected) += count;GC_G(free_list) = orig_free_list;GC_G(next_to_free) = orig_next_to_free;} return count;}

第619行 判斷緩沖區(qū)是否為空,如果為空則不會(huì)執(zhí)行垃圾回收操作
第622行 判斷垃圾回收操作是否正則進(jìn)行,如果正在進(jìn)行,則直接返回
第625~627行 將垃圾回收操作次數(shù)加1,初始化空閑列表,設(shè)置gc_active為1表示垃圾回歸正在進(jìn)行
第628行 此處為其官方文檔中算法的步驟 B ,算法使用深度優(yōu)先搜索查找所有可能的根,找到后將每個(gè)變量容器中的引用計(jì)數(shù)減1″,為確保不會(huì)對(duì)同一個(gè)變量容器減兩次”1″,用灰色標(biāo)記已減過(guò)1的。
第629行 這是算法的步驟 C ,算法再一次對(duì)每個(gè)根節(jié)點(diǎn)使用深度優(yōu)先搜索,檢查每個(gè)變量容器的引用計(jì)數(shù)。如果引用計(jì)數(shù)是 0 ,變量容器用白色來(lái)標(biāo)記。如果引用次數(shù)大于0,則恢復(fù)在這個(gè)點(diǎn)上使用深度優(yōu)先搜索而將引用計(jì)數(shù)減1的操作(即引用計(jì)數(shù)加1),然后將它們重新用黑色標(biāo)記。
第630行 算法的最后一步 D ,算法遍歷根緩沖區(qū)以從那里刪除變量容器根(zval roots),同時(shí),檢查是否有在上一步中被白色標(biāo)記的變量容器。每個(gè)被白色標(biāo)記的變量容器都被清除。
在[gc_collect_cycles() - gc_collect_roots() - zval_collect_white() ]中我們可以看到,對(duì)于白色標(biāo)記的結(jié)點(diǎn)會(huì)被添加到全局變量zval_to_free列表中。此列表在后面的操作中有用到。
第632~633行 將全局變量free_list和next_to_free存放在相對(duì)應(yīng)當(dāng)?shù)呐R時(shí)變量中,在最后會(huì)恢復(fù)到此時(shí)的狀態(tài)。
第634~635行 初始化需要清除的列表,清空將要清空的zval列表并且將垃圾收集的操作狀態(tài)為不激活狀態(tài)。
第639~655行 第一次調(diào)用析構(gòu)函數(shù),并統(tǒng)計(jì)清除的變量個(gè)數(shù)
第657~678行 清除變量
第682~686行 釋放內(nèi)存
第687~689行 處理垃圾個(gè)數(shù)統(tǒng)計(jì),恢復(fù)free_list和next_to_free變量

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,更多相關(guān)內(nèi)容請(qǐng)關(guān)注PHP !

相關(guān)推薦:

淺談PHP源碼三十三:PHP5.3新增加的垃圾回收機(jī)制(Garbage Collection)基礎(chǔ)

淺談PHP源碼三十二:PHP內(nèi)存池中的emalloc/efree層與堆(heap)層

淺談PHP源碼二十九:關(guān)于接口的繼承

以上就是淺談PHP源碼三十四:PHP5.3新增加的垃圾回收機(jī)制(Garbage Collection)的詳細(xì)內(nèi)容,PHP教程

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 修文县| 五华县| 莱芜市| 仪征市| 阜宁县| 吉林省| 洮南市| 金阳县| 沈阳市| 樟树市| 宜宾县| 井研县| 雅江县| 镇坪县| 安岳县| 桐梓县| 屏南县| 重庆市| 千阳县| 长岭县| 武汉市| 昌图县| 合川市| 合肥市| 马尔康县| 彭泽县| 六枝特区| 奇台县| 房山区| 阳东县| 秦皇岛市| 揭东县| 濉溪县| 达拉特旗| 平泉县| 华池县| 滁州市| 三门县| 义马市| 龙门县| 资兴市|