MappedByteBuffer VS FileChannel 孰強(qiáng)孰弱妙黍?

前言

Java 在 JDK 1.4 引入了 ByteBuffer 等 NIO 相關(guān)的類峭梳,使得 Java 程序員可以拋棄基于 Stream 持偏,從而使用基于 Block 的方式讀寫文件砍的,另外痹筛,JDK 還引入了 IO 性能優(yōu)化之王—— 零拷貝 sendFile 和 mmap。但他們的性能究竟怎么樣? 和 RandomAccessFile 比起來帚稠,快多少谣旁? 什么情況下快?到底是 FileChannel 快還是 MappedByteBuffer 快......

(零拷貝參考 Zero Copy I: User-Mode Perspective)

天啊翁锡,問題太多了B凇!9菹巍N僚小!角溃!

讓我們慢慢分析拷获。

看看善于利用 IO 零拷貝的 MQ 們

我們知道,Java 世界有很多 MQ:ActiveMQ减细,kafka匆瓜,RocketMQ,去哪兒 MQ未蝌,而他們則是 Java 世界使用 NIO 零拷貝的大戶驮吱。

然而,他們的性能卻大相同萧吠,拋開其他的因素左冬,例如網(wǎng)絡(luò)傳輸方式,數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)纸型,文件存儲方式拇砰,我們僅僅討論 Broker 端對文件的讀寫,看看他們有什么不同狰腌。

下圖是樓主查看源碼總結(jié)的各個 MQ 使用的文件讀寫方式除破。

  • kafka:record 的讀寫都是基于 FileChannel。index 讀寫基于 MMAP(廝大提示)琼腔。
  • RocketMQ:讀盤基于 MMAP瑰枫,寫盤默認(rèn)使用 MMAP,可通過修改配置展姐,配置成 FileChannel躁垛,原因是作者想避免 PageCache 的鎖競爭,通過兩層架構(gòu)實(shí)現(xiàn)讀寫分離圾笨。
  • QMQ: 去哪兒 MQ教馆,讀盤使用 MMAP,寫盤使用 FileChannel擂达。
  • ActiveMQ 5.15: 讀寫全部都是基于 RandomAccessFile土铺,這也是我們拋棄 ActiveMQ 的原因。

那么,到底是 MMAP 強(qiáng)悲敷,還是 FileChannel 強(qiáng)究恤?

MMAP 眾所周知,基于 OS 的 mmap 的內(nèi)存映射技術(shù)后德,通過 MMU 映射文件部宿,使隨機(jī)讀寫文件和讀寫內(nèi)存相似的速度。

那 FileChannel 呢瓢湃?是零拷貝嗎理张?很遺憾,不是绵患。FileChannel 快雾叭,只是因?yàn)樗腔?block 的。

接下來落蝙,benchmark everything —— 徐媽.

Benchmark 织狐?

如何 Benchmark? Benchmark 哪些筏勒?

既然是讀寫文件移迫,自然就要看讀寫性能,這是最基本的管行。但起意,注意,通常 MQ 會使用定時(shí)刷盤病瞳,防止數(shù)據(jù)丟失,MMAP 和 FileChannel 都有 force 方法悲酷,用于將 pageCache 的數(shù)據(jù)刷到硬盤上套菜。force 會影響性能嗎? 答案是會设易。影響到什么程度呢逗柴? 不知道。每次寫入的數(shù)據(jù)大小會影響性能嗎顿肺,毫無疑問會戏溺,但規(guī)則是什么呢?FileOutputStream 真的一無是處嗎屠尊?答案是不一定旷祸。

