1

以下代码在第 20 次迭代的第二个断言语句中失败 - 请注意,我只是重新创建导致问题的代码;计数无关紧要,而是写入的字节数。

    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 类中,其中向消息添加了填充以将其缓存对齐到 64 个字节。我没有预料到必须将自己的消息长度添加到我的写入中,但如果编年史队列没有将它自己的标题填充到缓存行边界,这似乎是无法避免的。

提前致谢

4

1 回答 1

0

这是试图解决的问题是 CAS 操作实际上并不是跨缓存行的原子!在 ARM 上它只是获得一个 SIGBUS,但在 x64 上它只能工作 99.999% 的时间。

这是我们在客户使用该格式后发现的,因此我们最终解决了这个问题。下一个主要版本应该会解决这个问题。我建议在开头添加一个停止位编码长度,该长度仅为一两个字节。

于 2017-08-08T07:01:26.503 回答