This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch doc/perf-main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 4e41d5007cb0bdf20866d3c8871b6d9922d61d1f
Author: Volkan Yazıcı <vol...@yazi.ci>
AuthorDate: Tue May 14 10:03:15 2024 +0200

    Rewrite `garbagefree.adoc`
---
 src/site/antora/modules/ROOT/nav.adoc              |   4 +-
 .../antora/modules/ROOT/pages/manual/async.adoc    |   3 +-
 .../modules/ROOT/pages/manual/garbagefree.adoc     | 487 +++++++--------------
 .../antora/modules/ROOT/pages/manual/layouts.adoc  | 182 ++++++++
 .../modules/ROOT/pages/manual/performance.adoc     |   8 +-
 .../ROOT/partials/premature-optimization.adoc      |  24 +
 .../ROOT/partials/properties-async-logger.adoc     | 153 +++++++
 .../partials/properties-garbage-collection.adoc    | 118 +++++
 .../modules/ROOT/partials/properties-meta.adoc     |  52 +++
 .../ROOT/partials/properties-thread-context.adoc   | 101 +++++
 10 files changed, 788 insertions(+), 344 deletions(-)

diff --git a/src/site/antora/modules/ROOT/nav.adoc 
b/src/site/antora/modules/ROOT/nav.adoc
index ec81d8cc05..026d4b60b7 100644
--- a/src/site/antora/modules/ROOT/nav.adoc
+++ b/src/site/antora/modules/ROOT/nav.adoc
@@ -48,8 +48,6 @@
 * xref:manual/layouts.adoc[]
 ** xref:manual/json-template-layout.adoc[]
 * xref:manual/filters.adoc[]
-* xref:manual/async.adoc[]
-* xref:manual/garbagefree.adoc[]
 * xref:manual/extending.adoc[]
 * xref:manual/plugins.adoc[]
 * xref:manual/customconfig.adoc[]
@@ -57,6 +55,8 @@
 * xref:manual/jmx.adoc[]
 * xref:manual/logsep.adoc[]
 * xref:manual/performance.adoc[]
+** xref:manual/async.adoc[]
+** xref:manual/garbagefree.adoc[]
 
 .References
 * xref:plugin-reference.adoc[Plugin reference]
diff --git a/src/site/antora/modules/ROOT/pages/manual/async.adoc 
b/src/site/antora/modules/ROOT/pages/manual/async.adoc
index 4edd39c7c2..11018b8485 100644
--- a/src/site/antora/modules/ROOT/pages/manual/async.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/async.adoc
@@ -14,8 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
-= Lock-free Asynchronous Loggers for Low-Latency Logging
-Remko Popma <rpo...@apache.org>
+= Asynchronous loggers
 
 Asynchronous logging can improve your application's performance by
 executing the I/O operations in a separate thread. Log4j 2 makes a
diff --git a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc 
b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
index d933f830e9..cb658d2919 100644
--- a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
@@ -15,398 +15,219 @@
     limitations under the License.
 ////
 
-= Garbage-free Steady State Logging
+// Properties crowd the ToC, hence limit the exposed levels
+:page-toclevels: 2
+
+= Garbage-free logging
 
 include::partial$manual/garbagefree-intro.adoc[]
 
-[#Config]
-== Configuration
-
-Garbage-free logging in Log4j 2.6 is partially implemented by reusing
-objects in ThreadLocal fields, and partially by reusing buffers when
-converting text to bytes.
-
-ThreadLocal fields holding non-JDK classes can cause memory leaks in web
-applications when the application server's thread pool continues to
-reference these fields after the web application is undeployed. To avoid
-causing memory leaks, Log4j will not use these ThreadLocals when it
-detects that it is used in a web application (when the
-`javax.servlet.Servlet` class is in the classpath, or when system
-property `log4j2.isWebapp` is set to "true").
-
-Some garbage-reducing functionality does not rely on ThreadLocals and is
-enabled by default for all applications: in Log4j 2.6, converting log
-events to text and text to bytes can be done by directly encoding text
-into a reused ByteBuffer without creating intermediary Strings, char
-arrays and byte arrays. So while logging is not completely garbage-free
-for web applications yet, the pressure on the garbage collector can
-still be significantly reduced.
-
-NOTE: As of version 2.6, a Log4j configuration containing a
-`<Properties>` section will result in temporary objects being created
-during steady-state logging.
-
-NOTE:  as of version 2.18.0, the default Async Logger wait strategy used by 
Log4j
-(Timeout) is garbage-free. Some of the wait strategies included in LMAX 
disruptor 3.4.4,
-especially `TimeoutBlockingWaitStrategy` and `BlockingWaitStrategy` (Block)
-are not garbage-free since they
-cause `java.util.concurrent.locks.AbstractQueuedSynchronizer$Node` objects to 
be created.
-The default wait strategy used by Log4j uses a synchronized block instead of a 
ReentrantLock to avoid this problem.
-The Yield and Sleep wait strategies are garbage-free. (For configuring 
predefined wait strategies, see
-xref:manual/async.adoc#SysPropsAllAsync[here] and
-xref:manual/async.adoc#SysPropsMixedSync-Async[here],
-you may also configure a xref:manual/async.adoc#WaitStrategy[custom wait 
strategy].)
-
-=== Disabling Garbage-free Logging
-
-There are two separate system properties for manually controlling the
-mechanisms Log4j uses to avoid creating temporary objects:
-
-* `log4j2.enableDirectEncoders` - if "true" (the default) log events are
-converted to text and this text is converted to bytes without creating
-temporary objects. Note: _synchronous_ logging performance may be worse
-for multi-threaded applications in this mode due to synchronization on
-the shared buffer. If your application is multi-threaded and logging
-performance is important, consider using Async Loggers.
-* The ThreadContext map is _not_ garbage-free by default, but from Log4j
-2.7 it can be configured to be garbage-free by setting system property
-`log4j2.garbagefreeThreadContextMap` to "true".
-
-Instead of system properties, the above properties can also be specified
-in a file named `log4j2.component.properties` by including this file in
-the classpath of the application. See the
-xref:manual/configuration.adoc#SystemProperties[manual regarding system
-properties] for more info.
+include::partial$premature-optimization.adoc[]
 
