我想知道GatheringByteChannel的写方法(包括一个ByteBuffers数组)什么时候比“常规”WritableByteChannel写方法有优势。
我尝试了一个测试,在这个测试中,我可以在FileChannel上使用常规的和收集的写方法,在这两种情况下,ByteBuffers的总长度大约为400 27/秒,长度在23-27字节之间。收集写入使用的数组为64。常规方法消耗了大约12%的CPU,而收集方法消耗了大约16%的CPU (比常规方法更糟!)
这告诉我,在这个操作参数范围内在FileChannel上使用收集写是没有用的。为什么会出现这种情况,您什么时候会使用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());
}
}
}更新:
我做了一些测试,不同长度的ByteBuffers的收集方法似乎对文件I/O没有好处。更相关的是通过字节缓冲区长度对I/O流的“分段”。我修改了我的程序,以便它通过将输入读入特定长度的字节缓冲区来复制一个相对较大的(27 my )文件。如果缓冲区长度小于256字节,则程序将开始显着地减速。
我决定尝试第三种选择,即编写我自己的简单“收集”例程,该例程在写入文件机制之前,将缓冲区并将其合并到一个更大的缓冲区中。这就破坏了GatheringByteChannel write(ByteBuffer[] buffers)方法的速度。(注意:所有三种写作模式的阅读大小都是相同的,因此,我创建了一组小型ByteBuffers并使用它们读取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;
}
}
}发布于 2010-05-22 05:50:12
packets.poll()是否每次创建一个新的Buffer?如果不是,在第一种情况下,您正在写入错误的数据。
https://stackoverflow.com/questions/2883970
复制相似问题