Java文件IO操作教程之DirectIO的意义

发布时间:2020-10-12 20:17:54 作者:徐靖峰
来源:脚本之家 阅读:151

前言

在前文《文件IO操作的一些最佳实践》中,我介绍了一些 Java 中常见的文件操作的接口,并且就 PageCache 和 DIrect IO 进行了探讨,最近我自己封装了一个 Direct IO 的库,趁着这个机会,本文重点谈谈 Java 中 Direct IO 的意义,以及简单介绍下我自己的轮子。

Java 中的 Direct IO

如果你阅读过我之前的文章,应该已经了解 Java 中常用的文件操作接口为:FileChannel,并且没有直接操作 Direct IO 的接口。这也就意味着 Java 无法绕开 PageCache 直接对存储设备进行读写,但对于使用 Java 语言来编写的数据库,消息队列等产品而言,的确存在绕开 PageCache 的需求:

PageCache 可能会好心办坏事,采用 Direct IO + 自定义内存管理机制会使得产品更加的可控,高性能。

Direct IO 的限制

在 Java 中使用 Direct IO 最终需要调用到 c 语言的 pwrite 接口,并设置 O_DIRECT flag,使用 O_DIRECT 存在不少限制

查看系统 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

引入依赖

<dependency>
 <groupId>moe.cnkirito.kdio</groupId>
 <artifactId>kdio-core</artifactId>
 <version>1.0.0</version>
</dependency>

注意事项

// 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

总结

这个简单的 Direct IO 框架参考了smacke/jaydio,这个库自己搞了一套 Buffer 接口跟 JDK 的类库不兼容,且读写实现里面加了一块 Buffer 用于缓存内容至 Block 对齐有点破坏 Direct IO 的语义。同时,感谢尘央同学的指导,这个小轮子的代码量并不多,初始代码引用自他的一个小 demo(已获得本人授权)。为什么需要这么一个库?主要是考虑后续会出现像「中间件性能挑战赛」和「PolarDB性能挑战赛」这样的比赛,Java 本身的 API 可能不足以发挥其优势,如果有一个库可以屏蔽掉 Java 和 CPP 选手的差距,岂不是美哉?我也将这个库发到了中央仓库,方便大家在自己的代码中引用。

后续会视需求,会这个小小的轮子增加注入 fadvise,mmap 等系统调用的映射,也欢迎对文件操作感兴趣的同学一起参与进来,pull request & issue are welcome!

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对亿速云的支持。

推荐阅读:
  1. startupProbe存在的意义是什么?
  2. CocoaPods安装和使用教

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java 文件io directio

上一篇:jquery制作的移动端购物车效果完整示例

下一篇:Python网络编程基于多线程实现多用户全双工聊天功能示例

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》