国产成人精品亚洲777人妖,欧美日韩精品一区视频,最新亚洲国产,国产乱码精品一区二区亚洲

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

PHP特點(diǎn)之垃圾回收機(jī)制3——性能方面考慮的因素

瀏覽:8日期:2022-09-15 14:53:32

在上一節(jié)我們已經(jīng)簡(jiǎn)單的提到:回收可能根有細(xì)微的性能上影響,但這是把PHP 5.2與PHP 5.3比較時(shí)才有的。盡管在PHP 5.2中,記錄可能根相對(duì)于完全不記錄可能根要慢些,而PHP 5.3中對(duì) PHP run-time 的其他修改減少了這個(gè)性能損失。

這里主要有兩個(gè)領(lǐng)域?qū)π阅苡杏绊憽5谝粋€(gè)是內(nèi)存占用空間的節(jié)省,另一個(gè)是垃圾回收機(jī)制執(zhí)行內(nèi)存清理時(shí)的執(zhí)行時(shí)間增加(run-time delay)。我們將研究這兩個(gè)領(lǐng)域。

內(nèi)存占用空間的節(jié)省

首先,實(shí)現(xiàn)垃圾回收機(jī)制的整個(gè)原因是為了,一旦先決條件滿足,通過清理循環(huán)引用的變量來(lái)節(jié)省內(nèi)存占用。在PHP執(zhí)行中,一旦根緩沖區(qū)滿了或者調(diào)用 gc_collect_cycles()函數(shù)時(shí),就會(huì)執(zhí)行垃圾回收。在下圖中,顯示了下面腳本分別在PHP 5.2 和 PHP 5.3環(huán)境下的內(nèi)存占用情況,其中排除了腳本啟動(dòng)時(shí)PHP本身占用的基本內(nèi)存。

Example #1 內(nèi)存使用示例

<?php class Foo {public $var = ’3.1415962654’; } $baseMemory = memory_get_usage(); for ( $i = 0; $i <= 100000; $i++ ) {$a = new Foo;$a->self = $a;if ( $i % 500 === 0 ){ echo sprintf( ’%8d: ’, $i ), memory_get_usage() - $baseMemory, 'n';} }?>PHP特點(diǎn)之垃圾回收機(jī)制3——性能方面考慮的因素

在這個(gè)很理論性的例子中,我們創(chuàng)建了一個(gè)對(duì)象,這個(gè)對(duì)象中的一個(gè)屬性被設(shè)置為指回對(duì)象本身。在循環(huán)的下一個(gè)重復(fù)(iteration)中,當(dāng)腳本中的變量被重新復(fù)制時(shí),就會(huì)發(fā)生典型性的內(nèi)存泄漏。在這個(gè)例子中,兩個(gè)變量容器是泄漏的(對(duì)象容器和屬性容器),但是僅僅能找到一個(gè)可能根:就是被unset的那個(gè)變量。在10,000次重復(fù)后(也就產(chǎn)生總共10,000個(gè)可能根),當(dāng)根緩沖區(qū)滿時(shí),就執(zhí)行垃圾回收機(jī)制,并且釋放那些關(guān)聯(lián)的可能根的內(nèi)存。這從PHP 5.3的鋸齒型內(nèi)存占用圖中很容易就能看到。每次執(zhí)行完10,000次重復(fù)后,執(zhí)行垃圾回收,并釋放相關(guān)的重復(fù)使用的引用變量。在這個(gè)例子中由于泄漏的數(shù)據(jù)結(jié)構(gòu)非常簡(jiǎn)單,所以垃圾回收機(jī)制本身不必做太多工作。從這個(gè)圖表中,你能看到 PHP 5.3的最大內(nèi)存占用大概是9 Mb,而PHP 5.2的內(nèi)存占用一直增加。

執(zhí)行時(shí)間增加(Run-Time Slowdowns)

垃圾回收影響性能的第二個(gè)領(lǐng)域是它釋放已泄漏的內(nèi)存耗費(fèi)的時(shí)間。為了看到這個(gè)耗時(shí)時(shí)多少,我們稍微改變了上面的腳本,有更多次數(shù)的重復(fù)并且刪除了循環(huán)中的內(nèi)存占用計(jì)算,第二個(gè)腳本代碼如下:

Example #2 GC performance influences

<?php class Foo {public $var = ’3.1415962654’; } for ( $i = 0; $i <= 1000000; $i++ ) {$a = new Foo;$a->self = $a; } echo memory_get_peak_usage(), 'n';?>

