JAVA IO專題三:java的內(nèi)存映射和應(yīng)用場(chǎng)景

相關(guān)java IO專題

JAVA IO專題一:java InputStream和OutputStream讀取文件并通過(guò)socket發(fā)送埋哟,到底涉及幾次拷貝
JAVA IO專題二:java NIO讀取文件并通過(guò)socket發(fā)送,最少拷貝了幾次?堆外內(nèi)存和所謂的零拷貝到底是什么關(guān)系
JAVA IO專題三:java的內(nèi)存映射和應(yīng)用場(chǎng)景
JAVA IO專題四:java順序IO原理以及對(duì)應(yīng)的應(yīng)用場(chǎng)景

mmap的作用

mmap的作用,是將文件的一部分直接映射到內(nèi)存(堆外內(nèi)存)漠另,對(duì)這個(gè)映射的操作會(huì)由操作系統(tǒng)在某個(gè)特定的時(shí)期自動(dòng)將臟頁(yè)寫(xiě)回文件對(duì)應(yīng)的位置(也可以通過(guò)msync強(qiáng)制寫(xiě)回)探遵,而不必調(diào)用read/write。mapp完成后僧家,OS并沒(méi)有直接讀取文件的內(nèi)容,而是在真正要訪問(wèn)的時(shí)候裸删,通過(guò)缺頁(yè)異常來(lái)進(jìn)行讀磁盤操作八拱。

mmap相比普通的文件讀寫(xiě)優(yōu)勢(shì)在哪

常規(guī)文件操作為了提高讀寫(xiě)效率和保護(hù)磁盤,使用了頁(yè)緩存機(jī)制涯塔。這樣造成讀文件時(shí)需要先將文件頁(yè)從磁盤拷貝到頁(yè)緩存中肌稻,由于頁(yè)緩存處在內(nèi)核空間,不能被用戶進(jìn)程直接尋址匕荸,所以還需要將頁(yè)緩存中數(shù)據(jù)頁(yè)再次拷貝到內(nèi)存對(duì)應(yīng)的用戶空間中爹谭。

而mmap實(shí)現(xiàn)了將設(shè)備驅(qū)動(dòng)在內(nèi)核空間的部分地址直接映射到用戶空間,使得用戶程序可以直接訪問(wèn)和操作相應(yīng)的內(nèi)容榛搔,減少了額外的拷貝诺凡。

說(shuō)白了,mmap的關(guān)鍵點(diǎn)是實(shí)現(xiàn)了用戶空間和內(nèi)核空間的數(shù)據(jù)直接交互而省去了空間不同數(shù)據(jù)不通的繁瑣過(guò)程践惑。因此mmap效率更高腹泌。

mmap不適合的場(chǎng)景

mmap也不是萬(wàn)能的:

  • mmap內(nèi)存映射的大小始終是整數(shù)頁(yè),因此對(duì)于文件實(shí)際大小和映射的空間之間多少回有差異尔觉,這個(gè)差異的空間是被浪費(fèi)的凉袱,對(duì)于小文件來(lái)說(shuō)這個(gè)浪費(fèi)比例被放大,因此mmap更適合大文件侦铜。
  • 頻繁映射大量不同大小的內(nèi)存专甩,會(huì)導(dǎo)致內(nèi)存碎片化。

java中mmap的應(yīng)用

java中提供了MappedByteBuffer支持mmap的調(diào)用泵额,其本身是一個(gè)DirectByteBuffer配深,即堆外內(nèi)存携添。獲取MappedByteBuffer方式如下:

MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, fileSize);

另外MappedByteBuffer擴(kuò)展了一個(gè)force方法嫁盲,強(qiáng)制將buffer中的內(nèi)容寫(xiě)入磁盤。

java內(nèi)存映射的應(yīng)用場(chǎng)景

消息隊(duì)列的場(chǎng)景非常契合前面說(shuō)到的mmap的優(yōu)勢(shì)烈掠,并且能夠完美避開(kāi)其劣勢(shì)羞秤。java開(kāi)源消息隊(duì)列RocketMQ和QMQ都采用了MappedByteBuffer寫(xiě)消息數(shù)據(jù),以順序?qū)懙姆绞教岣咄掏铝孔蟮小_@里舉QMQ為例(RocketMQ筆者不太了解hhh):

  • 所有的消息都用LogSegment來(lái)管理瘾蛋,一個(gè)LogSegment對(duì)應(yīng)磁盤上的一個(gè)文件,持有一個(gè)fileChannel
    mappedByteBuffer矫限,并且每次都會(huì)記錄最后寫(xiě)入的位置AtomicInteger wrotePosition = new AtomicInteger(0);
  • mappedByteBufferchannel.map獲得哺哼,fileSize默認(rèn)都是1G佩抹。
  • 寫(xiě)數(shù)據(jù)的時(shí)候會(huì)通過(guò)mappedByteBuffer.slice獲取targetByteBuffer(沒(méi)有直接寫(xiě)到mappedByteBuffer是因?yàn)椋咳《浚┕髌唬⑼ㄟ^(guò) buffer.position(currentPos);將寫(xiě)指針移動(dòng)到上次寫(xiě)的位置,然后將數(shù)據(jù)追加到后面:
//這里的workingBuffer是堆內(nèi)存茵汰,初始化了一些header數(shù)據(jù)
targetBuffer.put(workingBuffer.array(), 0, headerSize);
//這里的nioBuffer是netty接收到的消息枢里,默認(rèn)為堆外內(nèi)存
targetBuffer.put(message.getBody().nioBuffer());
  • 另外在PeriodicFlushService中開(kāi)啟一個(gè)定時(shí)任務(wù),每隔一定時(shí)間(默認(rèn)500ms)將buffer數(shù)據(jù)刷盤(通過(guò)buffer.force())蹂午。

參考文章

Linux 中 mmap() 函數(shù)的內(nèi)存映射問(wèn)題理解
認(rèn)真分析mmap:是什么 為什么 怎么用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末栏豺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子豆胸,更是在濱河造成了極大的恐慌奥洼,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晚胡,死亡現(xiàn)場(chǎng)離奇詭異溉卓,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)搬泥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門桑寨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人忿檩,你說(shuō)我怎么就攤上這事尉尾。” “怎么了燥透?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵沙咏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我班套,道長(zhǎng)肢藐,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任吱韭,我火速辦了婚禮吆豹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘理盆。我一直安慰自己痘煤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布猿规。 她就那樣靜靜地躺著衷快,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姨俩。 梳的紋絲不亂的頭發(fā)上蘸拔,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天师郑,我揣著相機(jī)與錄音,去河邊找鬼调窍。 笑死呕乎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陨晶。 我是一名探鬼主播猬仁,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼先誉!你這毒婦竟也來(lái)了湿刽?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤褐耳,失蹤者是張志新(化名)和其女友劉穎诈闺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铃芦,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雅镊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刃滓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仁烹。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咧虎,靈堂內(nèi)的尸體忽然破棺而出卓缰,到底是詐尸還是另有隱情,我是刑警寧澤砰诵,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布征唬,位于F島的核電站,受9級(jí)特大地震影響茁彭,放射性物質(zhì)發(fā)生泄漏总寒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一理肺、第九天 我趴在偏房一處隱蔽的房頂上張望摄闸。 院中可真熱鬧,春花似錦哲嘲、人聲如沸贪薪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至竣稽,卻和暖如春囱怕,著一層夾襖步出監(jiān)牢的瞬間霍弹,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工娃弓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留典格,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓台丛,卻偏偏與公主長(zhǎng)得像耍缴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挽霉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容