NIO中FileChannel和MappedByteBuffer原理和性能对比

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

mmap(Memory Mapped Files),简单描述其作用就是:将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件。
它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
通过mmap,进程像读写硬盘一样读写内存(当然是虚拟机内存),也不必关心内存的大小有虚拟内存为我们兜底。使用这种方式可以获取很大的I/O提升,省去了用户空间到内核空间复制的开销。
mmap也有一个很明显的缺陷——不可靠,写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘。

benchmark比较:

小数据量测试,每次32byte

FileChannel的性能

/*
 @author:   chenyang
 @date  2019/11/10 12:10 AM

*/

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

你可能感兴趣的:(NIO中FileChannel和MappedByteBuffer原理和性能对比)