代码之家  ›  专栏  ›  技术社区  ›  big_cotton

当“padtocacheallign”==true时,记录队列消息长度更改问题

  •  1
  • big_cotton  · 技术社区  · 7 年前

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

    问题似乎出现在SingleChronicleQueueExcepts类中,在该类中,向消息添加填充以将其缓存对齐到64字节。我并没有预料到必须将自己的消息长度添加到写操作中,但如果历史记录队列没有将自己的头填充到缓存线边界,这似乎是不可避免的。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Peter Lawrey    7 年前

    本文试图解决的问题是,CAS操作实际上不是跨缓存线的原子操作!!在ARM上,它只有一个SIGBUS,但在x64上,它只有99.999%的时间工作。

    我建议在开始处添加一个停止位编码长度,该长度仅为一两个字节。