内存映射文件

1.简介

内存映射文件,机器学习读大文件时可用,效率比传统IO要高。

用于内存映射文件的这部分内存,在Java的堆空间以外。

常见nio相关类见《 java NIO》,http://blog.csdn.net/chuchus/article/details/51886586  。

1.1 传统读写

在传统的文件IO中,底层是类似C语言的read()、write()操作 ,操作系统  由当前的【用户态】切换到【内核态】,然后读数据至【OS缓冲区】,再拷贝到【进程的私有地址空间】中去,这样便完成了一次IO操作。

问:为什么要多此一举搞一个内核IO缓冲区把原本只需一次拷贝数据的事情搞成需要2次数据拷贝呢?
答:根据程序访问的局部性原理,这么做是为了减少磁盘的IO操作。当继续访问的文件数据在OS缓冲区时,便直接拷贝数据到进程私有空间,避免了再次的低效率磁盘IO操作。

问:既然如此,JAVA的IO包中为啥还要提供一个 BufferedInputStream 类来作为缓冲区呢?
答:当读取OS内核缓冲区数据的时候,便发起了一次系统调用操作(通过native的C函数调用),而系统调用的代价相对来说是比较高的,涉及到进程用户态和内核态的上下文切换等一系列操作。
BufferedInputStream 会根据情况自动为我们预读更多的字节数据到它自己维护的一个内部字节数组缓冲区中,这样我们便可以减少系统调用次数,从而达到其缓冲区的目的。

1.2 内存映射

内存映射文件和之前说的 标准IO操作最大的不同之处就在于它虽然最终也是要从磁盘读取数据,但是它并不需要将数据读取到OS内核缓冲区,而是直接将进程的用户私有地址空间中的一部分区域与文件对象建立起映射关系,就好像直接从内存中读、写文件一样,速度当然快了。

2.相关类

java.nio.MappedByteBuffer

一个直接的字节缓冲,内容是一个文件的内存映射区域。 

MappedByteBuffer java.nio.channels.FileChannel.map(MapMode mode, long position, long size) 

将当前文件的一部分直接映射到内存。size为要映射部分的大小。

2.1 映射模式

java.nio.channels.FileChannel.MapMode

映射模式的枚举。

java.nio.channels.FileChannel.MapMode.READ_ONLY

只读。

java.nio.channels.FileChannel.MapMode.READ_WRITE

读写。

java.nio.channels.FileChannel.MapMode.PRIVATE

copy-on-write模式。

专用模式采用的是OS的“写时拷贝”原则,即在没有发生写操作的情况下,多个进程之间都是共享文件的同一块物理内存(进程各自的虚拟地址指向同一片物理地址)。一旦某个进程进行写操作,那么将会把受影响的文件数据单独拷贝一份到进程的私有缓冲区中,不会反映到物理文件中去。

3.例子

1G文件的读写,都在1秒以内。

实际使用中,用完FileChannel后必须将其关闭。

时间: 2024-10-01 23:15:08

内存映射文件的相关文章

汇编教程之内存映射文件

本课中我们将要讲解内存映射文件并且演示如何运用它.您将会发现使用内存映射文件是非常简单的. 理论: 如果您仔细地研究了前一课的例子, 就会发现它有一个严重的缺陷:如果您想读的内容大于系统分配的内存块怎么办?如果您想搜索的字符串刚好超过内存块的边界又该如何处理?对于第一个问题,您也许会说,只要不断地读就不解决了吗.至于第二个问题,您又会说在内存块的边界处做一些特别的处理,譬如放上一些标志位就可以了.原理上确实是行得通,但是这随问题复杂程度加深而显得非常难以处理.其中的第二个问题是有名的边界判断问题

内存映射文件原理及实例

本课中我们将要讲解内存映射文件并且演示如何运用它.您将会发现使用内存映射文件是非常简单的. 理论:如果您仔细地研究了前一课的例子, 就会发现它有一个严重的缺陷:如果您想读的内容大于系统分配的内存块怎么办?如果您想搜索的字符串刚好超过内存块的边界又该如何处理?对于第一个问题,您也许会说,只要不断地读就不解决了吗.至于第二个问题,您又会说在内存块的边界处做一些特别的处理,譬如放上一些标志位就可以了.原理上确实是行得通,但是这随问题复杂程度加深而显得非常难以处理.其中的第二个问题是有名的边界判断问题,

