自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

請(qǐng)手動(dòng)釋放你的資源

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

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

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

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

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

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

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

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

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

所以在PHP5.3以后, 我們引入了GC, 也就是說, 我們引入GC是為了解決用戶無法解決的問題.

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

看一個(gè)例子:

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

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

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

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

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

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

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

這是一個(gè)真實(shí)的教訓(xùn), 代碼如上面所示, 突然有一天我們的Mysql出現(xiàn)了問題, 導(dǎo)致連接Mysql的耗時(shí)增大, 然后就導(dǎo)致, 一個(gè)腳本對(duì)Memcached連接占用過長(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)程來說, 自己還有進(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, 而是保留下來給后續(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)

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

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

結(jié)論 (conclusion)

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

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

原文鏈接:http://www.laruence.com/2012/07/25/2662.html

【編輯推薦】

 

責(zé)任編輯:張偉 來源: 風(fēng)雪之隅
相關(guān)推薦

2010-03-05 13:59:16

Linux服務(wù)器內(nèi)存

2010-01-12 11:52:40

2010-01-21 11:25:44

linux多線程線程資源

2012-11-30 11:26:00

代碼注釋

2024-04-29 10:16:40

2020-08-13 11:35:52

Linuxswapbuffer

2021-06-21 06:16:50

cpulimitCPULinux

2009-09-02 10:39:00

C#釋放托管資源

2021-02-24 14:00:42

LinuxChromebook谷歌

2017-07-13 10:14:20

大數(shù)據(jù)動(dòng)向數(shù)據(jù)價(jià)值

2012-09-10 09:16:54

2015-11-16 20:59:37

2015-04-08 09:54:41

OpenStack資源私有云部署

2014-05-22 10:25:44

Umask 值Linux

2014-12-05 10:06:44

程序員

2020-06-22 08:30:42

Linux內(nèi)存手動(dòng)釋放

2016-12-23 14:51:25

Android手動(dòng)備份短信彩信

2016-12-27 18:36:58

Android備份手機(jī)

2017-06-12 13:59:11

2023-11-13 14:50:53

CSS開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)