0

我使用 log4j2 2.10.0 并具有以下代码:

   SingleChronicleQueue q = SingleChronicleQueueBuilder.binary(args[0]).blockSize(536870912).build();
    ExcerptAppender a = q.acquireAppender();

    char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
    StringBuilder sb = new StringBuilder();
    Random random = new Random();
    for (int i = 0; i < 1000; i++) {
        char c = chars[random.nextInt(chars.length)];
        sb.append(c);
    }
    String t = sb.toString();

    for (int i = 0; i < 1000000; i ++ ) {
        m_logger.info(i + " " + t);
        a.writeText(t);
    }

cq4 和日志都写入同一个目录。

在日志中,它爆炸得很好,直到我看到

    12:40:00.853 - [main] INFO c.c.c.a.r.SandboxApp 601049 
    12:40:00.853 - [main] INFO c.c.c.a.r.SandboxApp 601050 
    12:40:00.853 - [main] INFO c.c.c.a.r.SandboxApp 601051 
    12:40:06.156 - [main] INFO c.c.c.a.r.SandboxApp 601052 

有某种 IO 操作使它延迟了 6 秒。

我对磁盘、挂载等知之甚少。如果我注释掉 writeText,这会消失,但我不知道这是编年史问题还是 log4j2。

我的 log4j2 参数是

-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -DAsyncLogger.RingBufferSize=65536*65536 -DAsyncLogger.WaitStrategy=Sleep -Dlog4j2.AsyncQueueFullPolicy=丢弃 -Dlog4j2.DiscardThreshold=INFO

这是分析器显示的内容

探查器

谢谢!!

4

1 回答 1

0

一旦你开始使用内存映射文件,你就离开了 Java 领域,进入了操作系统(和硬件)的世界。

那么,问题 1:您使用的是什么操作系统(以及什么版本)?

问题2:你的机器上有多少物理内存?

问题3:你用的是什么硬盘?SSD 还是旋转磁盘?

2017 年,写入速度超过 200 MB/秒的消费级旋转磁盘非常快。相比之下,2017 年比较中最快的 SSD写入速度为 1900 MB/秒。

您只是尝试将大约 2GB 写入内存映射文件。这需要在某个时候与物理磁盘同步。同步很容易需要 6 秒...

内存映射文件的“乐趣”在于您几乎无法控制何时发生这种同步。人们最终会拆分成更小的文件,以确保这些停顿不会变得太大。在调整此类应用程序的性能方面存在一些黑魔法。在这个领域有很多东西要学。未来的欢乐时光!享受!

顺便说一句,你不能配置

-DAsyncLogger.RingBufferSize=65536*65536 # not a number

Log4j2 将尝试解析65536*65536为数字,这将失败,它会回退到使用默认缓冲区大小。您需要以字节为单位指定所需的环形缓冲区大小。

于 2017-12-25T22:22:59.980 回答