前言
公司主營業(yè)務(wù):網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)公司是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)公司推出洛陽免費做網(wǎng)站回饋大家。
在前文《文件IO操作的一些最佳實踐》中,我介紹了一些 Java 中常見的文件操作的接口,并且就 PageCache 和 DIrect IO 進行了探討,最近我自己封裝了一個 Direct IO 的庫,趁著這個機會,本文重點談?wù)?Java 中 Direct IO 的意義,以及簡單介紹下我自己的輪子。
Java 中的 Direct IO
如果你閱讀過我之前的文章,應(yīng)該已經(jīng)了解 Java 中常用的文件操作接口為:FileChannel,并且沒有直接操作 Direct IO 的接口。這也就意味著 Java 無法繞開 PageCache 直接對存儲設(shè)備進行讀寫,但對于使用 Java 語言來編寫的數(shù)據(jù)庫,消息隊列等產(chǎn)品而言,的確存在繞開 PageCache 的需求:
PageCache 可能會好心辦壞事,采用 Direct IO + 自定義內(nèi)存管理機制會使得產(chǎn)品更加的可控,高性能。
Direct IO 的限制
在 Java 中使用 Direct IO 最終需要調(diào)用到 c 語言的 pwrite 接口,并設(shè)置 O_DIRECT flag,使用 O_DIRECT 存在不少限制
查看系統(tǒng) blockSize 大小的方式:stat /boot/|grep “IO Block”
ubuntu@VM-30-130-ubuntu:~$ stat /boot/|grep “IO Block”
Size: 4096 Blocks: 8 IO Block: 4096 directory通常為 4kb
Java 使用 Direct IO
項目地址
https://github.com/lexburner/kdio
引入依賴
moe.cnkirito.kdio kdio-core 1.0.0
注意事項
// file path should be specific since the different file path determine whether your system support direct io public static DirectIOLib directIOLib = DirectIOLib.getLibForPath("/"); // you should always write into your disk the Integer-Multiple of block size through direct io. // in most system, the block size is 4kb private static final int BLOCK_SIZE = 4 * 1024;
Direct IO 寫
private static void write() throws IOException { if (DirectIOLib.binit) { ByteBuffer byteBuffer = DirectIOUtils.allocateForDirectIO(directIOLib, 4 * BLOCK_SIZE); for (int i = 0; i < BLOCK_SIZE; i++) { byteBuffer.putInt(i); } byteBuffer.flip(); DirectRandomAccessFile directRandomAccessFile = new DirectRandomAccessFile(new File("./database.data"), "rw"); directRandomAccessFile.write(byteBuffer, 0); } else { throw new RuntimeException("your system do not support direct io"); } }
Direct IO 讀
public static void read() throws IOException { if (DirectIOLib.binit) { ByteBuffer byteBuffer = DirectIOUtils.allocateForDirectIO(directIOLib, 4 * BLOCK_SIZE); DirectRandomAccessFile directRandomAccessFile = new DirectRandomAccessFile(new File("./database.data"), "rw"); directRandomAccessFile.read(byteBuffer, 0); byteBuffer.flip(); for (int i = 0; i < BLOCK_SIZE; i++) { System.out.print(byteBuffer.getInt() + " "); } } else { throw new RuntimeException("your system do not support direct io"); } }
主要 API
總結(jié)
這個簡單的 Direct IO 框架參考了smacke/jaydio,這個庫自己搞了一套 Buffer 接口跟 JDK 的類庫不兼容,且讀寫實現(xiàn)里面加了一塊 Buffer 用于緩存內(nèi)容至 Block 對齊有點破壞 Direct IO 的語義。同時,感謝塵央同學(xué)的指導(dǎo),這個小輪子的代碼量并不多,初始代碼引用自他的一個小 demo(已獲得本人授權(quán))。為什么需要這么一個庫?主要是考慮后續(xù)會出現(xiàn)像「中間件性能挑戰(zhàn)賽」和「PolarDB性能挑戰(zhàn)賽」這樣的比賽,Java 本身的 API 可能不足以發(fā)揮其優(yōu)勢,如果有一個庫可以屏蔽掉 Java 和 CPP 選手的差距,豈不是美哉?我也將這個庫發(fā)到了中央倉庫,方便大家在自己的代碼中引用。
后續(xù)會視需求,會這個小小的輪子增加注入 fadvise,mmap 等系統(tǒng)調(diào)用的映射,也歡迎對文件操作感興趣的同學(xué)一起參與進來,pull request & issue are welcome!
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。