1、文件输入输出流读取文件(fileinputstream、fileoutputstream)
这两个流读取的工具,调用的是native的readBytes和writeBytes,查看这两个native,调用的是io_utils.c下的readBytes和writeBytes,从内核态读取和写入时候,都需要在内存创建一个直接内存区,用来在“堆内存缓冲区”和内核缓冲区之间做中转,大概的逻辑
// 大概是这样,简化了下 buf = malloc(len); // 创建一块内存区域 nread = IO_Read(fd, buf, len); // 读取数据到内存区域 (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf); # 内存复制到java堆
也就是说数据之间的传输是这样的。
read:堆 <- 直接内存 <- PageCache <- 磁盘 write:堆 -> 直接内存 -> PageCache -> 磁盘
总共需要经过6次拷贝,才能完成一次读取和输出;
什么是缓冲区
缓冲区是内存空间的一部分** 。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据 ,这部分预留的空间就叫做缓冲区。** 缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
为什么要引入缓冲区
比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以 减少磁盘的读写次数 ,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度** 。**
又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
缓冲区的类型
缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。
用户内存缓冲区(不是缓存,buffer不是cache)
用户内存缓冲区,也就是进程内存缓冲区
操作系统在读取文件,切换从用户态到内核态时候,需要在读取文件前准备好一个缓冲空间,之后程序读取这个缓冲空间后,再复制到堆内存中。这个就是用户内存空间。在io_utils.c文件读取文件时候,首先做了malloc(len)操作,就是建立用户内存缓冲区。
内核缓冲区
当用户进程要读取磁盘数据时候,通常不会
2、filechannel
Buffers + Cached + SwapCached = Active(file) + Inactive(file) + Shmem + SwapCached
在 Page Cache 中,Active(file)+Inactive(file) 是 File-backed page(与文件对应的内存 页),是你最需要关注的部分。因为你平时用的 mmap() 内存映射方式和 buffered I/O 来消 耗的内存就属于这部分,最重要的是,这部分在真实的生产环境上也最容易产生问题,我们在
接下来的课程案例篇会重点分析它
3、直接IO
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提供的通用化的缓存机制
由于直接IO绕过了cache,因此,申请读写的buffer不能够使用malloc等函数,因为这些函数并不能够实现地址对齐,因此要使用memalign,这里注意,第一个参数必须对齐页大小,是页大小的幂次。
如果使用DIRECT IO进行读取,和写差不多,也要申请对齐的buf。