FileChannel和MappedByteBuffer

使用内存映射文件可以高效访问文件。下面代码做了一个示例,对比内存映射文件的操作和FileOutputStream写文件的效率差异。

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.RandomAccessFile;

import java.nio.MappedByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.channels.FileChannel.MapMode;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

public class FileClient {

private FileChannel fileChannel;

private MappedByteBuffer mappedByteBuffer;

private File file;

private static int mapedFileSizeCommitLog = 1024 * 1024 * 1024;

private static final String fileName = "D:\\temp\\testfilecache\\a.dat";

private static final String fileName2 = "D:\\temp\\testfilecache\\b.dat";

private static final Logger logger = LoggerFactory.getLogger(FileClient.class.getName());

public static void main(String[] args) throws IOException {

FileClient fclient = new FileClient();

fclient.start();

fclient.start2();

}

@SuppressWarnings("resource")

public void start() throws IOException {

file = new File(fileName);

String testString = "hello";

boolean ok = false;

try {

this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel();

this.mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE, 0, mapedFileSizeCommitLog);

int curPos = 0;

long startTime = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

this.mappedByteBuffer.position(curPos);

this.mappedByteBuffer.put(testString.getBytes());

curPos += 6;

}

this.mappedByteBuffer.force();

this.fileChannel.close();

long stopTime = System.currentTimeMillis();

logger.debug("time :  " + (stopTime - startTime));

ok = true;

} catch (FileNotFoundException e) {

logger.error("create file channel " + fileName + " Failed. ", e);

throw e;

} catch (IOException e) {

logger.error("map file " + fileName + " Failed. ", e);

throw e;

} finally {

if (!ok && this.fileChannel != null) {

this.fileChannel.close();

}

}

}

public void start2() throws IOException {

FileOutputStream fos = new FileOutputStream(fileName2);

String testString = "hello";

long startTime = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

fos.write(testString.getBytes());

}

fos.close();

long stopTime = System.currentTimeMillis();

logger.debug("time2 :  " + (stopTime - startTime));

}

}

服务器sata盘,写入性能:

[[email protected] ~]# dd if=/dev/zero of=kwxgd bs=64k count=4k oflag=dsync

4096+0 records in

4096+0 records out

268435456 bytes (268 MB) copied, 8.93065 seconds, 30.1 MB/s

运行后,可以看到对比结果:

[[email protected] ~]# java -jar filechannel-test.jar

17:56:46.987 [main] DEBUG o.l.filechannel_test.FileClient - time :  207

17:56:48.670 [main] DEBUG o.l.filechannel_test.FileClient - time2 :  1675

性能相差8倍

代码可以从https://github.com/mfcliu/netty-learning下载。

时间: 2024-10-21 23:15:47

FileChannel和MappedByteBuffer的相关文章

同一个主机上的JVM实例之间通信

hadoop yarn里用了RPC调用.NM里面文件本地化类ContainerLocalizer用RPC心跳方式跟本机的ResourceLocalizationService通信. 用shared memory还要调到native层去,不知道会不会比tcp/ip快? 可以用文件,考虑锁的问题.但是文件貌似不能两边一起写,否则会乱的.也许弄两个文件,每个都是单工?这样还要监视文件是否发生变化. 还可以用剪切板,干扰比较严重 可以socket,socket是双工的,读写时都不用加锁防止另一边占用so

RocketMQ 源码分析(二) —— Message 存储

CommitLog 结构 CommitLog.MappedFileQueue.MappedFile 的关系如下: CommitLog : MappedFileQueue : MappedFile = 1 : 1 : N. 反应到系统文件如下: ··· Yunai-MacdeMacBook-Pro-2:commitlog yunai$ pwd /Users/yunai/store/commitlog Yunai-MacdeMacBook-Pro-2:commitlog yunai$ ls -l t

JAVA I/O(三)内存映射文件

<Java编程思想>中对内存映射文件有详细的介绍,此处仅做简单记录和总结.内存映射文件允许创建和修改因为太大而不能放入内存的文件. 1. 内存映射文件简单实例 import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class LargeMappedFiles { priv

消息队列(五)--- RocketMQ-消息存储2

概述 RocketMQ存储中主要用到以下知识点: mmap 文件映射 内存池 异步刷盘 consumeQueue 同时本节将介绍各个重要的类,本篇文章将介绍 mmap 文件映射的相关方法和内存池相关知识点,刷盘和 consumeQueue 相关知识点在下篇介绍. MappedFile mappedFile 对应着底层映射文件,主要的功能是 bytebuffer写入映射文件 回刷回文件 重要字段 public static final int OS_PAGE_SIZE = 1024 * 4; pr

随机访问文件RandomAccessFile 与 内存映射文件MappedByteBuffer

一.RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须是可知的.但是该类仅限于操作文件. RandomAccessFile不属于InputStream和OutputStream类系的.实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系

java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射

java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果文件超大的话,更快的方式是采用MappedByteBuffer. MappedByteBuffer是java nio引入的文件内存映射方案,读写性能极高.NIO最主要的就是实现了对异步操作的支持.其中一种通过把一个套接字通道(SocketChannel)注册到一个选择器(Selector)中,不时调用后者的选择(select)方法就能返回满足的选择键(SelectionKey

MappedByteBuffer高速缓存文件、RandomAccessFile随机访问

说到高速缓存存储,处理读写文件,那就不得不说MappedByteBuffer. 看了好多文章以后写一下自己的总结. 在这里先介绍一下相关的类与方法. 先说一下Buffer.ByteBuffer.MappedByteBuffer这几个类之间的关系. public abstract class Buffer { // Invariants: mark <= position <= limit <= capacity private int mark = -1; private int pos

(转) Java RandomAccessFile与MappedByteBuffer

RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须是可知的.但是该类仅限于操作文件. RandomAccessFile不属于InputStream和OutputStream类系的.实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不

Java NIO Channel之FileChannel [ 转载 ]

Java NIO Channel之FileChannel [ 转载 ] @author zachary.guo 对于文件 I/O,最强大之处在于异步 I/O(asynchronous I/O),它允许一个进程可以从操作系统请求一个或多个 I/O 操作而不必等待这些操作的完成.发起请求的进程之后会收到它请求的 I/O 操作已完成的通知.异步 I/O 是一种高级性能,当前的很多操作系统都还不具备.因此,文件通道在多数情况下来说总是阻塞式的,因此不能被置于非阻塞模式. FileChannel 对象不能