zoukankan      html  css  js  c++  java
  • 什么是Scatter/Gather?

    scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道;

    scatter(分散):指的是从通道中读取数据分散到多个缓冲区Buffer的过程,该过程会将每个缓存区填满,直至通道中无数据或缓冲区没有空间;

    gather(聚集):指的是将多个缓冲区Buffer聚集起来写入到通道的过程,该过程类似于将多个缓冲区的内容连接起来写入通道;

    scatter/gather接口

    如下是ScatteringByteChannel接口和GatheringByteChannel接口的定义,我们可以发现,接口中定义的方法都传入了一个Buffer数组;

    所谓的scatter/gather操作就是聚集(gather)这个Buffer数组并写入到一个通道,或读取通道数据并分散(scatter)到这个Buffer数组中;

     
    public interface ScatteringByteChannel extends ReadableByteChannel
    {
        public long read(ByteBuffer[] dsts) throws IOException;
    
        public long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
    }
    
    public interface GatheringByteChannel extends WritableByteChannel
    {
        public long write(ByteBuffer[] srcs) throws IOException;
    
        public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
    }
     

    提醒下,带offset和length参数的read( ) 和write( )方法可以让我们只使用缓冲区数组的子集,注意这里的offset指的是缓冲区数组索引,而不是Buffer数据的索引,length指的是要使用的缓冲区数量;

    如下代码,将会往通道写入第二个、第三个、第四个缓冲区内容;

    int bytesRead = channel.write (fiveBuffers, 1, 3);

    注意,无论是scatter还是gather操作,都是按照buffer在数组中的顺序来依次读取或写入的;

    gather写入

    scatter / gather经常用于需要将传输的数据分开处理的场合,下面我们看一下一个聚集写入的示例:

     
    
    
    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(1024);
    
    //write data into buffers
    
    ByteBuffer[] bufferArray = { header, body };
    
    channel.write(bufferArray);
     

    以上代码会将header和body这两个缓冲区的数据写入到通道;

    这里要特别注意的并不是所有数据都写入到通道,写入的数据要根据position和limit的值来判断,只有position和limit之间的数据才会被写入;

    举个例子,假如以上header缓冲区中有128个字节数据,但此时position=0,limit=58;那么只有下标索引为0-57的数据才会被写入到通道中;

    scatter读取

    如下是一个分散读取的示例:

     
    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(1024);
    
    ByteBuffer[] bufferArray = { header, body };
    
    channel.read(bufferArray);
     

    以上代码会将通道中的数据依次写入到Buffer中,当一个buffer被写满后,channel紧接着向另一个buffer中写;

    举个例子,假如通道中有200个字节数据,那么header会被写入128个字节数据,body会被写入72个字节数据;

    好处

    更加高效(以下内容摘自《JAVA NIO》);

    大多数现代操作系统都支持本地矢量I/O(native vectored I/O)操作。

    当您在一个通道上请求一个Scatter/Gather操作时,该请求会被翻译为适当的本地调用来直接填充或抽取缓冲区,减少或避免了缓冲区拷贝和系统调用;

    Scatter/Gather应该使用直接的ByteBuffers以从本地I/O获取最大性能优势;

    参考资料

    《Java NIO》

    http://ifeve.com/java-nio-scattergather/

  • 相关阅读:
    Codeforces 877 C. Slava and tanks
    Codeforces 877 D. Olya and Energy Drinks
    2017 10.25 NOIP模拟赛
    2017 国庆湖南 Day1
    UVA 12113 Overlapping Squares
    学大伟业 国庆Day2
    51nod 1629 B君的圆锥
    51nod 1381 硬币游戏
    [JSOI2010]满汉全席
    学大伟业 2017 国庆 Day1
  • 原文地址:https://www.cnblogs.com/kzd666/p/9437764.html
Copyright © 2011-2022 走看看