-[#Appenders]
-=== Supported Appenders
+The act of logging is an interplay between the logging API (i.e., Log4j API) 
where the programmer publishes logs and a logging implementation (i.e., Log4j 
Core) where published logs get consumed; filtered, enriched, encoded, and 
written to files, databases, network sockets, etc.
+Both parties contain different features with different memory allocation 
characteristics.
+To achieve an end-to-end garbage-free logging system, they need to work hand 
in hand.
+Hence, we will discuss both:
 
-The following xref:manual/appenders.adoc[appenders] are garbage-free during
-steady-state logging:
+. xref:#Config[]
+. xref:#api[]
 
-* Console
-* File
-* RollingFile (some temporary objects are created during file rollover)
-* RandomAccessFile
-* RollingRandomAccessFile (some temporary objects are created during
-file rollover)
-* MemoryMappedFile
+[#impatient]
+== For the impatient
 
-Any other appenders not in the above list (including AsyncAppender)
-create temporary objects during steady-state logging. Instead of
-AsyncAppender, use xref:manual/async.adoc[Async Loggers] to log asynchronously
-in a garbage-free manner.
+If you want to have a garbage-free Log4j setup, but don't want to spend time 
with associated details, you can start with setting the following system 
properties to `true`:
 
-[#Filters]
-=== Supported Filters
+* xref:#log4j2.enableThreadlocals[`log4j2.enableThreadlocals`]
+* 
xref:#log4j2.garbagefreeThreadContextMap[`log4j2.garbagefreeThreadContextMap`]
 
-The following xref:manual/filters.adoc[filters] are garbage-free during
-steady-state logging:
+This should be sufficient for a majority of use cases.
+If not for yours, keep on reading.
 
-* CompositeFilter (adding and removing element filters creates temporary
-objects for thread safety)
-* DynamicThresholdFilter
-* LevelRangeFilter (garbage free since 2.8)
-* MapFilter (garbage free since 2.8)
-* MarkerFilter (garbage free since 2.8)
-* StructuredDataFilter (garbage free since 2.8)
-* ThreadContextMapFilter (garbage free since 2.8)
-* ThresholdFilter (garbage free since 2.8)
-* TimeFilter (garbage free since 2.8 except when range must be recalculated 
once per day)
-
-Other filters like BurstFilter, RegexFilter and ScriptFilter are not
-trivial to make garbage free, and there is currently no plan to change
-them.
-
-[#Layouts]
-=== Supported Layouts
-
-==== JsonTemplateLayout
+[#Config]
+== Log4j Core configuration
 
-`JsonTemplateLayout` is garbage-free with
-xref:manual/json-template-layout.adoc#faq-garbage-free[a few exceptions].
+In order to have a garbage-free Log4j Core, you need to
 
-==== PatternLayout
+* xref:#properties[configure it using properties],
+* and employ garbage-free xref:#Layouts[layouts], xref:Appenders[appenders], 
and xref:#Filters[filters].
 
-PatternLayout with the following limited set of conversion patterns is
-garbage-free. Format modifiers to control such things as field width,
-padding, left and right justification will not generate garbage.
+[#core-properties]
+=== Properties
 
-[cols="1m,2"]
-|===
-|Conversion Pattern |Description
+Garbage-free logging can be configured for Log4j Core using properties listed 
below.
+(See xref:manual/configuration.adoc[] on details how you can set these 
properties.)
 
-|%c\{precision}, %logger\{precision}
-|Logger name
+include::partial$properties-meta.adoc[leveloffset=+2]
 
-|%d, %date
-a|
-Note: Only the predefined date formats are garbage-free: (millisecond
-separator may be either a comma ',' or a period '.')
+include::partial$properties-garbage-collection.adoc[leveloffset=+2,tag=!api]
 
-[cols="1m,1"]
-!===
-!Pattern !Example
+[#Layouts]
+=== Layouts
 
-!%d\{DEFAULT}
-!2012-11-02 14:34:02,781
+The following xref:manual/layouts.adoc[layouts] can be configured to run 
garbage-free during steady-state logging.
+To understand which configuration knobs exhibit what kind of allocation 
behaviour, see their dedicated pages.
 
-!%d\{ISO8601}
-!2012-11-02T14:34:02,781
+// Maintain the alphabetical ordering while making changes, please!
+* xref:manual/layouts.adoc#GELFLayout[`GelfLayout`]
+* xref:manual/json-template-layout.adoc#faq-garbage-free[`JsonTemplateLayout`]
+* xref:manual/layouts.adoc#PatternLayout-gcfree[`PatternLayout`]
 
-!%d\{ISO8601_BASIC}
-!20121102T143402,781
+.Implementation notes
+[%collapsible]
+====
+Garbage-free xref:manual/layouts.adoc[layouts] need to implement the 
`Encoder<LogEvent>` interface.
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/layout/StringBuilderEncoder.html[`StringBuilderEncoder`]
 helps with encoding text to bytes in a garbage-free manner.
+====
 
-!%d\{ABSOLUTE}
-!14:34:02,781
+[#Appenders]
+=== Appenders
 
-!%d\{DATE}
-!02 Nov 2012 14:34:02,781
+The following xref:manual/appenders.adoc[appenders] are garbage-free during 
steady-state logging:
 
-!%d\{COMPACT}
-!20121102143402781
+// Maintain the alphabetical ordering while making changes, please!
+* xref:manual/appenders.adoc#ConsoleAppender[`ConsoleAppender`]
+* xref:manual/appenders.adoc#FileAppender[`FileAppender`]
+* 
xref:manual/appenders.adoc#MemoryMappedFileAppender[`MemoryMappedFileAppender`]
+* 
xref:manual/appenders.adoc#RandomAccessFileAppender[`RandomAccessFileAppender`]
+* xref:manual/appenders.adoc#RollingFileAppender[`RollingFileAppender`] 
(except during rollover)
+* 
xref:manual/appenders.adoc#RollingRandomAccessFileAppender[`RollingRandomAccessFileAppender`]
 (except during rollover)
 
-!%d{HH:mm:ss,SSS}
-!14:34:02,781
+Any other appender not shared in the above list (including 
xref:manual/appenders.adoc#AsyncAppender[`AsyncAppender`]) is not garbage-free.
 
-!%d{dd MMM yyyy HH:mm:ss,SSS}
-!02 Nov 2012 14:34:02,781
+.Implementation notes
+[%collapsible]
+====
+Garbage-free xref:manual/appenders.adoc[appenders] need to provide their 
xref:manual/layouts.adoc[layout] with a `ByteBufferDestination` implementation 
that the layout can directly write into.
 
-!%d{HH:mm:ss}{GMT+0}
-!18:34:02
+[NOTE]
+=====
+`AbstractOutputStreamAppender` has been modified to make the following 
appenders garbage-free:
 
-!%d\{UNIX}
-!1351866842
+* `ConsoleAppender`
+* `(Rolling)FileAppender`
+* `(Rolling)RandomAccessFileAppender`
+* `MemoryMappedFileAppender`
 
-!%d\{UNIX_MILLIS}
-!1351866842781
-!===
+An effort has been made to minimize impact on custom appenders that extend 
`AbstractOutputStreamAppender`, but it is impossible to guarantee that changing 
the superclass will not impact any and all subclasses.
+Custom appenders that extend `AbstractOutputStreamAppender` should verify that 
they still function correctly.
+In case there is a problem, xref:#log4j2.enableDirectEncoders[the 
`log4j2.enableDirectEncoders` system property] can be set to `false` to revert 
to the pre-Log4j 2.6 behaviour.
+=====
+====
 
-|%enc\{pattern}, %encode\{pattern}
-|Encodes special characters such as
-'\n' and HTML characters to help prevent log forging and some XSS
-attacks that could occur when displaying logs in a web browser -
-garbage-free since 2.8
+[#Filters]
+=== Filters
 
-|%equals\{pattern}\{test}\{substitution},
-%equalsIgnoreCase\{pattern}\{test}\{substitution}
-|Replaces occurrences
-of 'test', a string, with its replacement 'substitution' in the string
-resulting from evaluation of the pattern - garbage-free since 2.8
+The following xref:manual/filters.adoc[filters] are garbage-free during 
steady-state logging:
 
-|%highlight\{pattern}\{style}
-|Adds ANSI colors - garbage-free since 2.7
-(unless nested pattern is not garbage free)
+// Maintain the alphabetical ordering while making changes, please!
+* xref:manual/filters.adoc#CompositeFilter[`CompositeFilter`] (adding and 
removing element filters creates temporary
+objects for thread safety)
+* xref:manual/filters.adoc#DynamicThresholdFilter[`DynamicThresholdFilter`]
+* xref:manual/filters.adoc#LevelRangeFilter[`LevelRangeFilter`] (garbage-free 
since `2.8`)
+* xref:manual/filters.adoc#MapFilter[`MapFilter`] (garbage-free since `2.8`)
+* xref:manual/filters.adoc#MarkerFilter[`MarkerFilter`] (garbage-free since 
`2.8`)
+* xref:manual/filters.adoc#StructuredDataFilter[`StructuredDataFilter`] 
(garbage-free since `2.8`)
+* xref:manual/filters.adoc#ThreadContextMapFilter[`ThreadContextMapFilter]` 
(garbage-free since `2.8`)
+* xref:manual/filters.adoc#ThresholdFilter[`ThresholdFilter`] (garbage-free 
since `2.8`)
+* xref:manual/filters.adoc#TimeFilter[`TimeFilter`] (garbage-free since `2.8` 
except when range must be recalculated once per day)
 
-|%K\{key}, %map\{key}, %MAP\{key}
-|Outputs the entries in a
-link:../javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[MapMessage],
-if one is present in the event - garbage-free since 2.8.
+Any other filter not shared in the above list is not garbage-free.
 
-|%m, %msg, %message
-|Log message (garbage-free unless message text
-contains '${')
+[#core-limitations]
+=== Limitations
 
-|%marker
-|The full name of the marker (including parents) - garbage-free
-since 2.8
+There are certain caveats associated with the configuration of garbage-free 
logging:
 
-|%markerSimpleName
-|The simple name of the marker (not including
-parents)
+[#core-limitation-properties]
+`<Properties>` section::
 
-|%maxLen, %maxLength
-|Truncates another pattern to some max number of
-characters - garbage-free since 2.8
+A configuration containing 
xref:manual/configuration.adoc#PropertySubstitution[a `<Properties>` section] 
will result in temporary objects being created during steady-state logging.
 
-|%n
-|The platform dependent line separator
+[#core-limitation-async-logger-wait-strategy]
+Asynchronous logger wait strategies::
 
-|%N, %nano
-|System.nanoTime() when the event was logged
+As of version `2.18.0`, the default xref:manual/async.adoc[asynchronous 
logger] wait strategy (i.e., `Timeout`) is garbage-free while running against 
both LMAX Disruptor 3 and 4.
+See 
xref:manual/async.adoc#log4j2.asyncLoggerWaitStrategy[`log4j2.asyncLoggerWaitStrategy`]
 for details on predefined wait strategies.
 
-|%notEmpty\{pattern}, %varsNotEmpty\{pattern},
-%variablesNotEmpty\{pattern}
-|Outputs the result of evaluating the
-pattern if and only if all variables in the pattern are not empty -
-garbage-free since 2.8
+[#api]
+== Log4j API configuration and usage
 
-|%p, %level
-|The level of the logging event
+In order to have a garbage-free Log4j API, you need to
 
-|%r, %relative
-|The number of milliseconds elapsed since the JVM was
-started until the creation of the logging event - garbage-free since 2.8
+* xref:#api-config[configure it using properties],
+* and xref:#api-usage[use garbage-free API methods].
 
-|%sn, %sequenceNumber
-|A sequence number that will be incremented in
-every event - garbage-free since 2.8
+[#api-config]
+=== Configuration
 
-|%style\{pattern}{ANSI style}
-|Style the message - garbage-free since
-2.7 (unless nested pattern is not garbage free)
+Garbage-free logging can be configured for Log4j API using properties listed 
below.
+(See xref:manual/configuration.adoc[] on details how you can set these 
properties.)
 
-|%T, %tid, %threadId
-|The ID of the thread that generated the logging
-event
+include::partial$properties-garbage-collection.adoc[leveloffset=+2,tag=api]
 
-|%t, %tn, %thread, %threadName
-|The name of the thread that generated
-the logging event
+include::partial$properties-thread-context.adoc[leveloffset=+2,tag=gcfree]
 
-|%tp
-|The priority of the thread that generated the logging event
+[#api-usage]
+=== Usage
 
-|%X{key[,key2...]}, %mdc{key[,key2...]}, %MDC{key[,key2...]}
-|Outputs
-the Thread Context Map (also known as the Mapped Diagnostic Context or
-MDC) associated with the thread that generated the logging event -
-garbage-free since 2.8
-
-|literal text
-|Garbage-free unless literal contains '${' (variable
-substitution)
-|===
-
-Other PatternLayout conversion patterns, and other Layouts may be
-updated to avoid creating temporary objects in future releases. (Patches
-welcome!)
-
-NOTE: Logging exceptions and stack traces will create temporary
-objects with any layout. (However, Layouts will only create these
-temporary objects when an exception actually occurs.) We haven't figured
-out a way to log exceptions and stack traces without creating temporary
-objects. That is unfortunate, but you probably still want to log them
-when they happen.
-
-****
-NOTE: patterns containing regular expressions and lookups for property
-substitution will result in temporary objects being created during
-steady-state logging.
-
-Including location information is done by walking the stacktrace of an
-exception, which creates temporary objects, so the following patterns
-are not garbage-free:
-
-* %C, %class - Class Name
-* %F, %file - File Location
-* %l, %location - Location
-* %L, %line - Line Location
-* %M, %method - Method Location
-
-Also, the pattern converters for formatting Throwables are not
-garbage-free:
-
-* %ex, %exception, %throwable - The Throwable trace bound to the
-LoggingEvent
-* %rEx, %rException %rThrowable - Same as %ex but with wrapping
-exceptions
-* %xEx, %xException, %xThrowable - Same as %ex but with class packaging
-information
-* %u, %uuid - Creates a new random or time-based UUID while formatting
-
-****
+xref:manual/api.adoc[Log4j API] contains several features to facilitate 
garbage-free logging:
 
-[#api]
-=== API Changes
+[#api-vararg]
+==== Parameterized message arguments
 
-Methods have been added to the `Logger` interface so that no vararg
-array objects are created when logging messages with up to ten
-parameters.
+The `Logger` interface contains methods for parameterized messages up to 10 
arguments.
+Logging more than 10 parameters creates 
https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html[vararg
 arrays].
 
-Also, methods have been added to the `Logger` interface to log
-`java.lang.CharSequence` messages. User-defined objects that implement
-the `CharSequence` interface can be logged without creating temporary
-objects: Log4j will try to turn CharSequence messages, Object messages
-and message parameters into text by appending them to a StringBuilder as
-a CharSequence. This avoids calling `toString()` on these objects.
+[#api-encode-custom-object]
+==== Encoding custom objects
 
-An alternative is to implement the
-http://logging.apache.org/log4j/2.x/log4j-api/xref/org/apache/logging/log4j/util/StringBuilderFormattable.html[`org.apache.logging.log4j.util.StringBuilderFormattable`]
-interface. If an object is logged that implements this interface, its
-`formatTo` method is called instead of `toString()`.
+When a message parameter contains an unknown type by the layout, it will 
encode by calling `toString()` on these objects.
+Most objects don't have garbage-free `toString()` methods.
+Objects themselves can implement their own garbage-free encoders by either 
extending from 
https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html[Java's 
`CharSequence`] or 
link:../javadoc/log4j-api/org/apache/logging/log4j/util/StringBuilderFormattable.html[Log4j's
 `StringBuilderFormattable`].
 
 [#codeImpact]
-=== Impact on Application Code: Autoboxing
+==== Avoiding autoboxing
 
-We made an effort to make logging garbage-free without requiring code
-changes in existing applications, but there is one area where this was
-not possible. When logging primitive values (i.e. int, double, boolean,
-etc.) the JVM autoboxes these primitive values to their Object wrapper
-equivalents, creating garbage.
-
-Log4j provides an `Unbox` utility to prevent autoboxing of primitive
-parameters. This utility contains a thread-local pool of reused
-`StringBuilder`s. The `Unbox.box(primitive)` methods write directly into
-a StringBuilder, and the resulting text will be copied into the final
-log message text without creating temporary objects.
+We made an effort to make logging garbage-free without requiring code changes 
in existing applications, but there is one area where this was not possible.
+https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html[When logging 
primitive values (i.e., `int`, `double`, `boolean`, etc.) the JVM autoboxes 
these primitive values to their `Object` wrapper equivalents, creating garbage.]
+Log4j provides an `Unbox` utility to prevent autoboxing of primitive 
parameters:
 
 [source,java]
 ----
 import static org.apache.logging.log4j.util.Unbox.box;
 
-// ...
-public void garbageFree() {
-    logger.debug("Prevent primitive autoboxing {} {}", box(10L), box(2.6d));
-}
+LOGGER.debug("Prevent primitive autoboxing {} {}", box(10L), box(2.6d));
 ----
 
-****
-NOTE: not all logging is garbage free. Specifically:
-
-* The ThreadContext map is not garbage-free by default, but can be
-configured to be garbage-free by setting system property
-`log4j2.garbagefreeThreadContextMap` to "true".
-* The ThreadContext stack is not garbage-free.
-* Logging more than 10 parameters creates vararg arrays.
-* Logging very large messages (more than 518 characters) when all
-loggers are Async Loggers will cause the internal StringBuilder in the
-RingBuffer to be trimmed back to their max size.
-* Logging messages containing '${': substituting a `$\{variable}` creates
-temporary objects.
-* Logging a lambda _as a parameter_
-(`logger.info("lambda value is {}", () -> callExpensiveMethod())`)
-creates a vararg array. Logging a lambda expression by itself is
-garbage-free: `logger.debug(() -> callExpensiveMethod())`.
-* The `Logger.traceEntry` and `Logger.traceExit` methods create
-temporary objects.
-* Time calculations are not garbage free when log4j2.usePreciseClock is set to 
true.
-The default is false.
-****
-
-[#UnderTheHood]
-== Under the Hood
-
-Custom Message implementations that implement
-`org.apache.logging.log4j.util.StringBuilderFormattable` can be
-converted to text by garbage-free Layouts without creating temporary
-objects. PatternLayout uses this mechanism and other layouts that
-convert LogEvents to text will likely also look for this interface.
-
-Custom Layouts that want to be garbage-free should implement the
-`Encoder<LogEvent>` interface. For custom Layouts that convert a
-LogEvent to a text representation, the
-`org.apache.logging.log4j.core.layout.StringBuilderEncoder` class may be
-useful to convert this text to bytes in a garbage-free manner.
-
-Custom Appenders that want to be garbage-free should provide their
-Layout with a `ByteBufferDestination` implementation that the Layout can
-directly write into.
-
-`AbstractOutputStreamAppender` has been modified to make the
-ConsoleAppender, (Rolling)FileAppender,
-(Rolling)RandomAccessFileAppender and MemoryMappedFileAppender
-garbage-free. An effort has been made to minimize impact on custom
-Appenders that extend `AbstractOutputStreamAppender`, but it is
-impossible to guarantee that changing the superclass will not impact any
-and all subclasses. Custom Appenders that extend
-`AbstractOutputStreamAppender` should verify that they still function
-correctly. In case there is a problem, system property
-`log4j2.enable.direct.encoders` can be set to "false" to revert to the
-pre-Log4j 2.6 behaviour.
+This utility contains a `ThreadLocal` pool of reused ``StringBuilder``s.
+The pool size is configured by xref:#log4j2.unboxRingbufferSize[the 
`log4j2.unboxRingbufferSize` system property].
+The `Unbox.box(primitive)` methods write directly into a `StringBuilder`, and 
the resulting text will be copied into the final log message text without 
creating temporary objects.
 
-////
-TODO Applications that wish to reuse custom Message instances with Async 
Loggers should let
-their Message classes implement the 
`org.apache.logging.log4j.message.ReusableMessage` interface.
-TODO This is not sufficient: see LOG4J2-1342, would be nice if we could solve 
this in a generic way.
-////
+[#api-limitations]
+=== Limitations
+
+Not all Log4j API feature set is garbage-free, specifically:
+
+* The `ThreadContext` map (aka. MDC) is not garbage-free by default, but can 
be configured to be garbage-free by setting 
xref:#log4j2.garbagefreeThreadContextMap[the 
`log4j2.garbagefreeThreadContextMap` system property] to `true`.
+* The `ThreadContext` stack is not garbage-free.
+* Logging very large messages (i.e., more than 
xref:#log4j2.maxReusableMsgSize[`log4j2.maxReusableMsgSize`] characters, which 
defaults to 518), when all loggers are xref:manual/async.adoc[asynchronous 
loggers], will cause the internal `StringBuilder` in the
+`RingBuffer` to be trimmed back to their configured maximum size.
+* Logging messages containing `$\{variable}` substitutions creates temporary 
objects.
+* Logging a lambda as a parameter:
++
+[source,java]
+----
+LOGGER.info("lambda value is {}", () -> callExpensiveMethod());
+----
++
+creates a vararg array.
+Logging a lambda expression by itself:
++
+[source,java]
+----
+LOGGER.debug(() -> callExpensiveMethod());
+----
++
+is garbage-free.
+* The 
link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#traceEntry()[`traceEntry()`]
 and 
link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#traceExit()[`traceExit()`]
 methods create temporary objects.
+* Time calculations are not garbage-free when the `log4j2.usePreciseClock` 
system property (defaults to `false`) is set to `true`.
diff --git a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc 
b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
index 7a13314f58..dce83f99ea 100644
--- a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
@@ -1610,6 +1610,188 @@ should be used.
 </PatternLayout>
 ----
 
+[#PatternLayout-gcfree]
+=== Garbage-free configuration
+
+PatternLayout with the following limited set of conversion patterns is
+garbage-free. Format modifiers to control such things as field width,
+padding, left and right justification will not generate garbage.
+
+[cols="1m,2"]
+|===
+|Conversion Pattern |Description
+
+|%c\{precision}, %logger\{precision}
+|Logger name
+
+|%d, %date
+a|
+Note: Only the predefined date formats are garbage-free: (millisecond
+separator may be either a comma ',' or a period '.')
+
+[cols="1m,1"]
+!===
+!Pattern !Example
+
+!%d\{DEFAULT}
+!2012-11-02 14:34:02,781
+
+!%d\{ISO8601}
+!2012-11-02T14:34:02,781
+
+!%d\{ISO8601_BASIC}
+!20121102T143402,781
+
+!%d\{ABSOLUTE}
+!14:34:02,781
+
+!%d\{DATE}
+!02 Nov 2012 14:34:02,781
+
+!%d\{COMPACT}
+!20121102143402781
+
+!%d{HH:mm:ss,SSS}
+!14:34:02,781
+
+!%d{dd MMM yyyy HH:mm:ss,SSS}
+!02 Nov 2012 14:34:02,781
+
+!%d{HH:mm:ss}{GMT+0}
+!18:34:02
+
+!%d\{UNIX}
+!1351866842
+
+!%d\{UNIX_MILLIS}
+!1351866842781
+!===
+
+|%enc\{pattern}, %encode\{pattern}
+|Encodes special characters such as
+'\n' and HTML characters to help prevent log forging and some XSS
+attacks that could occur when displaying logs in a web browser -
+garbage-free since 2.8
+
+|%equals\{pattern}\{test}\{substitution},
+%equalsIgnoreCase\{pattern}\{test}\{substitution}
+|Replaces occurrences
+of 'test', a string, with its replacement 'substitution' in the string
+resulting from evaluation of the pattern - garbage-free since 2.8
+
+|%highlight\{pattern}\{style}
+|Adds ANSI colors - garbage-free since 2.7
+(unless nested pattern is not garbage free)
+
+|%K\{key}, %map\{key}, %MAP\{key}
+|Outputs the entries in a
+link:../javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[MapMessage],
+if one is present in the event - garbage-free since 2.8.
+
+|%m, %msg, %message
+|Log message (garbage-free unless message text
+contains '${')
+
+|%marker
+|The full name of the marker (including parents) - garbage-free
+since 2.8
+
+|%markerSimpleName
+|The simple name of the marker (not including
+parents)
+
+|%maxLen, %maxLength
+|Truncates another pattern to some max number of
+characters - garbage-free since 2.8
+
+|%n
+|The platform dependent line separator
+
+|%N, %nano
+|System.nanoTime() when the event was logged
+
+|%notEmpty\{pattern}, %varsNotEmpty\{pattern},
+%variablesNotEmpty\{pattern}
+|Outputs the result of evaluating the
+pattern if and only if all variables in the pattern are not empty -
+garbage-free since 2.8
+
+|%p, %level
+|The level of the logging event
+
+|%r, %relative
+|The number of milliseconds elapsed since the JVM was
+started until the creation of the logging event - garbage-free since 2.8
+
+|%sn, %sequenceNumber
+|A sequence number that will be incremented in
+every event - garbage-free since 2.8
+
+|%style\{pattern}{ANSI style}
+|Style the message - garbage-free since
+2.7 (unless nested pattern is not garbage free)
+
+|%T, %tid, %threadId
+|The ID of the thread that generated the logging
+event
+
+|%t, %tn, %thread, %threadName
+|The name of the thread that generated
+the logging event
+
+|%tp
+|The priority of the thread that generated the logging event
+
+|%X{key[,key2...]}, %mdc{key[,key2...]}, %MDC{key[,key2...]}
+|Outputs
+the Thread Context Map (also known as the Mapped Diagnostic Context or
+MDC) associated with the thread that generated the logging event -
+garbage-free since 2.8
+
+|literal text
+|Garbage-free unless literal contains '${' (variable
+substitution)
+|===
+
+Other PatternLayout conversion patterns, and other Layouts may be
+updated to avoid creating temporary objects in future releases. (Patches
+welcome!)
+
+NOTE: Logging exceptions and stack traces will create temporary
+objects with any layout. (However, Layouts will only create these
+temporary objects when an exception actually occurs.) We haven't figured
+out a way to log exceptions and stack traces without creating temporary
+objects. That is unfortunate, but you probably still want to log them
+when they happen.
+
+[NOTE]
+====
+patterns containing regular expressions and lookups for property
+substitution will result in temporary objects being created during
+steady-state logging.
+
+Including location information is done by walking the stacktrace of an
+exception, which creates temporary objects, so the following patterns
+are not garbage-free:
+
+* %C, %class - Class Name
+* %F, %file - File Location
+* %l, %location - Location
+* %L, %line - Line Location
+* %M, %method - Method Location
+
+Also, the pattern converters for formatting Throwables are not
+garbage-free:
+
+* %ex, %exception, %throwable - The Throwable trace bound to the
+LoggingEvent
+* %rEx, %rException %rThrowable - Same as %ex but with wrapping
+exceptions
+* %xEx, %xException, %xThrowable - Same as %ex but with class packaging
+information
+* %u, %uuid - Creates a new random or time-based UUID while formatting
+====
+
 [#RFC5424Layout]
 == RFC5424 Layout
 
diff --git a/src/site/antora/modules/ROOT/pages/manual/performance.adoc 
b/src/site/antora/modules/ROOT/pages/manual/performance.adoc
index b655f230b4..cced659d63 100644
--- a/src/site/antora/modules/ROOT/pages/manual/performance.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/performance.adoc
@@ -105,13 +105,7 @@ While this would work for cases where the message can be 
dropped due to insuffic
 
 Below sections walk you through a set of features that can have significant 
impact on the performance of Log4j Core.
 
-[IMPORTANT]
-====
-Extra tuning of any application will deviate you away from defaults and add up 
to the maintenance load.
-You are strongly advised to measure your application's overall performance and 
then, if Log4j is found to be an important bottleneck factor, tune it carefully.
-When this happens, we also recommend you to evaluate your assumptions on a 
regular basis to check if they still hold.
-Remember, 
https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize[premature 
optimization is the root of all evil].
-====
+include::partial$premature-optimization.adoc[]
 
 [TIP]
 ====
diff --git a/src/site/antora/modules/ROOT/partials/premature-optimization.adoc 
b/src/site/antora/modules/ROOT/partials/premature-optimization.adoc
new file mode 100644
index 0000000000..f48573a3ec
--- /dev/null
+++ b/src/site/antora/modules/ROOT/partials/premature-optimization.adoc
@@ -0,0 +1,24 @@
+////
+    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.
+////
+
+[IMPORTANT]
+====
+Extra tuning of any application will deviate you away from defaults and add up 
to the maintenance load.
+You are strongly advised to measure your application's overall performance and 
then, if Log4j is found to be an important bottleneck factor, tune it carefully.
+When this happens, we also recommend you to evaluate your assumptions on a 
regular basis to check if they still hold.
+Remember, 
https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize[premature 
optimization is the root of all evil].
+====
diff --git a/src/site/antora/modules/ROOT/partials/properties-async-logger.adoc 
b/src/site/antora/modules/ROOT/partials/properties-async-logger.adoc
new file mode 100644
index 0000000000..3907722a49
--- /dev/null
+++ b/src/site/antora/modules/ROOT/partials/properties-async-logger.adoc
@@ -0,0 +1,153 @@
+////
+    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.
+////
+[id=log4j2.asyncLoggerExceptionHandler]
+== `log4j2.asyncLoggerExceptionHandler`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_EXCEPTION_HANDLER
+| Type          | 
https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/ExceptionHandler.html[Class<?
 extends ExceptionHandler<? super RingBufferLogEvent>>]
+| Default value | 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/AsyncLoggerDefaultExceptionHandler[AsyncLoggerDefaultExceptionHandler]
+|===
+
+Fully qualified name of a class that implements the 
https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/ExceptionHandler.html[ExceptionHandler]
 interface, which will be notified when an exception occurs while logging 
messages.
+The class needs to have a public zero-argument constructor.
+
+The default exception handler will print a message and stack trace to the 
standard error output stream.
+
+[id=log4j2.asyncLoggerRingBufferSize]
+== `log4j2.asyncLoggerRingBufferSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_RING_BUFFER_SIZE
+| Type          | `int`
+| Default value | `256 &times; 1024`
+
+(GC-free mode: `4 &times; 1024`)
+|===
+
+Size (number of slots) in the RingBuffer used by the asynchronous logging 
subsystem.
+Make this value large enough to deal with bursts of activity.
+The minimum size is 128.
+The RingBuffer will be pre-allocated at first use and will never grow or 
shrink during the life of the system.
+
+When the application is logging faster than the underlying appender can keep 
up with for a long enough time to fill up the queue, the behaviour is 
determined by the 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/AsyncQueueFullPolicy.html[AsyncQueueFullPolicy].
+
+[id=log4j2.asyncLoggerWaitStrategy]
+== `log4j2.asyncLoggerWaitStrategy`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_WAIT_STRATEGY
+| Type          | 
https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/WaitStrategy.html[Class<?
 extends WaitStrategy>] or predefined constant
+| Default value | `Timeout`
+|===
+
+Specifies the 
https://lmax-exchange.github.io/disruptor/javadoc/com.lmax.disruptor/com/lmax/disruptor/WaitStrategy.html[WaitStrategy]
 used by the LMAX Disruptor.
+
+The value needs to be a fully qualified class name of a custom `WaitStrategy` 
implementation (cf. xref:manual/async.adoc#custom-waitstrategy[Custom 
WaitStrategy]) or one of the predefined constants:
+
+Block:: a strategy that uses a lock and condition variable for the I/O thread 
waiting for log events.
+Block can be used when throughput and low-latency are not as important as CPU 
resource.
+Recommended for resource constrained/virtualized environments.
+This wait strategy is not xref:manual/garbagefree.adoc[garbage free].
+
+Timeout:: a variation of the `Block` strategy that will periodically wake up 
from the lock condition `await()` call.
+This ensures that if a notification is missed somehow the consumer thread is 
not stuck but will recover with a small latency delay, see 
<<log4j2.asyncLoggerTimeout>>.
+This wait strategy is xref:manual/garbagefree.adoc[garbage free].
+
+Sleep:: a strategy that initially spins, then uses a `Thread.yield()`, and 
eventually parks for the minimum number of nanos the OS and JVM will allow 
while the I/O thread is waiting for log events (see 
<<log4j2.asyncLoggerRetries>> and <<log4j2.asyncLoggerSleepTimeNs>>).
+Sleep is a good compromise between performance and CPU resource.
+This strategy has very low impact on the application thread, in exchange for 
some additional latency for actually getting the message logged.
+This wait strategy is xref:manual/garbagefree.adoc[garbage free].
+
+Yield:: is a strategy that uses a `Thread.yield()` for waiting for log events 
after an initially spinning.
+Yield is a good compromise between performance and CPU resource, but may use 
more CPU than `Sleep` in order to get the message logged to disk sooner.
+This wait strategy is xref:manual/garbagefree.adoc[garbage free].
+
+[id=log4j2.asyncLoggerTimeout]
+== `log4j2.asyncLoggerTimeout`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_TIMEOUT
+| Type          | `int`
+| Default value | `10`
+|===
+
+Timeout in milliseconds of `Timeout` wait strategy (see 
<<log4j2.asyncLoggerWaitStrategy>>).
+
+[id=log4j2.asyncLoggerSleepTimeNs]
+== `log4j2.asyncLoggerSleepTimeNs`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_SLEEP_TIME_NS
+| Type          | `long`
+| Default value | `100`
+|===
+
+Sleep time in nanoseconds of `Sleep` wait strategy (see 
<<log4j2.asyncLoggerWaitStrategy>>).
+
+[id=log4j2.asyncLoggerRetries]
+== `log4j2.asyncLoggerRetries`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_RETRIES
+| Type          | `int`
+| Default value | `200`
+|===
+
+Total number of spin cycles and `Thread.yield()` cycles of `Sleep` (see 
<<log4j2.asyncLoggerWaitStrategy>>).
+
+[id=log4j2.asyncLoggerSynchronizeEnqueueWhenQueueFull]
+== `log4j2.asyncLoggerSynchronizeEnqueueWhenQueueFull`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_SYNCHRONIZE_ENQUEUE_WHEN_QUEUE_FULL
+| Type          | `boolean`
+| Default value | `true`
+|===
+
+Synchronizes access to the Disruptor ring buffer for blocking enqueue 
operations when the queue is full.
+Users encountered excessive CPU utilization with Disruptor v3.4.2 when the 
application was logging more than the underlying appender could keep up with 
and the ring buffer became full, especially when the number of application 
threads vastly outnumbered the number of cores.
+CPU utilization is significantly reduced by restricting access to the enqueue 
operation.
+Setting this value to `false` may lead to very high CPU utilization when the 
async logging queue is full.
+
+[id=log4j2.asyncLoggerThreadNameStrategy]
+== `log4j2.asyncLoggerThreadNameStrategy`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ASYNC_LOGGER_HREAD_NAME_STRATEGY
+| Type          | 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy[ThreadNameCachingStrategy]
 (enumeration)
+| Default value | `UNCACHED` for JRE 8u102 or later,
+
+`CACHED` otherwise
+|===
+
+Specifies the 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/ThreadNameCachingStrategy[ThreadNameCachingStrategy]
 to use to cache the result of 
https://docs.oracle.com/javase/{java-target-version}/docs/api/java/lang/Thread.html#getName--[Thread.getName()].
+
+This setting allows to cache the result of `Thread.getName()` calls and has 
two values:
+
+CACHED:: stores the name of the current thread in a `ThreadLocal` field,
+UNCACHED:: disables caching.
+
+NOTE: Since JRE 8u102 the `Thread.getName()` method does **not** allocate a 
new object.
diff --git 
a/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc 
b/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc
new file mode 100644
index 0000000000..9b0765e653
--- /dev/null
+++ b/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc
@@ -0,0 +1,118 @@
+////
+    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.
+////
+[id=log4j2.enableDirectEncoders]
+== `log4j2.enableDirectEncoders`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ENABLE_DIRECT_ENCODERS
+| Type          | `boolean`
+| Default value | `true`
+|===
+
+If `true`, garbage-aware layouts will directly encode log events into 
https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html[ByteBuffer]s 
provided by appenders.
+
+This prevents allocating temporary `String` and `char[]` instances.
+
+[id=log4j2.encoderByteBufferSize]
+== `log4j2.encoderByteBufferSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ENCODER_BYTE_BUFFER_SIZE
+| Type          | `int`
+| Default value | `8192`
+|===
+
+The size in bytes of the 
link:../https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html[ByteBuffer]s
 stored in `ThreadLocal` fields by layouts and 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/layout/StringBuilderEncoder[StringBuilderEncoder]s.
+
+This setting is only used if <<log4j2.enableDirectEncoders>> is set to `true`.
+
+[id=log4j2.encoderCharBufferSize]
+== `log4j2.encoderCharBufferSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ENCODER_CHAR_BUFFER_SIZE
+| Type          | `int`
+| Default value | `4096`
+|===
+
+The size in ``char``s of the 
link:../https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html[ByteBuffer]s
 stored in `ThreadLocal` fields 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/layout/StringBuilderEncoder[StringBuilderEncoder]s.
+
+This setting is only used if <<log4j2.enableDirectEncoders>> is set to `true`.
+
+// tag::api[]
+
+[id=log4j2.initialReusableMsgSize]
+== `log4j2.initialReusableMsgSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_INITIAL_REUSABLE_MSG_SIZE
+| Type          | `int`
+| Default value | `128`
+|===
+
+In GC-free mode, this property determines the initial size of the reusable 
``StringBuilder``s used by 
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages]
 for formatting purposes.
+
+[id=log4j2.maxReusableMsgSize]
+== `log4j2.maxReusableMsgSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_MAX_REUSABLE_MSG_SIZE
+| Type          | `int`
+| Default value | `518`
+|===
+
+In GC-free mode, this property determines the maximum size of the reusable 
``StringBuilder``s used by 
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages]
 for formatting purposes.
+
+The default value allows is equal to `2 &times; (2 &times; 
log4j.initialReusableMsgSize + 2) + 2` and allows the
+`StringBuilder` to be resized twice by the current JVM resize algorithm.
+
+// end::api[]
+
+[id=log4j2.layoutStringBuilderMaxSize]
+== `log4j2.layoutStringBuilderMaxSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_LAYOUT_STRING_BUILDER_MAX_SIZE
+| Type          | `int`
+| Default value | `2048`
+|===
+
+This property determines the maximum size of the reusable ``StringBuilder``s 
used to format 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/LogEvent[LogEvents].
+
+// tag::api[]
+
+[id=log4j2.unboxRingbufferSize]
+== `log4j2.unboxRingbufferSize`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_UNBOX_RINGBUFFER_SIZE
+| Type          | `int`
+| Default value | `32`
+|===
+
+The link:../javadoc/log4j-api/org/apache/logging/log4j/util/Unbox[Unbox] 
utility class can be used by users to format primitive values without incurring 
in the boxing allocation cost.
+
+This property specifies the maximum number of primitive arguments to a log 
message that will be cached and usually does not need to be changed.
+
+// end::api[]
diff --git a/src/site/antora/modules/ROOT/partials/properties-meta.adoc 
b/src/site/antora/modules/ROOT/partials/properties-meta.adoc
new file mode 100644
index 0000000000..088ed5d351
--- /dev/null
+++ b/src/site/antora/modules/ROOT/partials/properties-meta.adoc
@@ -0,0 +1,52 @@
+////
+    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.
+////
+[id=log4j2.isWebapp]
+== `log4j2.isWebapp`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_IS_WEBAPP
+| Type          | `boolean`
+| Default value | `true` if the 
https://jakarta.ee/specifications/servlet/6.0/apidocs/jakarta.servlet/jakarta/servlet/servlet[Servlet]
 class on classpath,
+
+`false` otherwise
+|===
+
+Setting this property to `true` switches Log4j Core into "Web application 
mode" (_"Web-app mode"_).
+
+In this mode Log4j is optimized to work in a Servlet container.
+
+This mode is incompatible with <<log4j2.enableThreadlocals>>.
+
+[id=log4j2.enableThreadlocals]
+== `log4j2.enableThreadlocals`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_ENABLE_THREADLOCALS
+| Type          | `boolean`
+| Default value | `false` if Web-app mode is enabled,
+
+`true` otherwise
+|===
+
+Setting this property to `true` switches Log4j Core into "garbage-free mode" 
(_"GC-free mode"_).
+
+In this mode Log4j uses ``ThreadLocal``s for object pooling to prevent object 
allocations.
+
+https://docs.oracle.com/en/java/javase/{java-target-version}/docs/api/java.base/java/lang/ThreadLocal.html[`ThreadLocal`]
 fields holding non-JDK classes can cause memory leaks in web applications when 
the application server's thread pool continues to reference these fields after 
the web application is undeployed.
+Hence, to avoid causing memory leaks, `log4j2.enableThreadlocals` by default 
reflects the opposite of xref:#log4j2.isWebapp[`log4j2.isWebapp`].
diff --git 
a/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc 
b/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc
new file mode 100644
index 0000000000..a3936eb2e4
--- /dev/null
+++ b/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc
@@ -0,0 +1,101 @@
+////
+    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.
+////
+[id=log4j2.disableThreadContext]
+== `log4j2.disableThreadContext`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_DISABLE_THREAD_CONTEXT
+| Type          | `boolean`
+| Default value | `false`
+|===
+
+If `true`, the `ThreadContext` stack and map are disabled.
+
+[id=log4j2.disableThreadContextStack]
+== `log4j2.disableThreadContextStack`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_DISABLE_THREAD_CONTEXT_STACK
+| Type          | `boolean`
+| Default value | `false`
+|===
+
+If `true`, the `ThreadContext` stack is disabled.
+
+[id=log4j2.disableThreadContextMap]
+== `log4j2.disableThreadContextMap`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_DISABLE_THREAD_CONTEXT_MAP
+| Type          | `boolean`
+| Default value | `false`
+|===
+
+If `true`, the `ThreadContext` map is disabled.
+
+// tag::gcfree[]
+
+[id=log4j2.threadContextMap]
+== `log4j2.threadContextMap`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_THREAD_CONTEXT_MAP
+| Type          | 
link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[Class<? 
extends ThreadContextMap>] or predefined constant
+| Default value | `WebApp`
+
+(GC-free mode: `CopyOnWrite`)
+|===
+
+Fully specified class name of a custom 
link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[ThreadContextMap]
 implementation class or one of the predefined constants:
+
+NoOp:: to disable the thread context,
+WebApp:: a web application-safe implementation, that only binds JRE classes to 
`ThreadLocal` to prevent memory leaks,
+CopyOnWrite:: a copy-on-write implementation,
+GarbageFree:: a garbage-free implementation.
+
+// end::gcfree[]
+
+[id=isThreadContextMapInheritable]
+== `log4j2.isThreadContextMapInheritable`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_IS_THREAD_CONTEXT_MAP_INHERITABLE
+| Type          | `boolean`
+| Default value | `false`
+|===
+
+If `true` uses an `InheritableThreadLocal` to copy the thread context map to 
newly created threads.
+
+// tag::gcfree[]
+
+[id=log4j2.garbagefreeThreadContextMap]
+== `log4j2.garbagefreeThreadContextMap`
+
+[cols="1h,5"]
+|===
+| Env. variable | LOG4J_GARBAGEFREE_THREAD_CONTEXT_MAP
+| Default value | `false`
+|===
+
+If set to `true` selects a garbage-free thread context map implementation.
+
+// end::gcfree[]

Reply via email to