You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/11/08 16:41:37 UTC
logging-log4j2 git commit: LOG4J2-1679 (GC) Avoid allocating
temporary objects in StructuredDataFilter.
Repository: logging-log4j2
Updated Branches:
refs/heads/master 171f9a328 -> d494e5472
LOG4J2-1679 (GC) Avoid allocating temporary objects in StructuredDataFilter.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/d494e547
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/d494e547
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/d494e547
Branch: refs/heads/master
Commit: d494e54728fde0bac26fd5785e1330c70d3e25e0
Parents: 171f9a3
Author: rpopma <rp...@apache.org>
Authored: Wed Nov 9 01:41:33 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Wed Nov 9 01:41:33 2016 +0900
----------------------------------------------------------------------
.../log4j/core/filter/StructuredDataFilter.java | 73 +++++++++++++++++---
log4j-core/src/test/resources/gcFreeLogging.xml | 4 ++
.../resources/gcFreeMixedSyncAsyncLogging.xml | 4 ++
src/changes/changes.xml | 3 +
4 files changed, 75 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d494e547/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
index 1feed36..a4a661a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StructuredDataFilter.java
@@ -34,13 +34,20 @@ import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.util.KeyValuePair;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.StructuredDataMessage;
+import org.apache.logging.log4j.util.PerformanceSensitive;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+import org.apache.logging.log4j.util.StringBuilders;
/**
* Filter based on data in a StructuredDataMessage.
*/
@Plugin(name = "StructuredDataFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
+@PerformanceSensitive("allocation")
public final class StructuredDataFilter extends MapFilter {
+ private static final int MAX_BUFFER_SIZE = 2048;
+ private static ThreadLocal<StringBuilder> threadLocalStringBuilder = new ThreadLocal<>();
+
private StructuredDataFilter(final Map<String, List<String>> map, final boolean oper, final Result onMatch,
final Result onMismatch) {
super(map, oper, onMatch, onMismatch);
@@ -66,10 +73,11 @@ public final class StructuredDataFilter extends MapFilter {
protected Result filter(final StructuredDataMessage message) {
boolean match = false;
- for (final Map.Entry<String, List<String>> entry : getMap().entrySet()) {
- final String toMatch = getValue(message, entry.getKey());
+ final SortedArrayStringMap map = getStringMap();
+ for (int i = 0; i < map.size(); i++) {
+ final StringBuilder toMatch = getValue(message, map.getKeyAt(i));
if (toMatch != null) {
- match = entry.getValue().contains(toMatch);
+ match = listContainsValue((List<String>) map.getValueAt(i), toMatch);
} else {
match = false;
}
@@ -80,18 +88,65 @@ public final class StructuredDataFilter extends MapFilter {
return match ? onMatch : onMismatch;
}
- private String getValue(final StructuredDataMessage data, final String key) {
+ private StringBuilder getValue(final StructuredDataMessage data, final String key) {
+ final StringBuilder sb = getStringBuilder();
if (key.equalsIgnoreCase("id")) {
- return data.getId().toString();
+ data.getId().formatTo(sb);
+ return sb;
} else if (key.equalsIgnoreCase("id.name")) {
- return data.getId().getName();
+ return appendOrNull(data.getId().getName(), sb);
} else if (key.equalsIgnoreCase("type")) {
- return data.getType();
+ return appendOrNull(data.getType(), sb);
} else if (key.equalsIgnoreCase("message")) {
- return data.getFormattedMessage();
+ data.formatTo(sb);
+ return sb;
} else {
- return data.getData().get(key);
+ return appendOrNull(data.getDataValue(key), sb);
+ }
+ }
+
+ private StringBuilder getStringBuilder() {
+ StringBuilder result = threadLocalStringBuilder.get();
+ if (result == null) {
+ result = new StringBuilder();
+ threadLocalStringBuilder.set(result);
+ }
+ if (result.length() > MAX_BUFFER_SIZE) {
+ result.setLength(MAX_BUFFER_SIZE);
+ result.trimToSize();
+ }
+ result.setLength(0);
+ return result;
+ }
+
+ private StringBuilder appendOrNull(final String value, final StringBuilder sb) {
+ if (value == null) {
+ return null;
+ }
+ sb.append(value);
+ return sb;
+ }
+
+ private boolean listContainsValue(final List<String> candidates, final StringBuilder toMatch) {
+ if (toMatch == null) {
+ for (int i = 0; i < candidates.size(); i++) {
+ final String candidate = candidates.get(i);
+ if (candidate == null) {
+ return true;
+ }
+ }
+ } else {
+ for (int i = 0; i < candidates.size(); i++) {
+ final String candidate = candidates.get(i);
+ if (candidate == null) {
+ return false;
+ }
+ if (StringBuilders.equals(candidate, 0, candidate.length(), toMatch, 0, toMatch.length())) {
+ return true;
+ }
+ }
}
+ return false;
}
/**
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d494e547/log4j-core/src/test/resources/gcFreeLogging.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/gcFreeLogging.xml b/log4j-core/src/test/resources/gcFreeLogging.xml
index 1b38047..2c92e8c 100644
--- a/log4j-core/src/test/resources/gcFreeLogging.xml
+++ b/log4j-core/src/test/resources/gcFreeLogging.xml
@@ -14,6 +14,10 @@
<KeyValuePair key="User1" value="DEBUG"/>
<KeyValuePair key="User2" value="WARN"/>
</ContextMapFilter>
+ <StructuredDataFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
+ <KeyValuePair key="id" value="Login"/>
+ <KeyValuePair key="id" value="Logout"/>
+ </StructuredDataFilter>
</Filters>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d494e547/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml b/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
index 73c7d4b..24d1c90 100644
--- a/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
+++ b/log4j-core/src/test/resources/gcFreeMixedSyncAsyncLogging.xml
@@ -14,6 +14,10 @@
<KeyValuePair key="User1" value="DEBUG"/>
<KeyValuePair key="User2" value="WARN"/>
</ContextMapFilter>
+ <StructuredDataFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
+ <KeyValuePair key="id" value="Login"/>
+ <KeyValuePair key="id" value="Logout"/>
+ </StructuredDataFilter>
</Filters>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d494e547/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 1f69bde..ec8d7f1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,9 @@
</properties>
<body>
<release version="2.8" date="2016-MM-DD" description="GA Release 2.8">
+ <action issue="LOG4J2-1679" dev="rpopma" type="fix">
+ (GC) Avoid allocating temporary objects in StructuredDataFilter.
+ </action>
<action issue="LOG4J2-1678" dev="rpopma" type="fix">
(GC) Avoid allocating temporary objects in ThreadContextMapFilter.
</action>