日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
請(qǐng)手動(dòng)釋放你的資源

我從來(lái)不認(rèn)為這個(gè)問(wèn)題是個(gè)問(wèn)題, 直到昨天.

創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站制作、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的開福網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

昨天晚上的時(shí)候, 我提交了一個(gè)RFC, 關(guān)于引入finally到PHP, 實(shí)現(xiàn)這個(gè)功能的出發(fā)點(diǎn)很簡(jiǎn)單, 因?yàn)槲铱匆姴簧偃说男枨? 另外還有就是Stas說(shuō), 一直只看到討論, 沒(méi)看到有人實(shí)現(xiàn). 于是我就給實(shí)現(xiàn)了.

發(fā)到郵件組以后, 一個(gè)開發(fā)組的同學(xué)Nikita Popov(nikic), 表示強(qiáng)烈反對(duì)這個(gè)RFC, 當(dāng)然最初的論點(diǎn)他說(shuō)了很多, ***我們?cè)诰€討論的時(shí)候, 他表達(dá)了一個(gè)他的觀點(diǎn):

“PHP在請(qǐng)求結(jié)束后會(huì)釋放所有的資源, 所以我們沒(méi)有必要調(diào)用fclose,或者mysql_close來(lái)釋放資源, PHP會(huì)替我們做”

并且他表示, 他從來(lái)都不會(huì)調(diào)用fclose, 認(rèn)為fclose的存在只是為了繼承C函數(shù)族.

我很驚訝, 我也不知道還有多少人是和他一樣的想法, 所以我決定寫這篇文章.

在PHP5.2以前, PHP使用引用計(jì)數(shù)(Reference count)來(lái)做資源管理, 當(dāng)一個(gè)zval的引用計(jì)數(shù)為0的時(shí)候, 它就會(huì)被釋放. 雖然存在循環(huán)引用(Cycle reference), 但這樣的設(shè)計(jì)對(duì)于開發(fā)Web腳本來(lái)說(shuō), 沒(méi)什么問(wèn)題, 因?yàn)閃eb腳本的特點(diǎn)和它追求的目標(biāo)就是執(zhí)行時(shí)間短, 不會(huì)長(zhǎng)期運(yùn)行. 對(duì)于循環(huán)引用造成的資源泄露, 會(huì)在請(qǐng)求結(jié)束時(shí)釋放掉. 也就是說(shuō), 請(qǐng)求結(jié)束時(shí)釋放資源, 是一種部補(bǔ)救措施(backup).

然而, 隨著PHP被越來(lái)越多的人使用, 就有很多人在一些后臺(tái)腳本使用PHP, 這些腳本的特點(diǎn)是長(zhǎng)期運(yùn)行, 如果存在循環(huán)引用, 導(dǎo)致引用計(jì)數(shù)無(wú)法及時(shí)釋放不用的資源, 則這個(gè)腳本最終會(huì)內(nèi)存耗盡退出.

所以在PHP5.3以后, 我們引入了GC, 也就是說(shuō), 我們引入GC是為了解決用戶無(wú)法解決的問(wèn)題.

這個(gè)是歷史, 我簡(jiǎn)單介紹下, 現(xiàn)在讓我們回頭來(lái)看開頭的問(wèn)題, 是不是因?yàn)镻HP會(huì)在請(qǐng)求結(jié)束后釋放所有的資源, 于是我們就可以不用手動(dòng)釋放呢?

看一個(gè)例子:

Mysql***連接數(shù)(mysql.max_connections)

 
 
 
  1.     $db = mysql_connect() ;
  2.     $resut = mysql_query();
  3.     // process result...
  4.     usleep(500);
  5.  
  6.     //mysql_close($db); let's say, you didn't call to this
  7.  
  8.     // other logic, assuming it costs 5s
  9.     sleep(5);
  10.  
  11.     exit(0); //finish

上面的例子, 我們會(huì)保持一個(gè)和Mysql的連接5秒鐘, 這樣的腳本對(duì)于一般的應(yīng)用來(lái)說(shuō)沒(méi)有關(guān)系, 但是對(duì)于一個(gè)請(qǐng)求量很大的腳本來(lái)說(shuō), 會(huì)導(dǎo)致一個(gè)致命問(wèn)題:

比如一個(gè)繁忙的應(yīng)用, 每秒要處理來(lái)自用戶的1000個(gè)請(qǐng)求, 那么5秒鐘請(qǐng)求多少個(gè)? 5 * 1000 = 5000, 而Mysql有***連接數(shù)限制(mysql.max_connections), 這個(gè)數(shù)字一般不超過(guò)2000, 默認(rèn)的會(huì)更低:(mysql.max_connections),

