天天看点

java filechannel 性能_NIO中FileChannel和MappedByteBuffer原理和性能对比

MappedByteBuffer实现MMAP(Memory Mapped Files)技术(内存映射)

mmap(Memory Mapped Files),简单描述其作用就是:将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件。

它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。

通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),也不必关心内存的大小有虚拟内存为我们兜底。使用这种方式可以获取很大的I/O提升,省去了用户空间到内核空间复制的开销。

mmap也有一个很明显的缺陷——不可靠,写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。

benchmark比较:

小数据量测试,每次32byte

FileChannel的性能

import java.io.RandomAccessFile;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

public class NormalNio {

RandomAccessFile aFile;

FileChannel inChannel;

public NormalNio() throws Exception{

this.aFile = new RandomAccessFile("/Users/chenyang/data/nio-data.txt", "rw");

this.inChannel = aFile.getChannel();

}

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

NormalNio normalNio=new NormalNio();

long start= System.currentTimeMillis();

for(int k=0;k<100;k++) {//100*1024*1024=100m

System.out.println(k);

for (int i = 0; i < 1024; i++) {//1024*1024=1m

for (int j = 0; j < 32; j++) {//1024

normalNio.writeFile();

}

}

}

System.out.println("执行时间:"+(System.currentTimeMillis()-start)/1000);

normalNio.inChannel.close();

}

private void writeFile() throws Exception{

inChannel.position(aFile.length());

String newData = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;

byte[] bytes=newData.getBytes();

ByteBuffer buf = ByteBuffer.allocate(48);

buf.put(bytes);

buf.flip();

while (buf.hasRemaining()) {

inChannel.write(buf);

}

}

}

响应时间:25s

MappedByteBuffer(MMAP)的性能:

import java.io.RandomAccessFile;

import java.nio.MappedByteBuffer;

import java.nio.channels.FileChannel;

public class MappedByteBufferNio {

RandomAccessFile aFile;

FileChannel inChannel;

MappedByteBuffer mappedByteBuffer;

public MappedByteBufferNio() throws Exception{

this.aFile = new RandomAccessFile("/Users/chenyang/data/nio-data.txt", "rw");

this.inChannel = aFile.getChannel();

//将文件的前 100*1024*1024 个字节映射到内存中

this.mappedByteBuffer=inChannel.map(FileChannel.MapMode.READ_WRITE,0,100*1024*1024);

}

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

MappedByteBufferNio mappedByteBufferNio=new MappedByteBufferNio();

long start= System.currentTimeMillis();

for(int k=0;k<100;k++) {//100*1024*1024=100m

System.out.println(k);

for (int i = 0; i < 1024; i++) {//1024*1024=1m

for (int j = 0; j < 32; j++) {//1024

mappedByteBufferNio.writeFile();

}

}

}

System.out.println("执行时间:"+(System.currentTimeMillis()-start)/1000);

mappedByteBufferNio.inChannel.close();

mappedByteBufferNio.aFile.close();

}

private void writeFile() throws Exception{

inChannel.position(aFile.length());

String newData = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;//32 byte

byte[] bytes=newData.getBytes();

mappedByteBuffer.put(bytes);

}

}

响应时间:6s