有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

nio Java:通过Techannel收集优势?

我想知道GatheringByteChannel的写方法(接受字节缓冲数组)比“常规”的可写字节通道写方法有什么优势

我尝试了一个测试,在这个测试中,我可以在一个文件通道上使用常规和聚集写入方法,在这两种情况下,字节缓冲区的总长度都在23-27字节之间,大约为400KB/s。收集写入使用了64个数组。常规方法消耗了我大约12%的CPU,而收集方法消耗了我大约16%的CPU(比常规方法更糟糕!)

这告诉我,围绕这一范围的操作参数在文件通道上使用收集写操作是没有用的。为什么会是这种情况,你什么时候会使用GatheringByteChannel?(在网络I/O上?)

相关差异如下:

public void log(Queue<Packet> packets) throws IOException
{
    if (this.gather)
    {
        int Nbuf = 64;
        ByteBuffer[] bbufs = new ByteBuffer[Nbuf];
        int i = 0;
        Packet p;
        while ((p = packets.poll()) != null)
        {
            bbufs[i++] = p.getBuffer();
            if (i == Nbuf)
            {
                this.fc.write(bbufs);
                i = 0;
            }
        }
        if (i > 0)
        {
            this.fc.write(bbufs, 0, i);
        }
    }
    else
    {
        Packet p;
        while ((p = packets.poll()) != null)
        {
            this.fc.write(p.getBuffer());
        }
    }
}

更新:

我做了一些测试,针对不同长度字节缓冲区的收集方法似乎对文件I/O没有好处。更重要的是通过字节缓冲区长度对I/O流进行“分段”。我改变了我的程序,通过将输入读入特定长度的字节缓冲区,它复制了一个相对较大(27MB)的文件。如果缓冲区长度小于256字节,则程序开始显著减慢

我决定尝试第三种选择,即编写自己的简单“收集”例程,在写入文件通道之前,将缓冲区合并到更大的缓冲区中。这打破了GatheringByteChannel write(ByteBuffer[] buffers)的速度方法。(注意:读取的大小对于所有三种写入模式都是相同的,因此我创建了一堆小字节缓冲区,并使用它们读取I/O,这一事实并没有导致显著的速度减慢。)我有点失望,Java不只是为你做这件事。哦,好吧

enum GatherType { NONE, AUTOMATIC, MANUAL }

static class BufferWriter
{
    final private FileChannel fc;
    private GatherType gather = GatherType.NONE;

    BufferWriter(FileChannel f) { this.fc = f; } 

    public void setGather(GatherType gather) { this.gather=gather; }
    public void write(Queue<ByteBuffer> buffers) throws IOException
    {
        switch (this.gather)
        {
            case AUTOMATIC:
            {
                int Nbuf = 64;
                ByteBuffer[] bbufs = new ByteBuffer[Nbuf];
                int i = 0;
                ByteBuffer b;
                while ((b = buffers.poll()) != null)
                {
                    bbufs[i++] = b;
                    if (i == Nbuf)
                    {
                        this.fc.write(bbufs);
                        i = 0;
                    }
                }
                if (i > 0)
                {
                    this.fc.write(bbufs, 0, i);
                }
            }
            break;
            case MANUAL:
            {
                ByteBuffer consolidatedBuffer = ByteBuffer.allocate(4096);
                ByteBuffer b;
                while ((b = buffers.poll()) != null)
                {
                    if (b.remaining() > consolidatedBuffer.remaining())
                    {
                        consolidatedBuffer.flip();
                        this.fc.write(consolidatedBuffer);
                        consolidatedBuffer.clear();
                    }

                    if (b.remaining() > consolidatedBuffer.remaining())
                    {
                        this.fc.write(b);
                    }
                    else
                    {
                        consolidatedBuffer.put(b);
                    }
                }

                consolidatedBuffer.flip();
                if (consolidatedBuffer.hasRemaining())
                {
                    this.fc.write(consolidatedBuffer);
                }
            }
            break;
            case NONE:
            {
                ByteBuffer b;
                while ((b = buffers.poll()) != null)
                {
                    this.fc.write(b);
                }
            }
            break;
        }
    }
}

共 (0) 个答案