Chronicle 队列 + log4j2 异步记录器
Chronicle queue + log4j2 async logger
我使用 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=休眠 -Dlog4j2.AsyncQueueFullPolicy=丢弃 -Dlog4j2.DiscardThreshold=信息
这是探查器显示的内容
谢谢!!
一旦开始使用内存映射文件,您就离开了 Java 的领域,进入了操作系统(和硬件)的世界。
那么,问题 1:您使用的是什么操作系统(以及什么版本)?
问题2:你的机器有多少物理内存?
问题三:你用的是什么硬盘? SSD 还是旋转磁盘?
2017 年,超过 200 MB/sec 的消费级旋转磁盘写入速度非常快。相比之下,this 2017 comparison 中最快的 SSD 写入 1900 MB/sec。
您只是尝试将大约 2GB 写入内存映射文件。这需要在某个时候与物理磁盘同步。同步很容易需要 6 秒...
内存映射文件的“乐趣”在于您几乎无法控制同步发生的时间。人们最终分裂成更小的文件,以确保这些停顿不会变得太大。在调整此类应用程序的性能方面存在一些黑魔法。这个领域有很多东西要学。未来的欢乐时光!享受吧!
顺便说一句,你不能配置
-DAsyncLogger.RingBufferSize=65536*65536 # not a number
Log4j2 将尝试将 65536*65536
解析为一个数字,这将失败,并且它将返回使用默认缓冲区大小。您需要以字节 为单位指定所需的环形缓冲区大小 。
我使用 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=休眠 -Dlog4j2.AsyncQueueFullPolicy=丢弃 -Dlog4j2.DiscardThreshold=信息
这是探查器显示的内容
谢谢!!
一旦开始使用内存映射文件,您就离开了 Java 的领域,进入了操作系统(和硬件)的世界。
那么,问题 1:您使用的是什么操作系统(以及什么版本)?
问题2:你的机器有多少物理内存?
问题三:你用的是什么硬盘? SSD 还是旋转磁盘?
2017 年,超过 200 MB/sec 的消费级旋转磁盘写入速度非常快。相比之下,this 2017 comparison 中最快的 SSD 写入 1900 MB/sec。
您只是尝试将大约 2GB 写入内存映射文件。这需要在某个时候与物理磁盘同步。同步很容易需要 6 秒...
内存映射文件的“乐趣”在于您几乎无法控制同步发生的时间。人们最终分裂成更小的文件,以确保这些停顿不会变得太大。在调整此类应用程序的性能方面存在一些黑魔法。这个领域有很多东西要学。未来的欢乐时光!享受吧!
顺便说一句,你不能配置
-DAsyncLogger.RingBufferSize=65536*65536 # not a number
Log4j2 将尝试将 65536*65536
解析为一个数字,这将失败,并且它将返回使用默认缓冲区大小。您需要以字节 为单位指定所需的环形缓冲区大小 。