blob: 7eb1957463baf32cdf104a2b54dc66fbecab63f7 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Generated by Apache Maven Doxia at 2021-12-29 -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Log4j &#x2013; Performance - Apache Log4j 2</title>
<link rel="stylesheet" href="./css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="./css/site.css" type="text/css" />
<script type="text/javascript" src="./js/jquery.min.js"></script>
<script type="text/javascript" src="./js/bootstrap.min.js"></script>
<script type="text/javascript" src="./js/prettify.min.js"></script>
<script type="text/javascript" src="./js/site.js"></script>
<meta name="author" content="Ralph Goers" />
<meta name="Date-Revision-yyyymmdd" content="20211229" />
<meta http-equiv="Content-Language" content="en" />
</head>
<body class="composite">
<img class="logo-left" src="./images/ls-logo.jpg" alt="Apache logging services logo" />
<img class="logo-right" src="./images/logo.jpg" alt="Apache log4j logo" />
<div class="clear"></div>
<div class="navbar">
<div class="navbar-inner">
<div class="container-fluid">
<a class="brand" href="/log4j/2.x/">Apache Log4j 2 &trade;</a>
<ul class="nav">
<li>
<a href="http://wiki.apache.org/logging" class="external" target="_blank" title="Logging Wiki">Logging Wiki</a>
</li>
<li>
<a href="http://www.apache.org/" class="external" target="_blank" title="Apache">Apache</a>
</li>
<li>
<a href="../../" title="Logging Services">Logging Services</a>
</li>
<li>
<a href="https://analysis.apache.org/dashboard/index/org.apache.logging.log4j:log4j" class="external" target="_blank" title="Sonar">Sonar</a>
</li>
</ul>
</div>
</div>
</div>
<div class="container-fluid">
<table class="layout-table">
<tr>
<td class="sidebar">
<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header"><i class="icon-home"></i>Apache Log4j™ 2</li>
<li class="none">
<a href="index.html" title="About">About</a>
</li>
<li class="none">
<a href="download.html" title="Download">Download</a>
</li>
<li class="none">
<a href="maven-artifacts.html" title="Maven and Ivy">Maven and Ivy</a>
</li>
<li class="none">
<a href="build.html" title="Build">Build</a>
</li>
<li class="none">
<a href="guidelines.html" title="Guidelines">Guidelines</a>
</li>
<li class="none">
<a href="javastyle.html" title="Style Guide">Style Guide</a>
</li>
<li class="none">
<a href="changelog.html" title="Changelog">Changelog</a>
</li>
<li class="collapsed">
<a href="javadoc.html" title="Javadoc">Javadoc</a>
</li>
<li class="none">
<a href="runtime-dependencies.html" title="Runtime Dependencies">Runtime Dependencies</a>
</li>
<li class="none">
<a href="faq.html" title="FAQ">FAQ</a>
</li>
<li class="none">
<a href="articles.html" title="Articles">Articles</a>
</li>
</ul>
<ul class="nav nav-list">
<li class="nav-header"><i class="icon-book"></i>Manual</li>
<li class="none">
<a href="manual/" title="Introduction">Introduction</a>
</li>
<li class="none">
<a href="manual/architecture.html" title="Architecture">Architecture</a>
</li>
<li class="none">
<a href="manual/migration.html" title="Log4j 1.x Migration">Log4j 1.x Migration</a>
</li>
<li class="collapsed">
<a href="manual/api.html" title="API">API</a>
</li>
<li class="collapsed">
<a href="manual/configuration.html" title="Configuration">Configuration</a>
</li>
<li class="collapsed">
<a href="manual/webapp.html" title="Web Applications and JSPs">Web Applications and JSPs</a>
</li>
<li class="collapsed">
<a href="manual/plugins.html" title="Plugins">Plugins</a>
</li>
<li class="collapsed">
<a href="manual/lookups.html" title="Lookups">Lookups</a>
</li>
<li class="collapsed">
<a href="manual/appenders.html" title="Appenders">Appenders</a>
</li>
<li class="collapsed">
<a href="manual/layouts.html" title="Layouts">Layouts</a>
</li>
<li class="collapsed">
<a href="manual/filters.html" title="Filters">Filters</a>
</li>
<li class="collapsed">
<a href="manual/async.html" title="Async Loggers">Async Loggers</a>
</li>
<li class="none">
<a href="manual/jmx.html" title="JMX">JMX</a>
</li>
<li class="none">
<a href="manual/logsep.html" title="Logging Separation">Logging Separation</a>
</li>
<li class="collapsed">
<a href="manual/extending.html" title="Extending Log4j">Extending Log4j</a>
</li>
<li class="collapsed">
<a href="manual/customconfig.html" title="Extending Log4j Configuration">Extending Log4j Configuration</a>
</li>
<li class="collapsed">
<a href="manual/customloglevels.html" title="Custom Log Levels">Custom Log Levels</a>
</li>
</ul>
<ul class="nav nav-list">
<li class="nav-header"><i class="icon-cog"></i>Components</li>
<li class="none">
<a href="log4j-api/" title="API">API</a>
</li>
<li class="none">
<a href="log4j-core/" title="Implementation">Implementation</a>
</li>
<li class="none">
<a href="log4j-jcl/" title="Commons Logging Bridge">Commons Logging Bridge</a>
</li>
<li class="none">
<a href="log4j-1.2-api/" title="Log4j 1.2 API">Log4j 1.2 API</a>
</li>
<li class="none">
<a href="log4j-slf4j-impl/" title="SLF4J Binding">SLF4J Binding</a>
</li>
<li class="none">
<a href="log4j-jul/" title="JUL Adapter">JUL Adapter</a>
</li>
<li class="none">
<a href="log4j-to-slf4j/" title="Log4j 2 to SLF4J Adapter">Log4j 2 to SLF4J Adapter</a>
</li>
<li class="none">
<a href="log4j-flume-ng/" title="Apache Flume Appender">Apache Flume Appender</a>
</li>
<li class="none">
<a href="log4j-taglib/" title="Log4j Tag Library">Log4j Tag Library</a>
</li>
<li class="none">
<a href="log4j-jmx-gui/" title="Log4j JMX GUI">Log4j JMX GUI</a>
</li>
<li class="none">
<a href="log4j-web/" title="Log4j Web Application Support">Log4j Web Application Support</a>
</li>
<li class="none">
<a href="log4j-nosql/" title="Log4j NoSQL support">Log4j NoSQL support</a>
</li>
<li class="none">
<a href="log4j-iostreams/" title="Log4j IO Streams">Log4j IO Streams</a>
</li>
</ul>
<ul class="nav nav-list">
<li class="nav-header"><i class="icon-info-sign"></i>Project Information</li>
<li class="none">
<a href="dependencies.html" title="Dependencies">Dependencies</a>
</li>
<li class="none">
<a href="dependency-convergence.html" title="Dependency Convergence">Dependency Convergence</a>
</li>
<li class="none">
<a href="dependency-management.html" title="Dependency Management">Dependency Management</a>
</li>
<li class="none">
<a href="team-list.html" title="Project Team">Project Team</a>
</li>
<li class="none">
<a href="mail-lists.html" title="Mailing Lists">Mailing Lists</a>
</li>
<li class="none">
<a href="issue-tracking.html" title="Issue Tracking">Issue Tracking</a>
</li>
<li class="none">
<a href="license.html" title="Project License">Project License</a>
</li>
<li class="none">
<a href="source-repository.html" title="Source Repository">Source Repository</a>
</li>
<li class="none">
<a href="project-summary.html" title="Project Summary">Project Summary</a>
</li>
</ul>
<ul class="nav nav-list">
<li class="nav-header"><i class="icon-cog"></i>Project Reports</li>
<li class="none">
<a href="changes-report.html" title="Changes Report">Changes Report</a>
</li>
<li class="none">
<a href="jira-report.html" title="JIRA Report">JIRA Report</a>
</li>
<li class="none">
<a href="surefire-report.html" title="Surefire Report">Surefire Report</a>
</li>
<li class="none">
<a href="rat-report.html" title="RAT Report">RAT Report</a>
</li>
</ul>
</div>
<div id="poweredBy">
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="poweredBy" alt="Built by Maven" src="./images/maven-feather.png" />
</a>
</div>
</td>
<td class="content">
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<div class="section">
<h2><a name="Performance"></a>Performance</h2>
<p>One of the often-cited arguments against logging is its
computational cost. This is a legitimate concern as even moderately
sized applications can generate thousands of log requests. Much
effort was spent measuring and tweaking logging performance. Log4j
claims to be fast and flexible: speed first, flexibility second.
</p>
<p>The user should be aware of the following performance issues.</p>
<ol style="list-style-type: decimal">
<li>
<div class="section">
<h3><a name="Logging_performance_when_logging_is_turned_off."></a>Logging performance when logging is turned off.</h3>
<p>When logging is turned off entirely or just for a set of Levels, the cost of a log request consists of
two method invocations plus an integer comparison. On a 2.53 GHz Intel Core 2 Duo MacBook Pro
calling isDebugEnabled 10 million times produces an average result in nanoseconds of:</p>
<div>
<pre>
Log4j: 4
Logback: 5
Log4j 2: 3
</pre></div>
<p>
The numbers above will vary slightly from run to run so the only conclusion that should be
drawn is that all 3 frameworks perform similarly on this task.
</p>
<p>However, The method invocation involves the &quot;hidden&quot; cost of parameter construction.
</p>
<p>For example,
</p>
<div>
<pre>
logger.debug(&quot;Entry number: &quot; + i + &quot; is &quot; + String.valueOf(entry[i]));
</pre></div>
<p>
incurs the cost of constructing the message parameter, i.e. converting both integer
<tt>i</tt> and <tt>entry[i]</tt> to a String, and concatenating intermediate strings,
regardless of whether the message will be logged or not.
This cost of parameter construction can be quite high and it
depends on the size of the parameters involved.
A comparison run on the same hardware as above yields:
</p>
<div>
<pre>
Log4j: 188
Logback: 183
Log4j 2: 188
</pre></div>
<p>
Again, no conclusion should be drawn regarding relative differences between the frameworks on
this task, but it should be obvious that it is considerably more expensive than simply testing
the level.
</p>
<p>
The best approach to avoid the cost of parameter construction is to use Log4j 2's formatting
capabilities. For example, instead of the above write:
</p>
<div>
<pre>
logger.debug(&quot;Entry number: {} is {}&quot;, i, entry[i]);
</pre></div>
<p>
Using this approach, a comparison run again on the same hardware produces:
</p>
<div>
<pre>
Log4j: Not supported
Logback: 9
Log4j 2: 4
</pre></div>
<p>
These results show that the difference in performance between the call to isDebugEnabled and
logger.debug is barely discernible.
</p>
<p>In some circumstances one of the parameters to logger.debug will be a costly method call that
should be avoided if debugging is disabled. In those cases write:
</p>
<div>
<pre>
if(logger.isDebugEnabled() {
logger.debug(&quot;Entry number: &quot; + i + &quot; is &quot; + entry[i].toString());
}
</pre></div>
<p>This will not incur the cost of whatever the toString() method needs to do if debugging is disabled.
On the other hand, if the logger is enabled for the debug level, it will incur twice the cost of
evaluating whether the logger is enabled or not: once
in <tt>isDebugEnabled</tt> and once in <tt>debug</tt>. This is an insignificant
overhead because evaluating a logger takes about 1% of the time it takes to actually log.
</p>
<p>Certain users resort to pre-processing or compile-time
techniques to compile out all log statements. This leads to perfect
performance efficiency with respect to logging. However, since the
resulting application binary does not contain any log statements,
logging cannot be turned on for that binary. This seems to be
a disproportionate price to pay in exchange for a small performance
gain.
</p>
</li>
<li>
</div>
<div class="section">
<h3><a name="The_performance_of_deciding_whether_to_log_or_not_to_log_when_logging_is_turned_on."></a>The performance of deciding whether to log or not to log when logging is turned on.</h3>
<p>
Unlike Log4j, Log4j 2 Loggers don't &quot;walk a hierarchy&quot;. Loggers point directly to the
Logger configuration that best matches the Logger's name. This incurs extra overhead when the Logger
is first created but reduces the overhead every time the Logger is used.
</p>
</li>
<li>
</div>
<div class="section">
<h3><a name="Actually_outputting_log_messages"></a>Actually outputting log messages</h3>
<p>This is the cost of formatting the log output and sending it to its target destination. Here again,
a serious effort was made to make layouts (formatters) perform as quickly as possible. The same
is true for appenders. One of the fundamental tenets of Log4j 2 is to use immutable objects whenever
possible and to lock at the lowest granularity possible. However, the cost of actually formatting and
delivering log events will never be insignificant. For example, the results of writing to a simple log
file using the same format using Log4j, Logback and Log4j 2 are:
</p>
<div>
<pre>
Log4j: 1651
Logback: 1419
Log4j 2.0: 1542
</pre></div>
<p>
As with many of the other results on this page the differences between the frameworks above should be
considered insignificant. The values will change somewhat on each execution and changing the order the
frameworks are tested or adding calls to System.gc() between the tests can cause a variation in the
reported times. However, these results show that actually writing out the events can be at least 1000
times more expensive than when they are disabled, so it is always recommended to take advantage of
Log4j 2's fine-grained filtering capabilities.
</p>
</li>
<li>
</div>
<div class="section">
<h3><a name="Advanced_Filtering"></a>Advanced Filtering</h3>
<p>
Both Logback and Log4j 2 support advanced filtering. Logback calls them TurboFilters while
Log4j 2 has a single Filter object. Advanced filtering provides the capability to filter
LogEvents using more than just the Level before the events are passed to Appenders.
However, this flexibility does come with some cost. Since multi-threading can also have an impact on the
performance of advanced filtering, the table below shows the difference in performance in two different
sets of context-wide filters running on the same hardware as the previous tests using
various numbers of threads.
</p>
<table border="0" class="bodyTable">
<tr class="a">
<th>Test</th>
<th>1 thread</th>
<th>2 threads</th>
<th>5 threads</th>
<th>10 threads</th>
<th>20 threads</th>
<th>50 threads</th>
</tr>
<tr class="b">
<td>Logback MDCFilter</td>
<td>37</td>
<td>50</td>
<td>145</td>
<td>316</td>
<td>606</td>
<td>1670</td>
</tr>
<tr class="a">
<td>Log4j 2 ThreadContextMapFilter</td>
<td>30</td>
<td>35</td>
<td>85</td>
<td>165</td>
<td>341</td>
<td>864</td>
</tr>
<tr class="b">
<td>Logback MarkerFilter</td>
<td>17</td>
<td>24</td>
<td>59</td>
<td>115</td>
<td>234</td>
<td>547</td>
</tr>
<tr class="a">
<td>Log4j 2 MarkerFilter</td>
<td>4</td>
<td>5</td>
<td>7</td>
<td>20</td>
<td>35</td>
<td>92</td>
</tr>
</table>
</li>
<li>
</div>
<div class="section">
<h3><a name="Client_vs_Server"></a>Client vs Server</h3>
<p>
Java supports a &quot;client&quot; and a &quot;server&quot; mode of operation. By default, applications that are
run in Java 5 on machines with 2 CPUs or more and 2GB of memory or more on operating systems
other than Windows or are run in a 64-bit JVM are automatically configured to run in &quot;server&quot; mode.
Testing has shown that Log4j 2 benefits greatly from running in server mode and user's are
strongly encouraged to configure their applications to run in server mode when using Log4j 2.
</p>
</li>
<li>
</div>
<div class="section">
<h3><a name="Asynchronous_Logging_Performance_Improvements"></a>Asynchronous Logging Performance Improvements</h3>
<p>
Log4j 2 offers Asynchronous Loggers for high throughput and low latency logging.
Asynchronous Loggers are implemented using the
<a class="externalLink" href="http://lmax-exchange.github.com/disruptor/">LMAX Disruptor</a>
inter-thread messaging library instead of the ArrayBlockingQueue used by Asynchronous Appenders.
</p>
<p>
Asynchronous Appenders already offered about 5 - 10 times more throughput than
synchronous loggers, but this advantage remained more or less constant
when more threads are logging. That is, if you double the number of threads
that are logging you would expect your total throughput to increase, but
this is not the case: the throughput per thread is roughly halved so your
total throughput remains more or less the same.
(Note that this happens even if the appender queue size is large enough to hold
all messages logged during the test, so this is not caused by disk I/O.)
</p>
<p>
Asynchronous Loggers have significantly higher throughput than the legacy Asynchronous Appenders,
especially in multi-threaded scenarios. In one test with 64 threads,
Asynchronous Loggers were 12 times faster than the fastest Asynchronous Appender,
and 68 times faster than the fastest synchronous logger.
In addition to throughput, Asynchronous Loggers have attractive latency characteristics.
Not only is average latency lower compared to Asynchronous Appenders,
but when increasing the number of application threads that do logging,
worst-case latency remained almost constant (10 - 20 microseconds)
where Asynchronous Appenders start experiencing worst-case
latency spikes in the 100 millisecond range, a difference of four orders of magnitude.
See <a href="manual/async.html#Performance">Asynchronous Logging Performance</a> for details.
</p>
</li>
</ol>
<p>
The performance results above were all derived from running the DebugDisabledPerformanceComparison,
FilterPerformanceComparison, and PerformanceComparison junit tests which can be found in the
Log4j 2 unit test source directory.
</p>
</div></div>
</td>
</tr>
</table>
</div>
<div class="footer">
<p>Copyright &copy; 1999-2021 <a class="external" href="http://www.apache.org">Apache Software Foundation</a>. All Rights Reserved.</p>
<p>Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the Apache Logging project logo are trademarks of The Apache Software Foundation.</p>
<p>Site powered by <a class="external" href="http://getbootstrap.com/">Twitter Bootstrap</a>. Icons from <a class="external" href="http://glyphicons.com/">Glyphicons Free</a>.</p>
</div>
</div>
</body>
</html>