使用ByteBuffer时的Chronicle队列性能



我使用Chronicle Queue作为DataStore,它将被写入一次,但读取多次。我正在努力获得最佳性能(读取x条记录的时间(。我的数据集(用于我的测试(大约有300万条记录,每条记录都由一堆长距离和双距离组成。我最初使用"高级"API,这显然很慢,然后自行描述"数据",如本编年史文档中所述,最后使用"原始数据",这提供了最好的性能。

代码如下:(为简洁起见,省略了相应的write((代码(

public List<DomainObject> read()
{
final ExcerptTailer tailer = _cq.createTailer();
List<DomainObject> result = new ArrayList<>();
for (; ; ) {
try (final DocumentContext ctx = tailer.readingDocument()) {
Wire wire = ctx.wire();
if(wire != null) {
wire.readBytes(in -> {
final long var1= in.readLong();
final int var2= in.readInt();
final double var3= in.readDouble();
final int var4= in.readInt();
final double var5= in.readDouble();
final int var6= in.readInt();
final double var7= in.readDouble();
result.add(DomainObject.create(var1, var2, var3, var4, var5, var6, var7);
});
}else{
return result;
}
}
}
}

然而,为了提高我的应用程序性能,我开始使用ByteBuffer而不是"DomainObject",因此通过读取方法进行了如下修改:

public List<ByteBuffer> read()
{
final ExcerptTailer tailer = _cq.createTailer();
List<ByteBuffer> result = new ArrayList<>();
for (; ; ) {
try (final DocumentContext ctx = tailer.readingDocument()) {
Wire wire = ctx.wire();
if(wire != null) {
ByteBuffer bb = ByteBuffer.allocate(56);
wire.readBytes(in -> {
in.read(bb); });
result.add(bb);
}else{
return result;
}
}
}
}

上面的代码列表平均花费了550毫秒,而第一个列表花费了270毫秒。

我也尝试过使用Bytes.lasticByteBuffer,正如这篇文章中提到的,但慢得多

我猜第二个代码列表的速度较慢,因为它必须遍历整个字节数组。

所以我的问题是-是否有更高性能的方法将Chronicle队列中的字节读取到ByteBuffer中?我的数据将始终是56个字节,每个数据项有8个字节。

我建议您使用Chronicle Bytes而不是原始ByteBuffer。Chronicle的Bytes类是ByteBuffer之上的一个包装器,但更易于使用。代码的问题是创建了一堆对象,而不是流处理。我建议你读一些类似的东西:

public void read(Consumer<Bytes> consumer) {
final ExcerptTailer tailer = _cq.createTailer();
for (; ; ) {
try (final DocumentContext ctx = tailer.readingDocument()) {
if (ctx.isPresent()) {
consumer.accept(ctx.wire().bytes());                    
} else {
break;
}
}
}
}

你的写作方法可能看起来像:

public void write(BytesMarshallable o) {
try (DocumentContext dc = _cq.acquireAppender().writingDocument()) {
o.writeMarshallable(dc.wire().bytes());
}
}

然后你的消费者可能会说:

private BytesMarshallable reusable = new BusinessObject(); //your class here
public accept(Bytes b) {
reusable.readMarshallable(b);
// your business logic here
doSomething(reusable);
}

最新更新