那么, 這樣代碼會(huì)導(dǎo)致你的應(yīng)用, 根本無(wú)法正常提供服務(wù). 而如果我們?cè)趯?duì)Mysql的處理完成后就關(guān)閉這個(gè)連接, 那么就不會(huì)觸發(fā)這個(gè)問(wèn)題.

而我們?cè)趯?shí)踐中, 遇到過(guò)一個(gè)更加實(shí)際的問(wèn)題, 看下面的例子:

 
 
 
  1. $mmc = new Memcached();
  2. $mysql = mysql_connect();
  3. //process
  4. mysql_close($mysql);
  5. $mmc->close();

這是一個(gè)真實(shí)的教訓(xùn), 代碼如上面所示, 突然有一天我們的Mysql出現(xiàn)了問(wèn)題, 導(dǎo)致連接Mysql的耗時(shí)增大, 然后就導(dǎo)致, 一個(gè)腳本對(duì)Memcached連接占用過(guò)長(zhǎng), ***Memcache因?yàn)檫B接數(shù)太多, 就拒絕服務(wù)了..

所以, 我們一定要讓連接代價(jià)***的資源, ***初始化.

系統(tǒng)***句柄 (/proc/sys/fs/file-max)

這個(gè)很簡(jiǎn)單, 如果你持續(xù)打開句柄, 而不釋放, 那么你有可能觸發(fā)系統(tǒng)***句柄限制, 對(duì)于進(jìn)程來(lái)說(shuō), 自己還有進(jìn)程可打開句柄數(shù)限制(ulimit -n).

系統(tǒng)調(diào)用是昂貴的(System call is expensive)

PHP之所以會(huì)在請(qǐng)求結(jié)束后正確的釋放掉所有的資源, 內(nèi)存, 這是因?yàn)楫?dāng)我們?cè)谀_本中使用新的內(nèi)存的時(shí)候, PHP會(huì)向OS申請(qǐng)一大塊內(nèi)存(ZEND_MM_SEG_SIZE大小), 然后分給你你需要的合適的一塊小內(nèi)存.

當(dāng)你不使用這塊小內(nèi)存的時(shí)候, PHP也不會(huì)返還給OS, 而是保留下來(lái)給后續(xù)的處理使用.

我們知道, malloc(3)會(huì)導(dǎo)致系統(tǒng)調(diào)用(brk(2))(當(dāng)然也可能是mmap, 我們此處不考慮這個(gè)細(xì)節(jié), thanks to 華裔), 而系統(tǒng)調(diào)用是昂貴的.

所以, 如果你使用完了資源不及時(shí)釋放, 那么后續(xù)的邏輯如果請(qǐng)求內(nèi)存, PHP發(fā)現(xiàn)之前申請(qǐng)的一大塊內(nèi)存已經(jīng)分光了, 它就只好再次向OS發(fā)起malloc調(diào)用, 得到一塊新的大內(nèi)存. 并且它還需要對(duì)這個(gè)大內(nèi)存做一些標(biāo)記處理..

而如果你使用完資源, 及時(shí)釋放的話, 那么下次腳本申請(qǐng)內(nèi)存的時(shí)候, 你之前歸還的內(nèi)存塊就可以被重復(fù)利用, 那么也許你的整個(gè)腳本只需要和OS申請(qǐng)一次內(nèi)存.

內(nèi)存峰值(Memory peak usage)

這個(gè)和上面的有一定的關(guān)系, 當(dāng)你使用完資源就釋放, 然后后續(xù)又使用這樣的資源. 那么PHP的內(nèi)存占用會(huì)是:

資源+1 -> 資源-1 -> 資源+1 -> 資源-1 (峰值是1)

而如果你是等到PHP請(qǐng)求結(jié)束再釋放:

資源+1 -> 資源 + 1 …. -> 資源 -1 -> 資源 – 1 (峰值是2)

也就說(shuō), 一個(gè)良好的編寫的腳本可能要比一個(gè)瞎寫的腳本, 要省很多峰值內(nèi)存..

考慮一個(gè)極端情況, 對(duì)一個(gè)很繁忙的服務(wù)器來(lái)說(shuō), 比如有10個(gè)PHP進(jìn)程, 每個(gè)PHP進(jìn)程***1G內(nèi)存, 而服務(wù)器只有8G內(nèi)存.

結(jié)論 (conclusion)

結(jié)論很明顯, 我開頭也說(shuō)過(guò)了, 我從來(lái)不認(rèn)為這個(gè)是個(gè)問(wèn)題.

這里說(shuō)一句, 如果你買了一本PHP的書, 它告訴你: “不用在PHP主動(dòng)釋放資源, 因?yàn)镻HP會(huì)幫你釋放”的話, 我建議你, 燒了它.


當(dāng)前名稱:請(qǐng)手動(dòng)釋放你的資源
鏈接地址:http://www.dlmjj.cn/article/dhdoedd.html