言
Java 在 JDK 1.4 引入了 ByteBuffer 等 NIO 相關(guān)的類,使得 Java 程序員可以拋棄基于 Stream ,從而使用基于 Block 的方式讀寫文件.
另外,JDK 還引入了 IO 性能優(yōu)化之王—— 零拷貝 sendFile 和 mmap。
但他們的性能究竟怎么樣? 和 RandomAccessFile 比起來,快多少? 什么情況下快?到底是 FileChannel 快還是 MappedByteBuffer 快……
天啊,問題太多了。。。讓我們慢慢分析。
看看善于利用IO零拷貝的MQ們
我們知道,Java世界有很多MQ:ActiveMQ,kafka,RocketMQ,QMQ(去哪兒MQ),他們是使用NIO零拷貝的大戶。
然而,他們的性能卻大相同,拋開其他的因素,例如網(wǎng)絡傳輸方式,數(shù)據(jù)結(jié)構(gòu)設計,文件存儲方式,我們僅僅討論 Broker 端對文件的讀寫,看看他們有什么不同。
下圖是樓主查看源碼總結(jié)的各個 MQ 使用的文件讀寫方式。
那么,到底是 MMAP 強,還是 FileChannel 強?
MMAP 眾所周知,基于 OS 的 mmap 的內(nèi)存映射技術(shù),通過 MMU 映射文件,使隨機讀寫文件和讀寫內(nèi)存相似的速度。
那 FileChannel 呢?是零拷貝嗎?很遺憾,不是。FileChannel 快,只是因為他是基于 block 的。
接下來,benchmark everything —— 徐媽.
Benchmark ?
如何 Benchmark? Benchmark 哪些?
既然是讀寫文件,自然就要看讀寫性能,這是最基本的。
但,注意,通常MQ會使用定時刷盤,防止數(shù)據(jù)丟失,MMAP 和 FileChannel 都有 force 方法,用于將 pageCache 的數(shù)據(jù)刷到硬盤上。
force 會影響性能嗎? 答案是會。影響到什么程度呢? 不知道。
每次寫入的數(shù)據(jù)大小會影響性能嗎,毫無疑問會,但規(guī)則是什么呢?FileOutputStream 真的一無是處嗎?答案是不一定。
一直以來,文件調(diào)優(yōu)都是藝術(shù),因為影響性能的因素太多,首先,SSD 的出現(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)”.
幸運的是,蘋果終于在 2017 年推送了 macOS High Sierra 和 iOS 10.3 系統(tǒng),這個兩個系統(tǒng)都拋棄了 HFS+,換成了性能更高的 APFS。
每個文件系統(tǒng)又可以設置不同的調(diào)度算法,另外,還有虛擬內(nèi)存缺頁中斷帶來的性能毛刺…….
(tips:良心的 RocketMQ 提供了 Linux IO 調(diào)優(yōu)的腳本,這點做的不錯 :)
跑題了。
樓主寫了一個小項目,用于測試 Java MappedByteBuffer & FileChannel & RandomAccessFile & FileXXXputStream 的讀寫性能。大家也可以在自己的機器上跑跑看。
測試環(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
測試注意點:
純粹讀測試
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ù)量的情況下,還差點意思。
再看縮略圖:
我們看到,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é)那里有一點點抖動,基本維持在4000左右,而沒有 force 的情況下,則在 1500 左右。而 FileChannel 則完全不受 force 的影響。
在我的測試中,1GB 的文件,一次 force 需要 800 毫秒左右。buffer 越大,時間越多,反之則越小。
說個題外話,Kafka 一直不建議使用 force,大概也有這個原因。當然,Kafka 還有自己的多副本策略保證數(shù)據(jù)安全。
這里,我們得出結(jié)論,如果你需要經(jīng)常執(zhí)行 force,即使是異步的,也請一定不要使用 mmap,請使用 FileChannel。
總結(jié)
基于以上測試,我們得出一張圖表:
假設,我們的系統(tǒng)的數(shù)據(jù)包在 1024 - 2048 左右,我們應該使用什么策略?
答:讀使用 mmap,僅僅寫使用 FileChannel。
再回過頭看看 MQ 的實現(xiàn)者們,似乎只有 QMQ是這么做的。
當然,RocketMQ 也提供了 FileChannel 的寫選項。但默認 mmap 寫加異步刷盤,應該是 broker busy 的元兇吧。
而 Kafka,因為默認不 force,也是使用 FileChannel 進行寫入的。
為什么使用 FileChannel 讀呢?大概是因為消息的大小在 4kb 以上吧。這樣一揣測,這些 MQ 的設計似乎都非常合理。
最后,能不用 force 就別用 force。如果要用 force ,就請使用 FileChannel。
我一直覺得電腦運行慢,使用各種優(yōu)化軟件也只能治標不治本。如果自己有能力的話,還是盡早升級電腦硬件吧。尤其是SSD固態(tài)硬盤,能顯著提升電腦的讀寫速度。今天在這里分享的這款Process Lasso Pro,看描述挺厲害的,大伙兒可以試試。
資源地址在第一張圖片描述里,有問題可以隨時私信我。
www。lanzous。com。/i91i8of
Process Lasso是一款非常獨特神奇的性能優(yōu)化工具,其核心功能進程平衡器(ProBalance),通過對進程CPU及I/O負載監(jiān)控,超標自動抑制,達到動態(tài)平衡系統(tǒng)負載,讓你再也沒有卡.卡..卡的感覺,適用于WinXP、Vista、Win7、Win8、Win8.1、Win10,,Process Lasso 最獨特的地方在于可以調(diào)整I0和Thread的優(yōu)先級,而不僅僅是CPU的優(yōu)先級,Process Lasso 是世上目前所唯一的一個有這個能力的,Sysinternals的Process Explorer 也只能調(diào)整CPU的優(yōu)先級而已。
Process Tamer等類似的軟件多了去了。甚至于任務管理器手動都可以調(diào)整。運行卡頓,多數(shù)在于硬盤IO能力弱,比如你拷貝大量數(shù)據(jù)的時候,運行程序會相當慢。所以除了把HDD換成SSD以外,最靠譜的就是調(diào)整IO的優(yōu)先級,比如把視頻、音樂播放器,瀏覽器的I0優(yōu)先級調(diào)整到最高。把文件復制之類的IO優(yōu)先級降低,Process Lasso可以實現(xiàn)。程序的Probalance的動態(tài)平衡,默認不會調(diào)整I0優(yōu)先級,需要選項自己開啟Process Lasso在后臺實時智能優(yōu)化您的系統(tǒng),不會自動修改任何系統(tǒng)任何現(xiàn)有的配置,適用于普通家庭用戶和專業(yè)工作環(huán)境以及服務器。它主要功能是基于其特別的算法,動態(tài)調(diào)整各個進程的優(yōu)先級并設為合理的優(yōu)先級,以實現(xiàn)為系統(tǒng)減負的目的,可有效避免藍屏、假死、進程停止響應、進程占用CPU時間過多等癥狀。
設置中文如下
安裝好后,在圖片下按選項打開,選擇Chinese (Simplfied)然后點OK,在重新安裝程序即可顯示中文