轉(zhuǎn)載:http://blog.csdn.net/lfhfut/archive/2007/09/20/1793797.aspx
消息隊(duì)列鎖調(diào)用太頻繁的問(wèn)題算是解決了,另一個(gè)讓人有些苦惱的大概是這太多的內(nèi)存分配和釋放操作了。頻繁的內(nèi)存分配不但增加了系統(tǒng)開(kāi)銷(xiāo),更使得內(nèi)存碎片不斷增多,非常不利于我們的服務(wù)器長(zhǎng)期穩(wěn)定運(yùn)行。也許我們可以使用內(nèi)存池,比如SGI STL中附帶的小內(nèi)存分配器。但是對(duì)于這種按照嚴(yán)格的先進(jìn)先出順序處理的,塊大小并不算小的,而且塊大小也并不統(tǒng)一的內(nèi)存分配情況來(lái)說(shuō),更多使用的是一種叫做環(huán)形緩沖區(qū)的方案,mangos的網(wǎng)絡(luò)代碼中也有這么一個(gè)東西,其原理也是比較簡(jiǎn)單的。
就好比兩個(gè)人圍著一張圓形的桌子在追逐,跑的人被網(wǎng)絡(luò)IO線(xiàn)程所控制,當(dāng)寫(xiě)入數(shù)據(jù)時(shí),這個(gè)人就往前跑;追的人就是邏輯線(xiàn)程,會(huì)一直往前追直到追上跑的人。如果追上了怎么辦?那就是沒(méi)有數(shù)據(jù)可讀了,先等會(huì)兒?jiǎn)h,等跑的人向前跑幾步了再追,總不能讓游戲沒(méi)得玩了吧。那要是追的人跑的太慢,跑的人轉(zhuǎn)了一圈過(guò)來(lái)反追上追的人了呢?那您也先歇會(huì)兒吧。要是一直這么反著追,估計(jì)您就只能換一個(gè)跑的更快的追逐者了,要不這游戲還真沒(méi)法玩下去。
前面我們特別強(qiáng)調(diào)了,按照嚴(yán)格的先進(jìn)先出順序進(jìn)行處理,這是環(huán)形緩沖區(qū)的使用必須遵守的一項(xiàng)要求。也就是,大家都得遵守規(guī)定,追的人不能從桌子上跨過(guò)去,跑的人當(dāng)然也不允許反過(guò)來(lái)跑。至于為什么,不需要多做解釋了吧。
環(huán)形緩沖區(qū)是一項(xiàng)很好的技術(shù),不用頻繁的分配內(nèi)存,而且在大多數(shù)情況下,內(nèi)存的反復(fù)使用也使得我們能用更少的內(nèi)存塊做更多的事。
在網(wǎng)絡(luò)IO線(xiàn)程中,我們會(huì)為每一個(gè)連接都準(zhǔn)備一個(gè)環(huán)形緩沖區(qū),用于臨時(shí)存放接收到的數(shù)據(jù),以應(yīng)付半包及粘包的情況。在解包及解密完成后,我們會(huì)將這個(gè)數(shù)據(jù)包復(fù)制到邏輯線(xiàn)程消息隊(duì)列中,如果我們只使用一個(gè)隊(duì)列,那這里也將會(huì)是個(gè)環(huán)形緩沖區(qū),IO線(xiàn)程往里寫(xiě),邏輯線(xiàn)程在后面讀,互相追逐。可要是我們使用了前面介紹的優(yōu)化方案后,可能這里便不再需要環(huán)形緩沖區(qū)了,至少我們并不再需要他們是環(huán)形的了。因?yàn)槲覀儗?duì)同一個(gè)隊(duì)列不再會(huì)出現(xiàn)同時(shí)讀和寫(xiě)的情況,每個(gè)隊(duì)列在寫(xiě)滿(mǎn)后交給邏輯線(xiàn)程去讀,邏輯線(xiàn)程讀完后清空隊(duì)列再交給IO線(xiàn)程去寫(xiě),一段固定大小的緩沖區(qū)即可。沒(méi)關(guān)系,這么好的技術(shù),在別的地方一定也會(huì)用到的。