RocketMQ 高性能存储

RocketMQ是一款高性能的消息中间件,它利用内存映射文件技术提升效率,避免了通过OS内核缓冲区的额外拷贝,实现了与硬件直接通信。文章详细探讨了内存映射文件相对于直接使用堆外内存的优势,以及标准IO操作与内存映射文件在性能上的差异,揭示了内存映射在处理大文件时的高效性。
摘要由CSDN通过智能技术生成

Rocketmq 是一款高性能的消息中间件。其中,存储文件的方式使用了 内存映射的方式。为什么不直接使用 堆外内存呢?因为 堆外内粗是和 OS 打交道的。而且,通过磁盘控制器读取到的数据先到 内存缓冲区中,然后 JVM 进行才能拿到这些数据。如果使用了 内存映射的方式,可以和硬件直接通信,这个效率不是一般的高啊!!! 

转载:http://blog.csdn.net/fcbayernmunchen/article/details/8635427

Java类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段。本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原理。

在传统的文件IO操作中,我们都是调用操作系统提供的底层标准IO系统调用函数 read()、write() ,此时调用此函数的进程(在JAVA中即java进程)由当前的用户态切换到内核态,然后OS的内核代码负责将相应的文件数据读取到内核的IO缓冲区,然后再把数据从内核IO缓冲区拷贝到进程的私有地址空间中去,这样便完成了一次IO操作。至于为什么要多此一举搞一个内核IO缓冲区把原本只需一次拷贝数据的事情搞成需要2次数据拷贝呢? 我想学过操作系统或者计算机系统结构的人都知道,这么做是为了减少磁盘的IO操作,为了提高性能而考虑的,因为我们的程序访问一般都带有局部性,也就是所谓的局部性原理,在这里主要是指的空间局部性,即我们访问了文件的某一段数据,那么接下去很可能还会访问接下去的一段数据,由于磁盘IO操作的速度比直接访问内存慢了好几个数量级,所以OS根据局部性原理会在一次 read()系统调用过程中预读更多的文件数据缓存在内核IO缓冲区中,当继续访问的文件数据在缓冲区中时便直接拷贝数据到进程私有空间,避免了再次的低效率磁盘IO操作。在JAVA中当我们采用IO包下的文件操作流,如:

[java] view plain copy

01.FileInputStream in = new FileInputStream(“D:\java.txt”);

[java] view plain copy

01.in.read();

JAVA虚拟机内部便会调用OS底层的 read()系统调用完成操作,如上所述,在第二次调用 in.read()的时候可能就是从内核缓冲区直接返回数据了(可能还有经过 native堆做一次中转,因为这些函数都被声明为 native,即本地平台相关,所以可能在C代码中有做一次中转,如 win32中是通过 C代码从OS读取数据,然后再传给JVM内存)。既然如此,JAVA的IO包中为啥还要提供一个 BufferedInputStream 类来作为缓冲区呢。关键在于四个字,”系统调用”!当读取OS内核缓冲区数据的时候,便发起了一次系统调用操作(通过native的C函数调用),而系统调用的代价相对来说是比较高的,涉及到进程用户态和内核态的上下文切换等一系列操作,所以我们经常采用如下的包装:

[java] view plain copy

01.FileInputStream in = new FileInputStream(“D:\java.txt”);

[java] view plain copy

01.BufferedInputStream buf_in = new BufferedInputStream(in);

[java] view plain copy

01.buf_in.read();

这样一来,我们每一次 buf_in.read() 时候,BufferedInputStream 会根据情况自动为我们预读更多的字节数据到它自己维护的一个内部字节数组缓冲区中,这样我们便可以减少系统调用次数,从而达到其缓冲区的目的。所以要明确的一点是 BufferedInputStream 的作用不是减少 磁盘IO操作次数(这个OS已经帮我们做了),而是通过减少系统调用次数来提高性能的。同理 BufferedOuputStream , BufferedReader/Writer 也是一样的。在 C语言的函数库中也有类似的实现,如 fread(),这个函数就是 C语言中的缓冲IO,作用与BufferedInputStream()相同.

这里简单的引用下JDK6 中 BufferedInputStream 的源码验证下:

[java] view plain copy

01.public
02.class BufferedInputStream extends FilterInputStream {
03.
04. private static int defaultBufferSize = 8192;
05.
06. /**
07. * The internal buffer array where the data is stored. When necessary,
08. * it may be replaced by another array of
09. * a different size.
10. */
11. protected volatile byte buf[];

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值