Chronicle-Queue 'padToCacheAlign' == true 时消息长度更改问题
Chronicle-Queue message length changes issue when 'padToCacheAlign' == true
以下代码在第 20 次迭代的第二个 assert 语句上失败 - 请注意,我只是重新创建导致问题的代码;计数不相关,而是写入的字节数。
SingleChronicleQueue writer = SingleChronicleQueueBuilder.binary("/tmp/broken").build();
ExcerptAppender excerptAppender = writer.acquireAppender();
try(DocumentContext dc = excerptAppender.writingDocument())
{
dc.wire().bytes().writeSkip(36);
}
for(int i = 0; i < 20; i++)
{
try (DocumentContext dc = excerptAppender.writingDocument())
{
dc.wire().bytes().writeSkip(14);
}
}
SingleChronicleQueue reader = SingleChronicleQueueBuilder.binary("/tmp/broken").build();
ExcerptTailer tailer = reader.createTailer();
try(DocumentContext dc = tailer.readingDocument())
{
assert dc.isPresent() && dc.wire().bytes().readRemaining() == 36;
}
for(int i = 0; i < 20; i++)
{
try(DocumentContext dc = tailer.readingDocument())
{
//Fails on the 20th read .. with 16 bytes being returned
assert dc.isPresent() && dc.wire().bytes().readRemaining() == 14;
}
}
问题似乎出在 SingleChronicleQueueExcerpts class 中,其中填充被添加到消息中以缓存对齐到 64 字节。我没有预料到必须将自己的消息长度添加到我的写入中,但如果 chronicle-queue 没有将它自己的 header 填充到缓存行边界,这似乎是不可避免的。
提前致谢
它试图解决的问题是 CAS 操作实际上并不是跨缓存行的原子操作!!在 ARM 上它只得到一个 SIGBUS 但在 x64 上它只在 99.999% 的时间内工作。
这是我们在客户使用该格式后发现的,因此我们最终解决了这个问题。下一个主要版本应该会解决这个问题。
我建议在开头添加一个停止位编码长度,这只会是一个或两个字节。
以下代码在第 20 次迭代的第二个 assert 语句上失败 - 请注意,我只是重新创建导致问题的代码;计数不相关,而是写入的字节数。
SingleChronicleQueue writer = SingleChronicleQueueBuilder.binary("/tmp/broken").build();
ExcerptAppender excerptAppender = writer.acquireAppender();
try(DocumentContext dc = excerptAppender.writingDocument())
{
dc.wire().bytes().writeSkip(36);
}
for(int i = 0; i < 20; i++)
{
try (DocumentContext dc = excerptAppender.writingDocument())
{
dc.wire().bytes().writeSkip(14);
}
}
SingleChronicleQueue reader = SingleChronicleQueueBuilder.binary("/tmp/broken").build();
ExcerptTailer tailer = reader.createTailer();
try(DocumentContext dc = tailer.readingDocument())
{
assert dc.isPresent() && dc.wire().bytes().readRemaining() == 36;
}
for(int i = 0; i < 20; i++)
{
try(DocumentContext dc = tailer.readingDocument())
{
//Fails on the 20th read .. with 16 bytes being returned
assert dc.isPresent() && dc.wire().bytes().readRemaining() == 14;
}
}
问题似乎出在 SingleChronicleQueueExcerpts class 中,其中填充被添加到消息中以缓存对齐到 64 字节。我没有预料到必须将自己的消息长度添加到我的写入中,但如果 chronicle-queue 没有将它自己的 header 填充到缓存行边界,这似乎是不可避免的。
提前致谢
它试图解决的问题是 CAS 操作实际上并不是跨缓存行的原子操作!!在 ARM 上它只得到一个 SIGBUS 但在 x64 上它只在 99.999% 的时间内工作。
这是我们在客户使用该格式后发现的,因此我们最终解决了这个问题。下一个主要版本应该会解决这个问题。 我建议在开头添加一个停止位编码长度,这只会是一个或两个字节。