VC++中使用内存映射文件处理大文件

摘要:本文给出了一种方便实用的解决大文件的读取.存储等处理的方法,并结合相关程序代码对具体的实现过程进行了介绍. 引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile().ReadFile()和MFC提供的CFile类等.一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB.几百GB.乃至几TB的海量存储,再以通常的文件处理方法进行处理

内存映射文件怎么处理文件???

问题描述 内存映射文件怎么处理文件??? 内存映射文件可以逐字节的处理文本吗??我原先用普通的打开文件的方式逐字节的读取文本,但是当文件很大的时候运行速度十分慢,上网查了一下内存映射文件可以处理超大文本,效率很高,但是不知道它怎么处理的?我是想逐字节的读取内容的??请大家帮忙解答一下!!谢谢! 解决方案 用内存映射文件读取大型文件

使用内存映射文件来提高你程序的性能

本人在学习<WINDOWS核心编程>的时候对JEFFREY大师提到的一个小程序写了两个版本来比较性能,该程序的原始需求是这样的:对一个大文件进行倒序,也就是将一个文件头变成尾,尾变成头. 使用的方法有很多种,这里使用两个方法来比较,主要是突出使用内存映射文件好处:两种方法为:内存映射文件方法,I/O读写的缓存办法. 第一种办法是创建内存映射文件对象,然后将该对象映射到进程的地址空间中,再读取文件内容,然后倒序,再写入文件. 第二中方法是,将文件内容读入一个大的缓冲区,然后倒序,再写入文件,中间

《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一2.6.1 内存映射文件的性能

2.6.1 内存映射文件的性能 在本节的末尾,你可以发现一个计算传统的文件输入和内存映射文件的CRC32校验和的程序.在同一台机器上,我们对JDK的jre/lib目录中的37MB的rt.jar文件用不同的方式来计算校验和,记录下来的时间数据如表2-5 所示. 正如你所见,在这台特定的机器上,内存映射比使用带缓冲的顺序输入要稍微快一点,但是比使用RandomAccessFile快很多. 当然,精确的值因机器不同会产生很大的差异,但是很明显,与随机访问相比,性能提高总是很显著的.另一方面,对于中等尺

java 深入理解内存映射文件原理_Android

内存映射文件原理 首先说说这篇文章要解决什么问题? 1.虚拟内存与内存映射文件的区别与联系. 2.内存映射文件的原理. 3.内存映射文件的效率. 4.传统IO和内存映射效率对比. 虚拟内存与内存映射文件的区别与联系 二者的联系 虚拟内存和内存映射文件都是将一部分内容加载到,另一部分放在磁盘上的一种机制,二者都是应用程序动态性的基础,由于二者的虚拟性,对于用户都是透明的. 虚拟内存其实就是硬盘的一部分,是计算机RAM与硬盘的数据交换区,因为实际的物理内存可能远小于进程的地址空间,这就需要把内存中暂

《windows核心编程》 17章 内存映射文件

内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以避免直接对文件IO操作和对文件内存进行缓存 进程间通讯 17.1 映射到内存的可执行文件和DLL 当一个线程调用CreateProcess的时候,系统会执行收入步骤: 1.判断exe位置,如果无法找到exe那么不会创建进程,这时会CreateProcess返回FALSE 2.创建一个新的进程内核对象

c++-求教!通过内存映射,实现生成的数组存储到文件中,显示出来头100个数?

问题描述 求教!通过内存映射,实现生成的数组存储到文件中,显示出来头100个数? 我目前就了解个大概,现在我不明白const DWORD mmf_size = 512*1024;//?这个地方不懂 ,这个原来的代码部分,我拿别人的代码改的,增加了自己的double的动态数组SigNRead,这个怎么弄 我就想实现,通过内存映射 实现写入 读取 double数组 数组有 1列 90000行个double数组成. #include #include #include #include #define