You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2019/12/31 14:47:41 UTC
[logging-log4j2] branch master updated: LOG4J2-2752:
MutableLogEvent and RingBufferLogEvent lazily create buffers
This is an automated email from the ASF dual-hosted git repository.
ckozak pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/master by this push:
new 8504933 LOG4J2-2752: MutableLogEvent and RingBufferLogEvent lazily create buffers
8504933 is described below
commit 8504933502bd9e6cf801968adda4c85532a0ea7b
Author: Carter Kozak <ck...@ckozak.net>
AuthorDate: Mon Dec 30 17:12:11 2019 -0500
LOG4J2-2752: MutableLogEvent and RingBufferLogEvent lazily create buffers
When reusable events are used with non-reusable message implementations
(ParameterizedMessageFactory) there's no need to create these buffers.
---
.../log4j/core/async/RingBufferLogEvent.java | 31 +++++++++++-----------
.../logging/log4j/core/impl/MutableLogEvent.java | 16 +++++------
.../log4j/core/impl/MutableLogEventTest.java | 5 ++++
src/changes/changes.xml | 3 +++
4 files changed, 29 insertions(+), 26 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index 030ce56..0434eb6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -60,12 +60,7 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
@Override
public RingBufferLogEvent newInstance() {
- final RingBufferLogEvent result = new RingBufferLogEvent();
- if (Constants.ENABLE_THREADLOCALS) {
- result.messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
- result.parameters = new Object[10];
- }
- return result;
+ return new RingBufferLogEvent();
}
}
@@ -134,10 +129,8 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
final ReusableMessage reusable = (ReusableMessage) msg;
reusable.formatTo(getMessageTextForWriting());
messageFormat = reusable.getFormat();
- if (parameters != null) {
- parameters = reusable.swapParameters(parameters);
- parameterCount = reusable.getParameterCount();
- }
+ parameters = reusable.swapParameters(parameters == null ? new Object[10] : parameters);
+ parameterCount = reusable.getParameterCount();
} else {
this.message = InternalAsyncUtil.makeMessageImmutable(msg);
}
@@ -145,8 +138,8 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
private StringBuilder getMessageTextForWriting() {
if (messageText == null) {
- // Should never happen:
- // only happens if user logs a custom reused message when Constants.ENABLE_THREADLOCALS is false
+ // Happens the first time messageText is requested or if a user logs
+ // a custom reused message when Constants.ENABLE_THREADLOCALS is false
messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
}
messageText.setLength(0);
@@ -412,12 +405,18 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
}
// ensure that excessively long char[] arrays are not kept in memory forever
- StringBuilders.trimToMaxSize(messageText, Constants.MAX_REUSABLE_MESSAGE_SIZE);
+ if (Constants.ENABLE_THREADLOCALS) {
+ StringBuilders.trimToMaxSize(messageText, Constants.MAX_REUSABLE_MESSAGE_SIZE);
- if (parameters != null) {
- for (int i = 0; i < parameters.length; i++) {
- parameters[i] = null;
+ if (parameters != null) {
+ Arrays.fill(parameters, null);
}
+ } else {
+ // A user may have manually logged a ReusableMessage implementation, when thread locals are
+ // disabled we remove the reference in order to avoid permanently holding references to these
+ // buffers.
+ messageText = null;
+ parameters = null;
}
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
index e38afae..7674491 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -69,7 +69,8 @@ public class MutableLogEvent implements LogEvent, ReusableMessage, ParameterVisi
transient boolean reserved = false;
public MutableLogEvent() {
- this(new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE), new Object[10]);
+ // messageText and the parameter array are lazily initialized
+ this(null, null);
}
public MutableLogEvent(final StringBuilder msgText, final Object[] replacementParameters) {
@@ -148,9 +149,7 @@ public class MutableLogEvent implements LogEvent, ReusableMessage, ParameterVisi
StringBuilders.trimToMaxSize(messageText, Constants.MAX_REUSABLE_MESSAGE_SIZE);
if (parameters != null) {
- for (int i = 0; i < parameters.length; i++) {
- parameters[i] = null;
- }
+ Arrays.fill(parameters, null);
}
// primitive fields that cannot be cleared:
@@ -214,10 +213,8 @@ public class MutableLogEvent implements LogEvent, ReusableMessage, ParameterVisi
final ReusableMessage reusable = (ReusableMessage) msg;
reusable.formatTo(getMessageTextForWriting());
this.messageFormat = msg.getFormat();
- if (parameters != null) {
- parameters = reusable.swapParameters(parameters);
- parameterCount = reusable.getParameterCount();
- }
+ parameters = reusable.swapParameters(parameters == null ? new Object[10] : parameters);
+ parameterCount = reusable.getParameterCount();
} else {
this.message = InternalAsyncUtil.makeMessageImmutable(msg);
}
@@ -225,8 +222,7 @@ public class MutableLogEvent implements LogEvent, ReusableMessage, ParameterVisi
private StringBuilder getMessageTextForWriting() {
if (messageText == null) {
- // Should never happen:
- // only happens if user logs a custom reused message when Constants.ENABLE_THREADLOCALS is false
+ // Happens the first time messageText is requested
messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
}
messageText.setLength(0);
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
index a1f4f91..7e94ca6 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
@@ -31,6 +31,7 @@ import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.message.ReusableMessageFactory;
+import org.apache.logging.log4j.message.ReusableSimpleMessage;
import org.apache.logging.log4j.message.SimpleMessage;
import org.apache.logging.log4j.util.FilteredObjectInputStream;
import org.apache.logging.log4j.util.SortedArrayStringMap;
@@ -189,6 +190,10 @@ public class MutableLogEventTest {
@Test
public void testClear() {
final MutableLogEvent mutable = new MutableLogEvent();
+ // initialize the event with an empty message
+ ReusableSimpleMessage simpleMessage = new ReusableSimpleMessage();
+ simpleMessage.set("");
+ mutable.setMessage(simpleMessage);
assertEquals("context data", 0, mutable.getContextData().size());
assertNull("context stack", mutable.getContextStack());
assertFalse("end of batch", mutable.isEndOfBatch());
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 92222b6..3bc396f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -193,6 +193,9 @@
<action issue="LOG4J2-2751" dev="ckozak" type="fix">
Fix StackLocator.getCallerClass performance in cases where Reflection.getCallerClass is not accessible.
</action>
+ <action issue="LOG4J2-2752" dev="ckozak" type="fix">
+ MutableLogEvent and RingBufferLogEvent avoid StringBuffer and parameter array allocation unless reusable messages are used.
+ </action>
</release>
<release version="2.13.0" date="2019-12-11" description="GA Release 2.13.0">
<action issue="LOG4J2-2058" dev="rgoers" type="fix">