Chronicle Queue 定制器为某些缓冲区添加了额外的字节 (0x008F)。如何确定哪些缓冲区具有此填充?

Chroncile Queue tailer adds additional bytes (0x008F) for some buffers. How to determine which buffers have this padding?

我们正在将 XML 数据编组为字符串并使用 getBytes(StandardCharsets.UTF_8) 将其转换为字节并将它们写入编年史队列:

try (DocumentContext dc = appender.writingDocument()) {
    Wire wire = dc.wire();
    Bytes bytes = wire.bytes();
    bytes.write(message);
}

并像这样阅读:

DocumentContext dc = tailer.readingDocument();
if (dc.isPresent()) {
    Bytes bytes = dc.wire().bytes();
    int length = bytes.length();
    byte[] output = new byte[length];
    bytes.read(output);
    return output;
} 

当我们读回缓冲区时,大多数缓冲区大小匹配,但对于某些缓冲区,如 100 中的 1,我们得到额外的字节(0x008F 的 1/2/3 字节)。我们无法确定哪些缓冲区具有此填充,并且由于此填充而无法真正解组缓冲区。不明白为什么有些缓冲区有这些额外的字节?

Chronicle queue 添加填充,以便 4 字节文档上下文 headers 不会分散 64 字节缓存行。这是因为 headers 在 CAS 操作中使用,并且在大多数架构下,如果 headers 跨越缓存行边界,CAS 操作是非原子的。

如果你想 write/read XML 数据你最好让队列编码和解码这个字符串,因为这样可以节省创建 byte[]

try (DocumentContext dc = appender.writingDocument()) {
    dc.wire().getValueOut().text(text);
}

// can be reused.
StringBuilder sb = new StringBuilder();

try (DocumentContext dc = tailer.readingDocument()) {
    if (dc.isPresent()) {
        dc.wire().text(sb);
        String text = sb.toString();
        process(text);
    }

}

注意:从 Queue 版本 5.16.14 开始,您将能够使用 writeText/readText

appender.writeText(text);

String s = tailer.readText();

节省字节数:

appender.writeBytes(BytesStore.wrap(b));

读取没有任何填充字节:

Bytes<?> bytes = dc.wire().bytes();
int size = (int) bytes.readRemaining();
byte[] result = new byte[size];
for (int i = 0; i < size; i++) {
    result[i] = bytes.readByte();
}