博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Memory-mapped File IO
阅读量:5955 次
发布时间:2019-06-19

本文共 4253 字,大约阅读时间需要 14 分钟。

转自:

 

建立和使用I/O系统,不管对于哪一种语言都是困难的(在Java中使用I/O库尤其困难)。在Java中,会有多种方式对于文件或者设备进行I /O操作。方法不同,性能很有差异。今天我们来对比一下通过Stream以及Memory-mapped File这两种方式的I/O性能对比。

Stream

“流”是I/O系统中通常使用的抽象概念,表示可以发出或者接受数据的点(source / sink)。“流”的概念也屏蔽掉了不同设备间的细节差异。

Input stream通常可以为:

  • 字节数组
  • String对象
  • 文件
  • 管道(pipe)
  • 其他流(将多个流组成一个流)
  • 网络设备等

Output stream通常可以为:

  • 字节数组
  • 文件
  • 管道

Memory-mapped File

对于那些很大的文件,将整个文件全部读进内存,将会极大地影响性能。通过Memory-mapped File可以只将文件的一部分读入内存,其他部分被换出(swap out),这样就能效率很高的读写大文件。

在Java的nio包中,用到了两种更接近于操作系统具体实现的数据结构:channel和buffer,memory-mapped file中就用到了channel。这种I/O方式,用户不需要跟数据源打交道,而只需把数据放到channel和buffer中,然后再调相应函数就可以了,通过这种“底层”的操作,已得到最大的I/O性能。(这种方式其实就跟C中的read和write一样了)

通过测试程序,我们可以看到两种方式性能的对比:

(注:表格中的文件大小N表示文件中含有N个char,而读写时间为ms)

读写方式 \ 文件大小 10 100 2^10 2^20 2^21 2^22

Stream Write 1.874 1.974 1.828 161.258 368.252 656.428

Memory-mapped File Write 2.5 6.648 1.265 11.774 20.23 46.262

Stream Read 0.122 0.174 0.58 158.352 313.37 627.531

Memory-mapped File Read 0.428 0.463 0.382 10.797 19.381 39.749

可以看到,文件很小时,Memory-mapped方式是没有优势的,而当读写大文件时,优势就十分明显了。

关键代码如下:

public class IOPerComp {     /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        int[] intSizes = {10, 100, 1<<10, 1<<20, 1<<21, 1<<22};        for (int i = 0; i < intSizes.length; i ++)        {            INT_SIZE = intSizes[i];            System.out.println("file size : " + INT_SIZE);            for (Tester tester : tests)            {                tester.runTest();            }            System.gc();            System.out.println("**********************");        }    }     private static final String FILE_LOC = "D:/tmpFile.txt";    private static int INT_SIZE = 1024 * 1024;    private abstract static class Tester {        private String name;        public Tester () {}        public Tester (String name)        {            this.name = name;        }        public void runTest ()        {            System.out.println("name : " + name);            long start = System.nanoTime();            try            {                test();            }            catch (IOException ioe)            {                ioe.printStackTrace();            }            start = System.nanoTime() - start;            System.out.format("time : %.3f\n", start/1.0e6);        }        public abstract void test() throws IOException;    }     private static Tester[] tests= {        new Tester("Stream Write")        {            public void test() throws IOException            {                File f = new File (FILE_LOC);                if ( f.exists() )                    f.delete();                DataOutputStream dos = new DataOutputStream(                        new BufferedOutputStream(                                new FileOutputStream(FILE_LOC)));                for (int i = 0; i < INT_SIZE; i ++)                    dos.writeInt(i);                dos.close();            }        },        new Tester("Mapped Write")        {            public void test() throws IOException            {                FileChannel fc = new RandomAccessFile(FILE_LOC, "rw").getChannel();                IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();                for (int i = 0; i < INT_SIZE; i ++)                    ib.put(i);                fc.close();            }        },        new Tester("Stream Read")        {            public void test() throws IOException            {                DataInputStream dis = new DataInputStream(                        new BufferedInputStream(                                new FileInputStream(FILE_LOC)));                for (int i = 0; i < INT_SIZE; i ++)                {                    dis.readInt();                }                dis.close();            }        },        new Tester("Mapped Read")        {            public void test() throws IOException            {                FileChannel fc = new FileInputStream(FILE_LOC).getChannel();                IntBuffer ib = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).asIntBuffer();                while ( ib.hasRemaining() )                {                    ib.get();                }                fc.close();            }        }    };}

转载于:https://www.cnblogs.com/jxta/archive/2011/09/13/2175105.html

你可能感兴趣的文章
RunLoop--
查看>>
chrome 2行换行省略号 ... text-ellipse
查看>>
C语言第四次作业
查看>>
Java学习-集合的理解
查看>>
iOS验证码倒计时(GCD实现)
查看>>
iOS中的过滤器和正则表达式(NSPredicate,NSRegularExpression)
查看>>
canvas和svg
查看>>
结对:复利美化版
查看>>
HDU_2689_Sort it
查看>>
urllib模块使用笔记
查看>>
mysql 连接慢的问题(超过了1秒)
查看>>
Linux嵌入式GDB调试环境搭建
查看>>
java分析jvm常用指令
查看>>
【Linux】Linux 在线安装yum
查看>>
oracle 管理操作 (转)
查看>>
DEV 等待窗口
查看>>
VS2017发布微服务到docker
查看>>
lombok
查看>>
Dev-FAT-UAT-PRO
查看>>
Android开发学习总结(五)——Android应用目录结构分析(转)
查看>>