I spent a little time today thinking about Log4j2’s latest salvo in the war for Java Logging.
For those who aren’t aware, Log4j 1.x is a dying project on life-support. They’re locked into Java 4 support and can’t take advantage of Java 5 concurrency primitives which make multi-threaded execution vastly easier. Log4j will stab you in the back at some point. Logback was born, founded by the same people who dreamed up log4j. Until ‘recently’ it’s been Log4j’s successor; Log4j was forked, repackaged, and branded Log4j2 (org.apache.log4j). Log4j2 has been cleaning up and adding Java 5 concurrency and in some cases going even further and otherwise competing with Logback. Some of this is explained in my presentation, Ninth Circle of Hell, a Gentle Introduction to Java Logging.
Log4j2’s just released a brand new AsyncAppender. Without restrictions on library usage, the AsyncAppender uses LMAX Disruptor, a very cool JVM library for doing lock-free blisteringly fast internal queueing with pre-allocated ring buffers. In theory, this looks really good for Log4j2, but in the real world it essentially poses as meaningless benchmark fodder (and adds another transitive dependency, ouch).
Log4j2 posted some benchmarks on their Async Loggers page. They duke out Log4j 1, Log4j 2, and Logback in various configurations. Shown below is Solaris, JDK7, without locations (%class, %location or %line replacements).
For the sake of argument, I’ve taken 2000 lines of output from one of my Java applications that logs with Logback. On average, a line of logging is about 83 characters. 83 characters can be conservatively estimated at 83 bytes. In their tests, they’re using 500-byte payloads.
On Solaris, Log4j2 pushes out 18,000,000 (64 threads) messages per second. Meanwhile, Logback pumps out an acceptable 1,360,000 logs/s (64-threads).
On Windows, Log4j2 puts up a mind-boggling 24,754,080 messages/s and Logback 4,269,920/s.
Using Solaris’ numbers,
288,997 logs/s * 64 threads * 83 bytes = 1535.05 MB/s. Now I’m not sure about you, but I don’t dedicate a Fusion IO RAID to logging.
Numbers including locations are much lower and pretty similar to each other — logging isn’t the bottleneck.
Ultimately not worth it
I’ve concluded that the Log4j2’s AsyncAppender, while neat, is just a shiny toy and there’s really no appreciable difference for any sane application. Greatest respect for the Log4j2 team, but I really wish they’d focused on building a single, cohesive, next-generation Java logging framework rather than adding yet another logging framework to the mix.
Logback , however, natively implements SLF4J (the de-facto standard for classpath-binding logging) and has more than acceptable performance (especially with locations turned on). It continues to be my logging framework of choice. It’s easy to use and I’ve never run into any issues with it.
If nothing else, avoid Log4j 1.x (Or really anything but Log4j2 or Logback) like the plague. In any system with load, you’ll eventually find it causing contention issues.