zoukankan      html  css  js  c++  java
  • 聊聊 传统IO和网络IO

    IO 模型

    传统 IO读写

           磁盘IO主要的延时是由(以15000rpm硬盘为例): 机械转动延时(机械磁盘的主要性能瓶颈,平均为2ms) + 寻址延时(2~3ms) + 块传输延时(一般4k每块,40m/s的传输速度,延时一般为0.1ms) 决定。(平均为5ms)

     /**
         * 传统的IO读取
         * @param oriStr
         * @param destStr
         */
        public void customRead(String oriStr,String destStr){
            FileInputStream in = null;
            FileOutputStream os = null;
            try {
                in = new FileInputStream(oriStr);
                os = new FileOutputStream(destStr);
                //一次读取1K 数据
                byte[] bytes = new byte[1024];
                while(in.read(bytes)!=-1){
                  os.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    in.close();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        /**
         * 带缓冲区的IO读取
         * @param oriStr
         * @param destStr
         */
        public void bufferRead(String oriStr,String destStr){
            BufferedInputStream in = null;
            BufferedOutputStream os = null;
            try {
                in = new BufferedInputStream(new FileInputStream(oriStr));
                os = new BufferedOutputStream(new FileOutputStream(destStr));
                //一次读取1K 数据
                byte[] bytes = new byte[1024];
                while(in.read(bytes)!=-1){
                    os.write(bytes);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    in.close();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    

         QA  很多人看了上述2段代码后,可能要反驳啦,customRead有缓存啊,不是一次性读取1024个字节到byte数组了吗

         QA  bufferRead 为啥一定比customeRead 速度快

         其实要理解上面2个问题,很简单,

         ①:fileInputStream.read(byte[]) 是一个骗人的方法,他是通过循环操作调用read()方法,每次读取一个字节,然后填满byte数组。

         ②:BufferedInputStream.read(byte[]) 他是预先从磁盘读取最大8K的数据,然后保存在本地的一个叫buf 数组中,后面读取数据的时候直接从这个buf中获取

          fileInputStream 每次从磁盘获取数据,BufferedInputStream 每次才从本地缓存拿数据,一目了然,BufferedInputStream 明显快多啦(源码不是很复杂,有兴趣的朋友可以看看源码就知道啦

       

    网络IO

        网络IO主要延时由: 服务器响应延时 + 带宽限制 + 网络延时 + 跳转路由延时 + 本地接收延时 决定。(一般为几十到几千毫秒,受环境干扰极大),考虑到网络IO瓶颈,就有很多传输模型,BIO,NIO等等 在这些模型中就不得不提 ByteBuffer,

        那ByteBuffer 是啥,其实这个东西经常用在网络传输NIO模型上,网络传输为了提高效率,不可能一个一个在磁盘上读取,那么需要读取一块数据存储到内存里,ByteBuffer(ByteBuffer内部维护一个byte[],是不是很熟悉,这个套路)就是应用缓存,负责在内存中保存读取的那一整块数据

    //伪代码
    public void nioRead() { FileChannel channel=null; try{ RandomAccessFile raf=new RandomAccessFile("src/exp_io.txt","rw"); //获取通道 channel=raf.getChannel(); if(0==raf.length()){ return; } //分配缓存空间 ByteBuffer buffer=ByteBuffer.allocate((int)raf.length()); byte [] bytes=new byte[(int)raf.length()]; //将数据写入缓存 int bytesRead=channel.read(buffer); int i=0; while (bytesRead!=-1){ buffer.flip(); while (buffer.hasRemaining()){ //从缓存读取数据 bytes[i]=buffer.get(); i++; } //将所有未读的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面 //现在向缓存中写入数据时不会覆盖未读的数据 buffer.compact(); bytesRead=channel.read(buffer); } System.out.println(new String(bytes)); }catch (Exception e){ }finally { try{ if (channel!=null){ channel.close(); } }catch (Exception e){ } } }

      

    总结

           java 为提高IO读写的效率,就一个办法,想办法一次性多读取数据,然后缓存起来。其实ByteBuffer 和BufferedInputStream的根本方法都是一致的,就是搞一个本地的应用缓存,来解决IO瓶颈。

           考虑一个问题 ByteBuffer 是堆内分配内存,如果,我直接用堆外内存(减少系统缓存copy到应用缓存中)作为应用缓存,那么能不能提高IO瓶颈。(netty的套路,有兴趣大家可以研究一下哈)

    参考资料

          网络IO和磁盘IO详解 https://www.cnblogs.com/sunsky303/p/8962628.html 

         BufferByte用法小结 https://blog.csdn.net/mrliuzhao/article/details/89453082

  • 相关阅读:
    《JS权威指南学习总结--3.8类型转换》
    php基础-1
    django的url分配和url捕获参数
    Django项目的创建和设计模式
    1.Tensorflow的基本概念:
    linux下安装pycharm
    url参数和字典的相互转化
    MySQL数据库一
    利用伪装文件夹实现对文件的加密-当然如果你懂,这是很好破解的,只是障眼法而已
    数组有N+M个数字, 数字的范围为1 ... N, 打印重复的元素, 要求O(M + N), 不可以用额外的空间
  • 原文地址:https://www.cnblogs.com/huxuhong/p/13405108.html
Copyright © 2011-2022 走看看