NIO中的内存映射文件使用对效率提高的验证

系统 1491 0

 对比较大的而不能放入内存的文件进行I/O操作时,如果使用NIO中的内存映射文件对性能效率和速度的提高是非常显著的。首先需要获取文件的通道,然后调用通道的map(FileChannel.MapMode mode,long position,long size)函数将文件从position位置开始的长度为size的内容映射到内存中。具体的效率比较代码示例如下:

 

Java代码   收藏代码
  1. import  java.io.BufferedInputStream;  
  2. import  java.io.BufferedOutputStream;  
  3. import  java.io.DataInputStream;  
  4. import  java.io.DataOutputStream;  
  5. import  java.io.FileInputStream;  
  6. import  java.io.FileOutputStream;  
  7. import  java.io.IOException;  
  8. import  java.io.RandomAccessFile;  
  9. import  java.nio.IntBuffer;  
  10. import  java.nio.channels.FileChannel;  
  11.   
  12. //测试代码是借用thingking in java中的   
  13. public   class  MappedIO {  
  14.       
  15.      //先声明需要写入的文件的内容的大小   
  16.      private   static   final   int  NUMOFINT= 4000000 ;  
  17.      private   static   final   int  NUMOFOUT= 2000000 ;  
  18.       
  19.      //测试类,用来测试使用普通的I/O操作和使用内存文件映射时速度的差别   
  20.      abstract   static   class  Tester{  
  21.          private  String name;  
  22.          public  Tester(String name){  
  23.              this .name=name;  
  24.         }  
  25.           
  26.          public   void  runTest(){  
  27.             System.out.println( "使用" +name+ "所消耗的时间:" );  
  28.              try {  
  29.              //以毫微秒为单位获取测试函数开始前的时间   
  30.              long  begin=System.nanoTime();  
  31.               
  32.             test();  
  33.              //将测试函数结束后的系统的时间减去开始之前的时间获取   
  34.              double  duration=System.nanoTime()-begin;  
  35.              //PrintStream中的使用指定格式字符串和参数将格式化字符串写入此输出流中的方法   
  36.             System.out.format( "%.2f\n" , duration/ 1 .0e9);  
  37.             } catch (IOException e){  
  38.                 e.printStackTrace();  
  39.             }  
  40.         }  
  41.           
  42.          //具体的测试函数中其实不仅有对文件进行读取或写入的时间,还包括消耗的各种初始化I/O对象的时间,而且内存映射文件的初始化对象消耗更要比普通的操作大   
  43.          public   abstract   void  test()  throws  IOException;  
  44.     }  
  45.       
  46.      private   static  Tester[] tests={  
  47.          //先使用普通的stream write,并且还是用了Buffered缓冲   
  48.          new  Tester( "stream write" ){  
  49.              public   void  test() throws  IOException{  
  50.                 DataOutputStream dos= new  DataOutputStream( new  BufferedOutputStream( new  FileOutputStream( "baolei.txt" )));   
  51.                  for ( int  i= 0 ;i<NUMOFINT;i++){  
  52.                     dos.writeInt(i);  
  53.                 }  
  54.                 dos.close();  
  55.             }  
  56.         },  
  57.          //使用内存映射文件方式写入文件时的测试内部类   
  58.          new  Tester( "mapped write" ){  
  59.              public   void  test()  throws  IOException{  
  60.                  //利用RandomAccessFile初始化文件获取通道   
  61.                 FileChannel fc= new  RandomAccessFile( "baolei.txt" , "rw" ).getChannel();  
  62.                  //利用IntBuffer基本类型视图缓冲器来修改底层的ByteBuffer,实际上ByteBuffer是将数据移进移出通道的唯一方式   
  63.                 IntBuffer ib=fc.map(FileChannel.MapMode.READ_WRITE,  0 ,fc.size()).asIntBuffer();  
  64.                  for ( int  i= 0 ;i<NUMOFINT;i++){  
  65.                     ib.put(i);  
  66.                 }  
  67.                   
  68.                 fc.close();  
  69.             }  
  70.         },  
  71.           
  72.          //下面的两个测试方法是测试read文件时的速度,基本和上面的两个一样   
  73.          new  Tester( "stream read" ){  
  74.              public   void  test() throws  IOException{  
  75.                 DataInputStream dis= new  DataInputStream( new  BufferedInputStream( new  FileInputStream( "baolei.txt" )));  
  76.                   
  77.                  for ( int  i= 0 ;i<NUMOFOUT;i++){  
  78.                     dis.readInt();  
  79.                 }  
  80.                 dis.close();  
  81.             }  
  82.         },  
  83.          new  Tester( "mapped read" ){  
  84.              public   void  test()  throws  IOException{  
  85.                 FileChannel fc= new  RandomAccessFile( "baolei.txt" , "rw" ).getChannel();  
  86.                 IntBuffer ib=fc.map(FileChannel.MapMode.READ_WRITE,  0 , fc.size()).asIntBuffer();  
  87.                  while (ib.hasRemaining()){  
  88.                     ib.get();  
  89.                 }  
  90.                   
  91.                 fc.close();  
  92.             }  
  93.         }  
  94.   
  95.     };  
  96.       
  97.      public   static   void  main(String[] args){  
  98.          for (Tester test:tests){  
  99.             test.runTest();  
  100.         }  
  101.     }  
  102.   
  103. }  

 

   可以看到运行后的结果如下:

           使用stream write所消耗的时间:
           0.92
          使用mapped write所消耗的时间:
           0.12 
          使用stream read所消耗的时间:
           0.50
         使用mapped read所消耗的时间:
           0.06
    效率确实大幅度提高啊。

NIO中的内存映射文件使用对效率提高的验证


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论