【linux】随机读写之DirectIO|MMAP和DIRECT IO区别

本文详细探讨了Linux下的DirectIO技术,解释了其在高性能、内存利用率要求高的场景下如何避免PageCache,提高随机读写效率。DirectIO通过避免PageCache,实现了数据直接写入磁盘,减少了内存拷贝,适用于数据库等场景。同时,文章介绍了内存管理,包括buffercache和pagecache的原理,以及如何通过系统参数调整PageCache。最后,讨论了顺序读写与随机读写的区别,以及如何通过线程同步实现顺序写。

目录

随机读写之DirectIO

MMAP和DIRECT IO区别


随机读写之DirectIO

原文:https://blog.csdn.net/alex_xfboy/article/details/91865675

在上一节中讲过MappedByteBuffer VS FileChannel它们称得上零拷贝技术,但留下了顺序读比随机读快,顺序写比随机写快的问题,在我们的实际应用场景中为了回避随机读写需求,通常的做法都是对其进行文件分片(又将随机变成了有序),而本节借助Direct IO来彻底解决该问题。

注:只有 Linux 系统才支持 Direct IO,还被 Linus 喷过,据说在 Jdk10 发布之后将会得到原生支持

buffered io

普通文件操作,对性能、吞吐量没有特殊要求,由kernel通过page cache统一管理缓存,page cache的创建和回收由kernel控制。

默认是异步写,如果使用sync,则是同步写,保证该文件所有的脏页落盘后才返回(对于db transaction很重要,通过sync保证redo log落盘,从而保证一致性)

mmap 对文件操作的吞吐量、性能有一定要求,且对内存使用不敏感,不要求实时落盘的情况下使用。mmap对比buffered io,可以减少一次从page cache -> user space的内存拷贝,大文件场景下能大幅度提升性能。同时mmap将把文件操作转换为内存操作,避免lseek。通过msync回写硬盘(此处只说IO相关的应用,抛开进程内存共享等应用)。
direct io

性能要求较高、内存使用率也要求较高的情况下使用。

适合DB场景,DB会将数据缓存在自己的cache中,换入、换出算法由DB控制,因为DB比kernel更了解哪些数据应该换入换出,比如innodb的索引,要求常驻内存,对于redo log不需要重读读写,更不要page cache,直接写入磁盘就好。

顺序读写 & 随机读写

定义不难理解,其实就是要有序,不要随机切换位置,比如:

thread1:write position[0~4096)
thread2:write position[4096~8194)
而非
thread1:write position[0~4096)
thread3:write position[8194~12288)
thread2:write position[4096~8194)

ExecutorService executor = Executors.newFixedThreadPool(64);
AtomicLong position = new AtomicLong(0);
//并发写(达到随机写的描述)
for(int i=0;i<1024;i++){
    final int index = i;
    executor.execute(()->{
        fileChannel.write(ByteBuffer.wrap(new byte[4*1024]),position.getAndAdd(4*1024));
    })
}
//加锁保证了顺序写
for(int i=0;i<1024;i++){
    final int index = i;
    executor.execute(()->{
        write(new byte[4*1024]);
    })
}
public synchronized void write(byte[] data){
    fileChannel.write(ByteBuffer.wrap(new byte[4*1024]),position.getAndAdd(4*1024));
}

思考:顺序写为什么比随机写要快?

这正是page cache在起作用!

disk cache分为两种:

1)buffer cache以块为单位,缓存裸分区中的内容,(如super block、inode)。

2)page cache是以页为单位缓存分区中文件的内容(通常为4K) ,它是位于 application buffer(用户内存)和 disk file(磁盘)之间的一层缓存。

linux2.4中,两者是并存的,但会造成mmap情况下,同一份数据会在两个cache空间内存在,造成空间浪费,在linux2.6中,两者合并,buffer cache也使用page cache的数据结构,只是在free统计内存时,会把page cache中缓存裸分区的部分统计为buffer cache。

当用户发起一个 fileChannel.read(4kb) 时:

  1. 操作系统从磁盘加载了磁盘块(block) 16kb进入 PageCache,这被称为预读(为了减少实际磁盘IO)
  2. 应用程序(application buffer)操作(read)其实是从 PageCache 拷贝 4kb 进
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值