天天看點

伺服器公共元件實作 -- 環形緩沖區

消息隊列鎖調用太頻繁的問題算是解決了,另一個讓人有些苦惱的大概是這太多的記憶體配置設定和釋放操作了。頻繁的記憶體配置設定不但增加了系統開銷,更使得記憶體碎片不斷增多,非常不利于我們的伺服器長期穩定運作。也許我們可以使用記憶體池,比如SGI STL中附帶的小記憶體配置設定器。但是對于這種按照嚴格的先進先出順序處理的,塊大小并不算小的,而且塊大小也并不統一的記憶體配置設定情況來說,更多使用的是一種叫做環形緩沖區的方案,mangos的網絡代碼中也有這麼一個東西,其原理也是比較簡單的。

  就好比兩個人圍着一張圓形的桌子在追逐,跑的人被網絡IO線程所控制,當寫入資料時,這個人就往前跑;追的人就是邏輯線程,會一直往前追直到追上跑的人。如果追上了怎麼辦?那就是沒有資料可讀了,先等會兒呗,等跑的人向前跑幾步了再追,總不能讓遊戲沒得玩了吧。那要是追的人跑的太慢,跑的人轉了一圈過來反追上追的人了呢?那您也先歇會兒吧。要是一直這麼反着追,估計您就隻能換一個跑的更快的追逐者了,要不這遊戲還真沒法玩下去。

  前面我們特别強調了,按照嚴格的先進先出順序進行處理,這是環形緩沖區的使用必須遵守的一項要求。也就是,大家都得遵守規定,追的人不能從桌子上跨過去,跑的人當然也不允許反過來跑。至于為什麼,不需要多做解釋了吧。

  環形緩沖區是一項很好的技術,不用頻繁的配置設定記憶體,而且在大多數情況下,記憶體的反複使用也使得我們能用更少的記憶體塊做更多的事。

  在網絡IO線程中,我們會為每一個連接配接都準備一個環形緩沖區,用于臨時存放接收到的資料,以應付半包及粘包的情況。在解包及解密完成後,我們會将這個資料包複制到邏輯線程消息隊列中,如果我們隻使用一個隊列,那這裡也将會是個環形緩沖區,IO線程往裡寫,邏輯線程在後面讀,互相追逐。可要是我們使用了前面介紹的優化方案後,可能這裡便不再需要環形緩沖區了,至少我們并不再需要他們是環形的了。因為我們對同一個隊列不再會出現同時讀和寫的情況,每個隊列在寫滿後交給邏輯線程去讀,邏輯線程讀完後清空隊列再交給IO線程去寫,一段固定大小的緩沖區即可。沒關系,這麼好的技術,在别的地方一定也會用到的。

繼續閱讀