一直以來,文件調(diào)優(yōu)都是藝術(shù)讼昆,因?yàn)橛绊懶阅艿囊蛩靥嗤邢恚紫龋琒SD 的出現(xiàn),已經(jīng)讓傳統(tǒng)基于 B+ tree 的樹形結(jié)構(gòu)產(chǎn)生了自我疑問闰围,第二赃绊,每個文件系統(tǒng)的性能不同,Linux ext3 和 ext4 性能天壤之別(刪除文件的性能差距在 20 倍左右)羡榴。而 Max OS 的 HFS+ 系統(tǒng)被 Linus 稱之為“有史以來最垃圾的文件系統(tǒng)”碧查,幸運(yùn)的是,蘋果終于在 2017 年推送了 macOS High Sierra 和 iOS 10.3 系統(tǒng)校仑,這個兩個系統(tǒng)都拋棄了 HFS+忠售,換成了性能更高的 APFS。而每個文件系統(tǒng)又可以設(shè)置不同的調(diào)度算法肤视,另外档痪,還有虛擬內(nèi)存缺頁中斷帶來的性能毛刺.......

(tips:良心的 RocketMQ 提供了 Linux IO 調(diào)優(yōu)的腳本,這點(diǎn)做的不錯 :)

跑題了邢滑。

樓主寫了一個小項(xiàng)目腐螟,用于測試 Java MappedByteBuffer & FileChannel & RandomAccessFile & FileXXXputStream 的讀寫性能。大家也可以在自己的機(jī)器上跑跑看困后。

測試環(huán)境

CPU:intel i7 4核8線程 4.2GHz
內(nèi)存:40GB DDR4
磁盤:SSD 讀寫 2GB/s 左右
JDK1.8
OS:Mac OS 10.13.6
虛擬內(nèi)存: 未關(guān)閉乐纸,大小 9GB

測試注意點(diǎn):

  1. 為了防止 PageCache 緩存的影響,每次都生成一個新的文件進(jìn)行讀取摇予。
  2. 為了測試不同數(shù)據(jù)包對性能的影響汽绢,需要使用不同大小的數(shù)據(jù)包進(jìn)行多次測試。
  3. force 對性能影響很大侧戴,應(yīng)該單獨(dú)測試宁昭。
  4. 使用 1GB 文件進(jìn)行測試(小文件沒有參考意義,大文件 mmap 無法映射)

純粹讀測試

1GB 文件:

測試 MappedByteBuffer & FileChannel & RandomAccessFile & FileInputStream.

大圖

從這張圖里酗宋,我們看到积仗,mmap 性能完勝,特別是在小數(shù)據(jù)量的情況下蜕猫。其他的流寂曹,只有在4kb 的情況下,才開始反殺 mmap回右。因此隆圆,讀 4kb 以下的數(shù)據(jù),請使用 mmap翔烁。

再放大看看 mmap 和 FileChannel 的比較:

縮放圖

根據(jù)上圖渺氧,我們看到,在寫入數(shù)據(jù)包大于 4kb 以上的情況下租漂,F(xiàn)ileChannel 等一眾非零拷貝阶女,基本完勝 mmap颊糜,除了那個一次讀 1G 文件的 BT 測試。

因此秃踩,如果你的數(shù)據(jù)包大于 4kb衬鱼,請使用 FileChannel

純粹寫測試

1GB 文件:

測試 MappedByteBuffer & FileChannel & RandomAccessFile & FileInputStream.

大圖

從上圖憔杨,我們可以看出鸟赫,mmap 性能還是一樣的穩(wěn)定。FileChannel 也不差消别,但是在 32 字節(jié)數(shù)據(jù)量的情況下抛蚤,還差點(diǎn)意思。

再看縮略圖:

寫縮略圖

我們看到寻狂,64字節(jié) 是 FileChannel 和 mmap 性能的分水嶺岁经,從 64字節(jié)開始,F(xiàn)ileChannel 一路反殺蛇券,直到 BT 1GB 文件稍稍輸了一丟丟缀壤。

因此,我們建議:如果你的數(shù)據(jù)包大小在 64 字節(jié)以上纠亚,請使用 FileChannel 寫入塘慕。

異步 force 測試

