我使用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 = Discard -Dlog4j2.DiscardThreshold = INFO
这是分析器显示的内容
谢谢!
答案 0 :(得分:0)
开始使用内存映射文件后,您将离开Java领域并进入操作系统(和硬件)世界。
那么,问题1:您使用的操作系统(以及版本)是什么?
问题2:您的机器上有多少物理内存?
问题3:您使用的硬盘是什么? SSD还是旋转磁盘?
2017年,超过200 MB /秒写入速度的消费级旋转磁盘非常快。相比之下,this 2017 comparison中最快的SSD写入1900 MB /秒。
您刚刚尝试将大约2GB写入内存映射文件。这需要在某些时候与物理磁盘同步。同步可能需要6秒......
内存映射文件的“快乐”是您无法控制何时发生此同步。人们最终会分成较小的文件,以确保这些暂停不会变得太大。调整这种应用程序的性能有一些黑魔法方面。在这个领域有很多东西需要学习。欢乐时光!享受!
顺便说一下,你无法配置
-DAsyncLogger.RingBufferSize=65536*65536 # not a number
Log4j2将尝试将65536*65536
解析为一个数字,这将失败,它将回退使用默认的缓冲区大小。您需要以字节指定所需的环形缓冲区大小。