"Fossies" - the Fresh Open Source Software Archive

Member "apache-log4j-2.12.4-src/src/site/xdoc/performance.xml" (20 Dec 2021, 29879 Bytes) of package /linux/misc/apache-log4j-2.12.4-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) XML source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "performance.xml": 2.18.0_vs_2.19.0.

    1 <?xml version="1.0"?>
    2 <!--
    3     Licensed to the Apache Software Foundation (ASF) under one or more
    4     contributor license agreements.  See the NOTICE file distributed with
    5     this work for additional information regarding copyright ownership.
    6     The ASF licenses this file to You under the Apache License, Version 2.0
    7     (the "License"); you may not use this file except in compliance with
    8     the License.  You may obtain a copy of the License at
    9 
   10          http://www.apache.org/licenses/LICENSE-2.0
   11 
   12     Unless required by applicable law or agreed to in writing, software
   13     distributed under the License is distributed on an "AS IS" BASIS,
   14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15     See the License for the specific language governing permissions and
   16     limitations under the License.
   17 -->
   18 
   19 <document xmlns="http://maven.apache.org/XDOC/2.0"
   20           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   21           xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
   22   <properties>
   23     <title>Performance</title>
   24     <author email="rpopma@apache.org">Remko Popma</author>
   25     <author email="rgoers@apache.org">Ralph Goers</author>
   26   </properties>
   27 
   28   <body>
   29     <section name="Performance">
   30       <!--
   31       <p>One of the often-cited arguments against logging is its
   32         computational cost. This is a legitimate concern as even moderately
   33         sized applications can generate thousands of log requests. Much
   34         effort was spent measuring and tweaking logging performance. Log4j
   35         claims to be fast and flexible: speed first, flexibility second.
   36       </p>
   37       -->
   38       <p>Apart from functional requirements, an important reason for selecting a logging library is often how well it
   39         fulfills non-functional requirements like reliability and performance.</p>
   40       <p>This page compares the performance of a number of logging frameworks
   41         (java.util.logging "JUL", Logback, Log4j 1.2 and Log4j 2.6),
   42         and documents some performance trade-offs for Log4j 2 functionality.
   43       </p>
   44       <a name="benchmarks" />
   45       <h3>Benchmarks</h3>
   46       <p>Performance can mean different things to different people. Common terms in this context are
   47         throughput and latency: <em>Throughput</em> is a measure of capacity and can be expressed in a single number:
   48         how many messages can be logged in a certain period of time.
   49         <em>Response time latency</em> is how long it takes to log a message.
   50         This cannot be expressed in a single number because each measurement has its own
   51         response time and we are often most interested in the outliers: how many there were and how large they were.</p>
   52       <p>When evaluating a logging framework's performance these may be useful questions to ask:</p>
   53       <ul>
   54         <li>What is its <b>peak throughput</b>?
   55           Many systems that react to external events need to log bursts of messages followed by periods of
   56           relative quiet.
   57           This number is the maximum throughput measured over a short period of time and gives some idea
   58           of how well the logging library deals with bursts.
   59           For systems that need to log a lot at a constant high rate (for example, batch jobs)
   60           this is less likely to be a useful measure of performance.</li>
   61         <li>What is the <b>maximum sustained throughput</b>? This is the throughput averaged over a long time.
   62           This is a useful measure of the "upper limit" of the capacity of the logging library.
   63           It is not recommended that reactive applications actually log at this rate since under this load
   64           they will likely experience jitter and large response time spikes.</li>
   65         <a name="responseTime" />
   66         <li><p>What is its <b>response time</b> behaviour under various loads?
   67           This is the most important question for applications that need to react to external events in a timely manner.
   68           Response time is the total amount of time it takes to log a message and is the sum of the
   69           service time and wait time.
   70           The <b>service time</b> is the time it takes to do the work to log the message.
   71           As the workload increases, the service time often varies little:
   72           to do X amount of work it always takes X amount of time.
   73           The <b>wait time</b> is how long the request had to wait in a queue before being serviced.
   74           <em>As the workload increases, wait time often grows to many times the service time.</em>
   75           </p>
   76           </li>
   77       </ul>
   78       <a name="responseTimeVsServiceTime" />
   79       <table>
   80         <tr><td>
   81           <h5>Sidebar: Why Care About Response Time Latency?</h5>
   82           <table border="0" style="border: 0">
   83             <tr style="border: 0">
   84               <td width="50%" style="border: 0"><p>
   85                 What is often measured and reported as <em>latency</em> is actually <em>service time</em>,
   86                 and omits that a service time spike adds wait time for many subsequent events.
   87                 This may present results that are more optimistic than what users experience.
   88               </p><p>
   89                 The graph on the right illustrates how much more optimistic service time is than response time.
   90                 The graph shows response time and service time for the same system under a load of 100,000 messages
   91                 per second. Out of 24 million measurements, only ~50 are more than 250 microseconds, less than 0.001%.
   92                 In a service time-only graph this would hardly be visible.
   93                 However, the depending on the load it will take a while to catch up after a spike.
   94               </p><p>
   95                 The response time graph shows that in reality many more events are
   96                 impacted by these delays than the service time numbers alone would suggest.
   97               </p>
   98                 <p>
   99                   To learn more, watch Gil Tene's eye-opening presentation
  100                   <a href="http://www.infoq.com/presentations/latency-response-time">How NOT to measure
  101                     latency</a>.
  102                 </p>
  103               </td>
  104               <td width="50%" style="border: 0"><a href="images/ResponseTimeVsServiceTimeAsyncLoggers.png"><img
  105                   src="images/ResponseTimeVsServiceTimeAsyncLoggers.png" width="480" height="288"/></a>
  106               </td>
  107             </tr>
  108           </table>
  109         </td></tr>
  110       </table>
  111       <a name="loglibComparison" />
  112       <h3>Logging Library Performance Comparison</h3>
  113 
  114       <a name="asyncLogging" />
  115       <h4>Asynchronous Logging - Peak Throughput Comparison</h4>
  116       <p>Asynchronous logging is useful to deal with bursts of events. How this works is that
  117         a minimum amount of work is done by the application thread to capture all required information in a log event,
  118         and this log event is then put on a queue for later processing by a background thread.
  119         As long as the queue is sized large enough, the application threads should be able to spend
  120         very little time on the logging call and return to the business logic very quickly.
  121       </p>
  122       <p>It turns out that the choice of queue is extremely important for peak throughput.
  123         Log4j 2's Async Loggers use a
  124         <a href="http://lmax-exchange.github.com/disruptor/">lock-free data structure</a>, whereas
  125         Logback, Log4j 1.2 and Log4j 2's Asynchronous Appenders use an ArrayBlockingQueue.
  126         With a blocking queue, multi-threaded applications often experience lock contention when trying to
  127         enqueue the log event.
  128       </p>
  129       <p>The graph below illustrates the difference a lock-free data structure can make to throughput
  130         in multi-threaded scenarios. <em>Log4j 2 scales better with the number of threads:
  131         an application with more threads can log more. The other logging libraries suffer
  132         from lock contention and total throughput stays constant or drops when more threads are logging.
  133         This means that with the other logging libraries, each individual thread will be able to log less.</em></p>
  134       <p>Bear in mind that this is <em>peak</em> throughput: Log4j 2's Async Loggers give better throughput up to a point, but
  135         once the queue is full, the appender thread needs to wait until a slot becomes available in the queue,
  136         and throughput will drop to the maximum sustained throughput of the underlying appenders at best.
  137       </p>
  138       <p><img src="images/async-throughput-comparison.png" alt="Peak throughput comparison" />
  139       </p>
  140       <p>For details, see the <a href="manual/async.html">Async
  141         Loggers</a> manual page.</p>
  142 
  143       <a name="asyncLoggingResponseTime" />
  144       <h4>Asynchronous Logging Response Time</h4>
  145       <p>Response time behaviour varies a lot with the workload and the number of threads that log concurrently.
  146         The <a href="manual/async.html#Latency">Async Loggers</a> manual page and the
  147         <a href="manual/garbagefree.html#Latency">garbage-free logging</a> manual page
  148         provide some graphs showing response time behaviour under various loads.
  149       </p>
  150       <p>This section shows another graph showing response time latency behaviour
  151       under a modest total workload of 64,000 messages per second, with 4 threads logging concurrently.
  152       At this load and on this hardware/OS/JVM configuration, lock contention and context switches play less of a role
  153       and the pauses are mostly caused by minor garbage collections.
  154       Garbage collection pause duration and frequency can vary a lot: when testing the Log4j 1.2.17
  155         Async Appender
  156         a minor GC pause of 7 milliseconds occurred while the Log4j 2 Async Appender test only saw
  157         a GC pause of a little over 2 milliseconds. This does not necessarily mean that one is better than the other.
  158       </p>
  159       <p>Generally, garbage-free async loggers had the best response time behaviour
  160       in all configurations we tested. </p>
  161       <p><img src="images/ResponseTimeAsyncLogging4Threads@16kEach.png" alt="" /></p>
  162       <p>The above result was obtained with
  163         the ResponseTimeTest class which can be found in the Log4j 2 unit test source directory,
  164         running on JDK 1.8.0_45 on
  165         RHEL 6.5 (Linux 2.6.32-573.1.1.el6.x86_64) with
  166         10-core Xeon CPU E5-2660 v3 @2.60GHz with hyperthreading switched on (20 virtual cores).
  167       </p>
  168       <a name="asyncLoggingWithParams" />
  169       <h4>Asynchronous Logging Parameterized Messages</h4>
  170       <p>Many logging libraries offer an API for logging parameterized messages.
  171         This enables application code to look something like this:<pre>
  172 logger.debug("Entry number: {} is {}", i, entry[i]);</pre>
  173         In the above example, the fully formatted message text is not created unless the DEBUG level is enabled for the logger.
  174         Without this API, you would need three lines of code to accomplish the same:
  175         <pre>
  176 if (logger.isDebugEnabled()) {
  177     logger.debug("Entry number: " + i + " is " + entry[i].toString());
  178 }</pre>
  179       </p>
  180       <p>If the DEBUG level <em>is</em> enabled, then at some point the message needs to be formatted.
  181         When logging asynchronously, the message parameters may be changed
  182         by the application thread before the background thread had a chance to log the message.
  183         This would show the wrong values in the log file.
  184         To prevent this, Log4j 2, Log4j 1.2 and Logback format the message text in the application thread
  185         <em>before</em> passing off the log event to the background thread.</p>
  186       <p>This is the safe thing to do, but the formatting has a performance cost.
  187         The graph below compares the throughput of logging messages with parameters using various logging libraries.
  188         These are all asynchronous logging calls, so these numbers do not include the cost of disk I/O
  189         and represent <em>peak</em> throughput.</p>
  190       <p>JUL (java.util.logging) does not have a built-in asynchronous Handler.
  191         <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/MemoryHandler.html">MemoryHandler</a>
  192         is the nearest thing available so we included it here.
  193         MemoryHandler does <em>not</em> do the safe thing of taking a snapshot
  194         of the current parameter state (it just keeps a reference to the original parameter objects),
  195         and as a result it is very fast when single-threaded.
  196         However, when more application threads are logging concurrently, the cost of lock contention outweighs this gain.</p>
  197       <p>In absolute numbers, <em>Log4j 2's Async Loggers perform well compared to the other logging
  198         frameworks, but notice that the message formatting cost increases sharply with the number of parameters.
  199         In this area, Log4j 2 still has work to do to improve: we would like to keep this cost more constant.</em>
  200       </p>
  201       <p><img src="images/ParamMsgThrpt1-4T.png" /></p>
  202       <p>The results above are for JUL (java.util.logging) 1.8.0_45, Log4j 2.6, Log4j 1.2.17 and Logback 1.1.7,
  203         and were obtained with the
  204         <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
  205         See the AsyncAppenderLog4j1Benchmark, AsyncAppenderLog4j2Benchmark, AsyncAppenderLogbackBenchmark,
  206         AsyncLoggersBenchmark and the MemoryHandlerJULBenchmark source code in the log4j-perf module.
  207       </p>
  208 
  209       <a name="asyncLoggingWithLocation" />
  210       <h4>Asynchronous Logging with Caller Location Information</h4>
  211       <p>
  212         Some layouts can show the class, method and line number in the application where the logging call was made.
  213         In Log4j 2, examples of such layout options are HTML
  214         <a href="layouts.html#HtmlLocationInfo">locationInfo</a>,
  215         or one of the patterns <a href="layouts.html#PatternClass">%C or $class</a>,
  216         <a href="layouts.html#PatternFile">%F or %file</a>,
  217         <a href="layouts.html#PatternLocation">%l or %location</a>,
  218         <a href="layouts.html#PatternLine">%L or %line</a>,
  219         <a href="layouts.html#PatternMethod">%M or %method</a>.
  220         In order to provide caller location information, the logging library
  221         will take a snapshot of the stack, and walk the stack trace to find the location information.
  222       </p>
  223       <p>
  224         The graph below shows the performance impact of capturing caller location information when logging
  225         asynchronously from a single thread. Our tests show that <em>capturing caller location has a similar impact
  226         across all logging libraries, and slows down asynchronous
  227         logging by about 30-100x</em>.
  228       </p>
  229       <p><img src="images/AsyncWithLocationThrpt1T-labeled.png" /></p>
  230       <p>The results above are for JUL (java.util.logging) 1.8.0_45, Log4j 2.6, Log4j 1.2.17 and Logback 1.1.7,
  231         and were obtained with the
  232         <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
  233         See the AsyncAppenderLog4j1LocationBenchmark, AsyncAppenderLog4j2LocationBenchmark,
  234         AsyncAppenderLogbackLocationBenchmark, AsyncLoggersLocationBenchmark and the
  235         MemoryHandlerJULLocationBenchmark source code in the log4j-perf module.
  236       </p>
  237 
  238       <a name="fileLoggingComparison" />
  239       <h4>Synchronous File Logging - Sustained Throughput Comparison</h4>
  240       <p>This section discusses the maximum sustained throughput of logging to a file.
  241         In any system, the maximum sustained throughput is determined by its slowest component.
  242         In the case of logging, this is the appender, where the message formatting and disk I/O takes place.
  243         For this reason we will look at simple <em>synchronous</em> logging to a file,
  244         without queues or background threads.</p>
  245       <p>The graph below compares Log4j 2.6's RandomAccessFile appender
  246         to the respective File appenders of Log4j 1.2.17, Logback 1.1.7 and
  247         Java util logging (JUL) on Oracle Java 1.8.0_45. ImmediateFlush was set to false for all
  248         loggers that support this. The JUL results are for the XMLFormatter (which in our measurements was
  249         about twice as fast as the SimpleFormatter).</p>
  250       <p><em>Log4j 2's sustained throughput drops a little when more threads are logging simultaneously,
  251         but its fine-grained locking pays off and throughput stays relatively high.
  252         The other logging frameworks' throughput drops dramatically in multi-threaded applications:
  253         Log4j 1.2 has 1/4th of its single-threaded capacity,
  254         Logback has 1/10th of its single-threaded capacity, and JUL steadily drops from 1/4th to 1/10th of its
  255         single-threaded throughput as more threads are added.</em></p>
  256       <p><img src="images/SyncThroughputLoggerComparisonLinux.png" /></p>
  257       <p>The synchronous logging throughput results above are obtained with the
  258         <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
  259         See the FileAppenderBenchmark source code in the log4j-perf module.</p>
  260 
  261       <h4>Synchronous File Logging - Response Time Comparison</h4>
  262       <p>Response time for synchronous file logging varies a lot with the workload and the
  263       number of threads. Below is a sample for a workload of 32,000 events per second,
  264       with 2 threads logging 16,000 events per second each.</p>
  265       <p><img src="images/SynchronousFileResponseTime2T32k-labeled.png" /></p>
  266       <p>The above result was obtained with the ResponseTimeTest class which can be found in the Log4j 2
  267         unit test source directory, running on JDK 1.8.0_45 on RHEL 6.5 (Linux 2.6.32-573.1.1.el6.x86_64)
  268         with 10-core Xeon CPU E5-2660 v3 @2.60GHz with hyperthreading switched on (20 virtual cores).</p>
  269 <!--
  270 TODO
  271       <h4>Synchronous Socket Sustained Throughput Comparison</h4>
  272       <h4>Synchronous Syslog Sustained Throughput Comparison</h4>
  273 -->
  274       <a name="filtering" />
  275       <h4>Filtering by Level</h4>
  276       <p>The most basic filtering a logging framework provides is filtering by log level.
  277         When logging is turned off entirely or just for a set of Levels, the cost of a log request consists
  278         of a number of method invocations plus an integer comparison.
  279         Unlike Log4j, Log4j 2 Loggers don't "walk a hierarchy".
  280         Loggers point directly to the Logger configuration that best matches the Logger's name.
  281         This incurs extra overhead when the Logger is first created but reduces the overhead every
  282         time the Logger is used.
  283       </p>
  284       <h4>Advanced Filtering</h4>
  285       <p>
  286         Both Logback and Log4j 2 support advanced filtering. Logback calls them TurboFilters while
  287         Log4j 2 has a single Filter object. Advanced filtering provides the capability to filter
  288         LogEvents using more than just the Level before the events are passed to Appenders.
  289         However, this flexibility does come with some cost.
  290         Since multi-threading can also have an impact on the
  291         performance of advanced filtering, the chart below shows the difference in performance of filtering based
  292         on a Marker or a Marker's parent.</p>
  293       <p>
  294         The "Simple Marker" comparison checks to see if a Marker that has no references
  295         to other markers matches the requested Marker. The "Parent Marker" comparison checks to see
  296         if a Marker that does have references to other markers matches the requested Marker. </p>
  297       <p>It appears that coarse-grained synchronization in SLF4J can impact performance in
  298         multi-threaded scenarios. See
  299         <a href="http://jira.qos.ch/browse/SLF4J-240">SLF4J-240</a>.</p>
  300       <p><img src="images/MarkerFilterCostComparison.png" /></p>
  301       <p>Log4j and Logback also support filtering
  302         on a value in the Log4j ThreadContext vs filtering in Logback on a value in the MDC.
  303         The graph below shows that the performance difference between Log4j 2 and Logback
  304         is small for the ThreadContext filter.
  305       </p><p><img src="images/ThreadContextFilterCostComparison.png" /></p>
  306       <p>The Filter comparison results above are obtained with the
  307         <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
  308         See the MarkerFilterBenchmark and MDCFilterBenchmark in the log4j-perf module for details on these
  309         benchmarks.</p>
  310       <a name="tradeoffs" />
  311       <h3>Trade-offs</h3>
  312       <a name="whichAppender" />
  313       <h4>Which Log4j 2 Appender to Use?</h4>
  314       <p>Assuming that you selected Log4j 2 as your logging framework,
  315         next you may be interested in learning what the performance trade-offs are for
  316         selecting a specific Log4j 2 configuration. For example, there are three appenders
  317         for logging to a file: the File, RandomAccessFile and MemoryMappedFile appenders.
  318         Which one should you use?</p>
  319       <p>If performance is all you care about, the graphs below show your best choice is either
  320         the MemoryMappedFile appender or the RandomAccessFile appender.
  321         Some things to bear in mind:
  322       </p>
  323       <ul>
  324         <li>MemoryMappedFile appender does not have a rolling variant yet.</li>
  325         <li>When the log file size exceeds the MemoryMappedFile's region length, the file needs to be remapped.
  326           This can be a very expensive operation, taking several seconds if the region is large.</li>
  327         <li>MemoryMappedFile appender creates a presized file from the beginning and fills it up gradually.
  328           This can confuse tools like <tt>tail</tt>; many such tools don't work very well with memory mapped files.</li>
  329         <li>On Windows, using a tool like <tt>tail</tt> on a file created by RandomAccessFile appender
  330           can hold a lock on this file which may prevent Log4j from opening the file again when the
  331           application is restarted. In a development environment where you expect to restart your application
  332           regularly while using tools like tail to view the log file contents, the File appender may be
  333           a reasonable trade-off between performance and flexibility. For production environments
  334           performance may have higher priority.</li>
  335       </ul>
  336       <p>
  337         The graph below shows sustained throughput for the console and file appenders in Log4j 2.6,
  338         and for reference also provides the 2.5 performance.</p>
  339       <p>It turns out that the garbage-free text encoding logic in 2.6 gives
  340         these appenders a performance boost compared to Log4j 2.5.
  341         It used to be that the RandomAccessFile appender was significantly faster,
  342         especially in multi-threaded scenarios, but with the 2.6 release the File appender
  343         performance has improved and the performance difference between these two appender is smaller.</p>
  344       <p>Another takeaway is just how much of a performance drag logging to the console can be.
  345         Considering logging to a file and using a tool like <tt>tail</tt> to watch the file change in real time.</p>
  346       <p><img src="images/Log4j2AppenderThroughputComparison-linux.png"/></p>
  347       <p>On Windows, the results are similar but the RandomAccessFile and MemoryMappedFile appenders outperform
  348       the plain File appender in multi-threaded scenarios.
  349       The absolute numbers are higher on Windows: we don't know why but it looks like Windows
  350       handles lock contention better than Linux.</p>
  351       <p><img src="images/Log4j2AppenderThroughputComparison-windows.png"/></p>
  352       <p>The Log4j 2 appender comparison results above are obtained with the
  353         <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
  354         See the Log4j2AppenderComparisonBenchmark source code in the log4j-perf module.</p>
  355       <!--
  356       <p>The user should be aware of the following performance issues.</p>
  357           <h3>Logging performance when logging is turned off.</h3>
  358           <p>When logging is turned off entirely or just for a set of Levels, the cost of a log request consists of
  359             two method invocations plus an integer comparison. On a 2.53 GHz Intel Core 2 Duo MacBook Pro
  360             calling isDebugEnabled 10 million times produces an average result in nanoseconds of:</p>
  361             <pre>
  362             Log4j: 4
  363             Logback: 5
  364             Log4j 2: 3
  365             </pre>
  366           <p>
  367             The numbers above will vary slightly from run to run so the only conclusion that should be
  368             drawn is that all 3 frameworks perform similarly on this task.
  369           </p>
  370           <p>However, The method invocation involves the "hidden" cost of parameter construction.
  371           </p>
  372           <p>For example,
  373           </p>
  374             <pre>
  375               logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
  376             </pre>
  377           <p>
  378             incurs the cost of constructing the message parameter, i.e. converting both integer
  379             <code>i</code> and <code>entry[i]</code> to a String, and concatenating intermediate strings,
  380             regardless of whether the message will be logged or not.
  381 
  382             This cost of parameter construction can be quite high and it
  383             depends on the size of the parameters involved.
  384 
  385             A comparison run on the same hardware as above yields:
  386           </p>
  387             <pre>
  388             Log4j: 188
  389             Logback: 183
  390             Log4j 2: 188
  391             </pre>
  392           <p>
  393             Again, no conclusion should be drawn regarding relative differences between the frameworks on
  394             this task, but it should be obvious that it is considerably more expensive than simply testing
  395             the level.
  396           </p>
  397           <p>
  398             The best approach to avoid the cost of parameter construction is to use Log4j 2's formatting
  399             capabilities. For example, instead of the above write:
  400           </p>
  401             <pre>
  402             logger.debug("Entry number: {} is {}", i, entry[i]);
  403             </pre>
  404           <p>
  405             Using this approach, a comparison run again on the same hardware produces:
  406           </p>
  407             <pre>
  408             Log4j: Not supported
  409             Logback: 9
  410             Log4j 2: 4
  411             </pre>
  412           <p>
  413             These results show that the difference in performance between the call to isDebugEnabled and
  414             logger.debug is barely discernible.
  415           </p>
  416           <p>In some circumstances one of the parameters to logger.debug will be a costly method call that
  417             should be avoided if debugging is disabled. In those cases write:
  418           </p>
  419             <pre>
  420             if(logger.isDebugEnabled() {
  421                 logger.debug("Entry number: " + i + " is " + entry[i].toString());
  422             }
  423             </pre>
  424           <p>This will not incur the cost of whatever the toString() method needs to do if debugging is disabled.
  425             On the other hand, if the logger is enabled for the debug level, it will incur twice the cost of
  426             evaluating whether the logger is enabled or not: once
  427             in <code>isDebugEnabled</code> and once in <code>debug</code>. This is an insignificant
  428             overhead because evaluating a logger takes about 1% of the time it takes to actually log.
  429           </p>
  430           <p>Certain users resort to pre-processing or compile-time
  431             techniques to compile out all log statements. This leads to perfect
  432             performance efficiency with respect to logging. However, since the
  433             resulting application binary does not contain any log statements,
  434             logging cannot be turned on for that binary. This seems to be
  435             a disproportionate price to pay in exchange for a small performance
  436             gain.
  437           </p>
  438           <h3>The performance of deciding whether to log or not to log when logging is turned on.</h3>
  439           <p>
  440             Unlike Log4j, Log4j 2 Loggers don't "walk a hierarchy". Loggers point directly to the
  441             Logger configuration that best matches the Logger's name. This incurs extra overhead when the Logger
  442             is first created but reduces the overhead every time the Logger is used.
  443           </p>
  444           <h3>Actually outputting log messages</h3>
  445           <p>This is the cost of formatting the log output and sending it to its target destination. Here again,
  446             a serious effort was made to make layouts (formatters) perform as quickly as possible. The same
  447             is true for appenders. One of the fundamental tenets of Log4j 2 is to use immutable objects whenever
  448             possible and to lock at the lowest granularity possible. However, the cost of actually formatting and
  449             delivering log events will never be insignificant. For example, the results of writing to a simple log
  450             file using the same format using Log4j, Logback and Log4j 2 are:
  451           </p>
  452           <pre>
  453               Log4j: 1651
  454               Logback: 1419
  455               Log4j 2.0: 1542
  456           </pre>
  457           <p>
  458             As with many of the other results on this page the differences between the frameworks above should be
  459             considered insignificant. The values will change somewhat on each execution and changing the order the
  460             frameworks are tested or adding calls to System.gc() between the tests can cause a variation in the
  461             reported times. However, these results show that actually writing out the events can be at least 1000
  462             times more expensive than when they are disabled, so it is always recommended to take advantage of
  463             Log4j 2's fine-grained filtering capabilities.
  464           </p>
  465         -->
  466 
  467     </section>
  468   </body>
  469 </document>