我們知道,RocketMQ 使用異步刷盤蒂胞,那么異步 force 對性能有沒有影響呢图呢?benchmark everything。我們使用異步線程骗随,每 16kb 刷盤一次蛤织,看看性能如何。

異步刷盤

mmap 一直落后鸿染,且性能很差瞳筏,除了在 2048 字節(jié)那里有一點(diǎn)點(diǎn)抖動,基本維持 在 4000 左右牡昆,而沒有 force 的情況下,則在 1500 左右摊欠。而 FileChannel 則完全不受 force 的影響丢烘。在我的測試中,1GB 的文件些椒,一次 force 需要 800 毫秒左右播瞳。buffer 越大,時(shí)間越多免糕,反之則越小赢乓。

說個題外話忧侧,Kafka 一直不建議使用 force,大概也有這個原因牌芋。當(dāng)然蚓炬,Kafka 還有自己的多副本策略保證數(shù)據(jù)安全。

這里躺屁,我們得出結(jié)論肯夏,如果你需要經(jīng)常執(zhí)行 force,即使是異步的犀暑,也請一定不要使用 mmap驯击,請使用 FileChannel。

總結(jié)耐亏。

基于以上測試徊都,我們得出一張圖表:

假設(shè),我們的系統(tǒng)的數(shù)據(jù)包在 1024 - 2048 左右广辰,我們應(yīng)該使用什么策略暇矫?

答:讀使用 mmap,僅僅寫使用 FileChannel轨域。

再回過頭看看 MQ 的實(shí)現(xiàn)者們袱耽,似乎只有 QMQ 是 這么做的。當(dāng)然干发,RocketMQ 也提供了 FileChannel 的寫選項(xiàng)朱巨。但默認(rèn) mmap 寫加異步刷盤,應(yīng)該是 broker busy 的元兇吧枉长。

而 Kafka冀续,因?yàn)槟J(rèn)不 force,也是使用 FileChannel 進(jìn)行寫入的必峰,為什么使用 FileChannel 讀呢洪唐?大概是因?yàn)橄⒌拇笮≡?4kb 以上吧。

這樣一揣測吼蚁,這些 MQ 的設(shè)計(jì)似乎都非常合理凭需。

最后,能不用 force 就別用 force肝匆。如果要用 force 粒蜈,就請使用 FileChannel。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旗国,一起剝皮案震驚了整個濱河市枯怖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌能曾,老刑警劉巖度硝,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肿轨,死亡現(xiàn)場離奇詭異,居然都是意外死亡蕊程,警方通過查閱死者的電腦和手機(jī)椒袍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來存捺,“玉大人槐沼,你說我怎么就攤上這事“浦危” “怎么了岗钩?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肖油。 經(jīng)常有香客問我兼吓,道長,這世上最難降的妖魔是什么森枪? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任视搏,我火速辦了婚禮,結(jié)果婚禮上县袱,老公的妹妹穿的比我還像新娘浑娜。我一直安慰自己,他們只是感情好式散,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布筋遭。 她就那樣靜靜地躺著,像睡著了一般暴拄。 火紅的嫁衣襯著肌膚如雪漓滔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天乖篷,我揣著相機(jī)與錄音响驴,去河邊找鬼。 笑死撕蔼,一個胖子當(dāng)著我的面吹牛豁鲤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鲸沮,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼畅形,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了诉探?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤棍厌,失蹤者是張志新(化名)和其女友劉穎肾胯,沒想到半個月后竖席,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡敬肚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年毕荐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艳馒。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡憎亚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弄慰,到底是詐尸還是另有隱情第美,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布陆爽,位于F島的核電站什往,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏慌闭。R本人自食惡果不足惜别威,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驴剔。 院中可真熱鬧省古,春花似錦、人聲如沸丧失。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽利花。三九已至科侈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炒事,已是汗流浹背臀栈。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挠乳,地道東北人权薯。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像睡扬,于是被迫代替她去往敵國和親盟蚣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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