Chroncile队列尾部为某些缓冲区添加了其他字节(0x008F)。如何确定哪些缓冲区具有此填充?

时间:2018-09-05 18:23:59

标签: chronicle chronicle-queue

我们将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个),我们得到了额外的字节(0 / x008F的1/2/3字节)。由于这种填充,我们无法确定哪些缓冲区具有该填充,也无法真正解组该缓冲区。无法理解为什么某些缓冲区有这些额外的字节?

3 个答案:

答案 0 :(得分:1)

编年史队列添加了填充,以便4字节的文档上下文标头不会​​分散在64字节的缓存行中。这是因为标头用于CAS操作,并且在大多数体系结构下,如果标头越过缓存行边界,则CAS操作是非原子的。

答案 1 :(得分:0)

如果要写入/读取XML数据,最好让Queue对该字符串进行编码和解码,因为这样可以节省创建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();

答案 2 :(得分:0)

节省字节:

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();
}