我們將運(yùn)行這個(gè)腳本兩次,一次通過配置zend.enable_gc 打開垃圾回收機(jī)制時(shí),另一次是它關(guān)閉時(shí)。

Example #3 Running the above script

time php -dzend.enable_gc=0 -dmemory_limit=-1 -n example2.php# andtime php -dzend.enable_gc=1 -dmemory_limit=-1 -n example2.php

在我的機(jī)器上,第一個(gè)命令持續(xù)執(zhí)行時(shí)間大概為10.7秒,而第二個(gè)命令耗費(fèi)11.4秒。時(shí)間上增加了7%。然而,執(zhí)行這個(gè)腳本時(shí)內(nèi)存占用的峰值降低了98%,從931Mb 降到 10Mb。這個(gè)基準(zhǔn)不是很科學(xué),或者并不能代表真實(shí)應(yīng)用程序的數(shù)據(jù),但是它的確顯示了垃圾回收機(jī)制在內(nèi)存占用方面的好處。好消息就是,對(duì)這個(gè)腳本而言,在執(zhí)行中出現(xiàn)更多的循環(huán)引用變量時(shí),內(nèi)存節(jié)省的更多的情況下,每次時(shí)間增加的百分比都是7%。

PHP內(nèi)部 GC 統(tǒng)計(jì)信息

在PHP內(nèi)部,可以顯示更多的關(guān)于垃圾回收機(jī)制如何運(yùn)行的信息。但是要顯示這些信息,你需要先重新編譯PHP使benchmark和data-collecting code可用。你需要在按照你的意愿運(yùn)行./configure前,把環(huán)境變量CFLAGS設(shè)置成-DGC_BENCH=1。下面的命令串就是做這個(gè)事:

Example #4 Recompiling PHP to enable GC benchmarking

export CFLAGS=-DGC_BENCH=1./config.nicemake cleanmake

當(dāng)你用新編譯的PHP二進(jìn)制文件來(lái)重新執(zhí)行上面的例子代碼,在PHP執(zhí)行結(jié)束后,你將看到下面的信息:

Example #5 GC statistics

GC Statistics-------------Runs: 110Collected: 2072204Root buffer length: 0Root buffer peak: 10000 Possible Remove from MarkedRoot Buffered buffer grey -------- -------- ----------- ------ZVAL 7175487 1491291 1241690 3611871ZOBJ 28506264 1527980 677581 1025731

主要的信息統(tǒng)計(jì)在第一個(gè)塊。你能看到垃圾回收機(jī)制運(yùn)行了110次,而且在這110次運(yùn)行中,總共有超過兩百萬(wàn)的內(nèi)存分配被釋放。只要垃圾回收機(jī)制運(yùn)行了至少一次,根緩沖區(qū)峰值(Root buffer peak)總是10000.

結(jié)論

通常,PHP中的垃圾回收機(jī)制,僅僅在循環(huán)回收算法確實(shí)運(yùn)行時(shí)會(huì)有時(shí)間消耗上的增加。但是在平常的(更小的)腳本中應(yīng)根本就沒有性能影響。

然而,在平常腳本中有循環(huán)回收機(jī)制運(yùn)行的情況下,內(nèi)存的節(jié)省將允許更多這種腳本同時(shí)運(yùn)行在你的服務(wù)器上。因?yàn)榭偣彩褂玫膬?nèi)存沒達(dá)到上限。

這種好處在長(zhǎng)時(shí)間運(yùn)行腳本中尤其明顯,諸如長(zhǎng)時(shí)間的測(cè)試套件或者daemon腳本此類。同時(shí),對(duì)通常比Web腳本運(yùn)行時(shí)間長(zhǎng)的? PHP-GTK應(yīng)用程序,新的垃圾回收機(jī)制,應(yīng)該會(huì)大大改變一直以來(lái)認(rèn)為內(nèi)存泄漏問題難以解決的看法。

標(biāo)簽: PHP
相關(guān)文章:
主站蜘蛛池模板: 稻城县| 徐汇区| 吉安县| 汉沽区| 乌拉特后旗| 淳化县| 浪卡子县| 清丰县| 洛阳市| 梁河县| 都兰县| 巴彦淖尔市| 孝义市| 焉耆| 新绛县| 伊吾县| 财经| 宁化县| 临泉县| 咸宁市| 宁河县| 任丘市| 南汇区| 祁东县| 濮阳县| 福安市| 嘉峪关市| 丽水市| 德惠市| 昌平区| 五大连池市| 黄大仙区| 积石山| 东方市| 新密市| 丽江市| 菏泽市| 荆门市| 罗田县| 龙南县| 三河市|