DirectIO(O_DIRECT) 详解
什么是DirectIO
DirectIO也叫无缓冲IO,裸IO(rawIO),意思是使用无缓冲IO对文件进行读写,不会经过OS Cache。
通常,我们使用的文件流读取、内存映射都属于Cache IO,因为将数据写入文件,首先会写入cache,最终再落盘到IO device 或者称为 disk上。cache IO使得我们在写入、读取(预读取、顺序读取等特性)文件数据的时候,性能得以提升,能够从cache(内存)中读取数据。
直接IO,则是直接将数据写入文件、或者从文件中读取出来,绕过了cache,这使得看起来性能没那么好,但是,仔细分析,无论哪种IO方式,最终数据都必须落盘,而两种的区别在于有无OS cache。
OS cache提供的预读取、顺序读取等特性,这些特性并不适用于所有的场景,比如数据库,数据库通常都有自己的一套缓存机制,就像mysql的innodb存储引擎,它有自己的缓存页,有自己的落盘机制,如果不使用directIO,这明显就会存在双重的cache,一个是OS设计的,一个是DB设计的,而通常,DB需要更加符合自己使用的cache机制,而非OS提供的通用化的缓存机制。
如何使用DirectIO
使用直接IO进行数据的写入
//d io
#include <fcntl.h>
#include <malloc.h>
#include <iostream>
#define _GNU_SOURCE //测试宏
void rawIO() {
int fd;
size_t length;
char *buf;
length = getpagesize() * 1024*16;
cout << "page size:" << getpagesize() << endl;
fd = open("/home/out.log", O_RDWR | O_APPEND | O_DIRECT);//选用了centos系统作为实验平台
if (fd == -1) {
printf("%s", strerror(errno));
exit(-1);
}
//函数:void * memalign (size_t boundary, size_t size)
//函数memalign将分配一个由size指定大小,地址是boundary的倍数的内存块。参数boundary必须是2的幂!
// 函数memalign可以分配较大的内存块,并且可以为返回的地址指定粒度。
//函数:void * valloc (size_t size)
//使用函数valloc与使用函数memalign类似,函数valloc的内部实现里,使用页的大小作为对齐长度,使用memalign来分配内存。它的实现如下所示:
//void *
//valloc (size_t size)
//{
//return memalign (getpagesize (), size);
//}
buf = (char *) memalign(getpagesize(), length);
if (buf == nullptr) {
printf("%s", strerror(errno));
exit(1);
}
for (int i = 0; i < length; i++) {
buf[i] = 'a';
}
int ret = write(fd, (void *) buf, length);
if (ret == -1) {
std::cout << "write fail" << std::endl;
printf("%s \n", strerror(errno));
}
free(buf);
}
由于直接IO绕过了cache,因此,申请读写的buffer不能够使用malloc等函数,因为这些函数并不能够实现地址对齐,因此要使用memalign,这里注意,第一个参数必须对齐页大小,是页大小的幂次。
如果使用DIRECT IO进行读取,和写差不多,也要申请对齐的buf。
DirectIO的性能
为了测试直接IO的性能,这里使用常规的写(不手动落盘)、手动落盘、自动落盘、直接IO的耗时比较,测试变量:
写入:4096* 1024*16 字节的耗时如下:
raw IO elapse ms:862
raw IO elapse us:862723
cache IO 手动 elapse ms:908
cache IO 手动 elapse us:908871
cache IO 自动 elapse ms:885
cache IO 自动 elapse us:885480
cache IO elapse ms:297
cache IO elapse us:297153
可以看出,实际落盘的时间都是差不多的,而写OS Cache,在不立即落盘的情况下,是最快的。
DirectIO的应用
- 数据库