MappedByteBuffer
计算机内存管理
原文链接 https://www.cnblogs.com/guozp/p/10470431.html
MMC:CPU的内存管理单元。
物理内存:即内存条的内存空间。
虚拟内存:计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
页面文件:操作系统反映构建并使用虚拟内存的硬盘空间大小而创建的文件,在windows下,即pagefile.sys文件,其存在意味着物理内存被占满后,将暂时不用的数据移动到硬盘上。
缺页中断:当程序试图访问已映射在虚拟地址空间中但未被加载至物理内存的一个分页时,由MMC发出的中断。如果操作系统判断此次访问是有效的,则尝试将相关的页从虚拟内存文件中载入物理内存。
MappedByteBuffer介绍
MappedByteBuffer 是Java NIO中引入的一种硬盘物理文件和内存映射方式,当物理文件较大时,采用MappedByteBuffer,读写性能较高,其内部的核心实现是DirectByteBuffer(JVM 堆外直接物理内存)。
JVM 进程通过内存映射方式加载的物理文件并不会耗费同等大小的物理内存。当应用程序访问数据时,程序通过虚拟地址寻址对应的内存页,如果物理内存中不存在对应页,MMU则会产生缺页中断异常,CPU尝试从系统Swap分区中查找,如仍不存在,则会直接从硬盘中物理文件中读取。
传统的基于文件流的方式读取文件方式是系统指令调用,文件数据首先会被读取到进程的内核空间的缓冲区,而后复制到进程的用户空间,这个过程中存在两次数据拷贝;而内存映射方式读取文件的方式,也是系统指令调用,在产生缺页中断后,CPU直接从磁盘文件load数据到进程的用户空间,只有一次数据拷贝。
FileChannel提供了map方法把磁盘文件映射到虚拟内存,通常情况可以映射整个文件,如果文件比较大,可以进行分段映射。
内存映像文件访问的方式,共三种:
a) MapMode.READ_ONLY:只读,试图修改得到的缓冲区将导致抛出异常。
b) MapMode.READ_WRITE:读/写,对得到的缓冲区的更改最终将写入文件;但该更改对映射到同一文件的其他程序不一定是可见的。
c) MapMode.PRIVATE:私用,可读可写,但是修改的内容不会写入文件,只是buffer自身的改变。
MappedByteBuffer在处理大文件时的确性能很高,但也存在一些问题,其所对应的内存使用的是JVM堆外内存,JVM young gc和CMS gc并不能触发回收MappedByteBuffer对应的内存,只有full gc(stop the world的方式)可以使其回收内存,堆外直接内存会根据自己的情况(当需要新分配直接内存时,如果所剩堆外内存空间不够,第一次产生OutOfMemoryError时)来触发 System.gc(),此处有坑,若JVM配置了参数-XX:DisableExplicitGC,System.gc()将不会触发full gc,最终导致内存泄漏。而且触发其内存回收的时间点是不确定的。Java api文档中标注:
A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.
在应用程序频繁使用堆外内存时,还可以通过-XX:MaxDirectMemorySize来指定最大的堆外内存大小,当使用达到了阈值的时候将调用System.gc来做一次full gc,以此来回收掉游离状态的堆外内存。
因此,在使用堆外内存高性能的福利的同时,及时的回收掉废弃掉的内存是十分关键的。
性能分析
从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。
但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么?
read()是系统调用,首先将文件从硬盘拷贝到内核空间的一个缓冲区,再将这些数据拷贝到用户空间,实际上进行了两次数据拷贝;
map()也是系统调用,但没有进行数据拷贝,当缺页中断发生时,直接将文件从硬盘拷贝到用户空间,只进行了一次数据拷贝。
所以,采用内存映射的读写效率要比传统的read/write性能高。
总结
MappedByteBuffer使用虚拟内存,因此分配(map)的内存大小不受JVM的-Xmx参数限制,但是也是有大小限制的。
如果当文件超出1.5G限制时,可以通过position参数重新map文件后面的内容。
MappedByteBuffer在处理大文件时的确性能很高,但也存在一些问题,如内存占用、文件关闭不确定,被其打开的文件只有在垃圾回收的才会被关闭,而且这个时间点是不确定的。
javadoc中也提到:A mapped byte buffer and the file mapping that it represents remain* valid until the buffer itself is garbage-collected.
原文链接 https://www.cnblogs.com/guozp/p/10470431.html
MappedByteBuffer的更多相关文章
- Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比
目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码. pack ...
- Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer
Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer 1. Java NIO(New Input/Output)1 1.1. 变更通知(因为每个事件都需要一个监听者 ...
- Java NIO教程 MappedByteBuffer
之前跟大家说过,要讲MappedByteBuffer,现在我来履行承诺了. 首先从大体上讲一下MappedByteBuffer究竟是什么.从继承结构上来讲,MappedByteBuffer继承自Byt ...
- MappedByteBuffer读写文件
一. MappedByteBuffer java把文件映射到内存中,避免堆内存产生大对象引起full gc.mappedByteBuffer的读写速度都要超过堆内读写文件的速度 public clas ...
- RandomAcessFile、MappedByteBuffer和缓冲读/写文件
项目需要进行大文件的读写,调查测试的结果使我决定使用MappedByteBuffer及相关类进行文件的操作,效果不是一般的高. 网上参考资源很多,如下两篇非常不错: 1.花1K内存实现高效I/O的Ra ...
- MappedByteBuffer高速缓存文件、RandomAccessFile随机访问
说到高速缓存存储,处理读写文件,那就不得不说MappedByteBuffer. 看了好多文章以后写一下自己的总结. 在这里先介绍一下相关的类与方法. 先说一下Buffer.ByteBuffer.Map ...
- Java NIO之内存映射文件——MappedByteBuffer
大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...
- Kafka-4614问题复盘 (MappedByteBuffer未关闭导致慢磁盘访问)
很早之前就想动笔就这个kafka bug总结一番了,只是这个问题既不是本人发现,也不是自己动手修复,终归是底气不足,故而一直耽搁下来.怎奈此问题实在是含金量十足,又恰逢最近有人询问Kafka 0.10 ...
- Java RandomAccessFile与MappedByteBuffer
Java RandomAccessFile与MappedByteBuffer https://www.cnblogs.com/guazi/p/6838915.html
随机推荐
- 【转】linux系统中如何进入退出vim编辑器,方法及区别
在linux家族中,vim编辑器是系统自带的文本编辑器,其功能强大自不必说了. 偶有小白,刚接触linux,要修改某个文本文件,不可能像WINDOWS那样操作,更有甚者,进入VI编辑器后,无法退出以致 ...
- Android UI性能优化实战 识别绘制中的性能问题
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/45556391: 本文出自:[张鸿洋的博客] 1.概述 2015年初google ...
- windows命令中的cd
cd命令的作用为改变文件夹,也就是跳转目录.切换路径的意思.它后面可以接驱动器符号.完整路径和相对路径. 打开命令行窗口的时候,默认的目录位于当前用户所在的路径下,比如:C:\Users\koi\De ...
- canvas绘制形状
栅格 之前简单模板中有个宽/高150px的canvas元素.如下图所示,canvas元素默认被网格所覆盖.通常来说网格中的一个单元相当于canvas元素中的一像素.栅格的起点为左上角(坐标为(0,0) ...
- [转]树莓派.设置自动重连WiFi
由于不可知的原因,有可能会导致树莓派失去连接,这时候需要重新连接WiFi. 自动重连的原理是,定期查看是否断网,如果断网了重启WiFi,参考的文章是这篇,第一步略有修改. 1.Python 代码 au ...
- 用ASP.NET Core 2.0 建立规范的 REST API -- GET 和 POST
本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314 ...
- Loadrunner下载脚本
由于最近又在SGM做性能测试,扒拉出一篇去年5.6月份的一个脚本. 最近写的翻来看看其实也蛮简单的,还是就不放博客了. Action(){ //定义文件大小 int flen; //定义响应数据内容大 ...
- 关于Python元祖,列表,字典,集合的比较
定义 方法 列表 可以包含不同类型的对象,可以增减元素,可以跟其他的列表结合或者把一个列表拆分,用[]来定义的 eg:aList=[123,'abc',4.56,['inner','list'], ...
- Maven安装教程详解
一.准备工作 1.确定电脑上已经成功安装jdk7.0以上版本 2.win10操作系统 3.maven安装包 下载地 ...
- React 中阻止事件冒泡的问题
在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达 ...