You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2021/06/18 11:44:50 UTC
[james-mime4j] 01/02: MIME4J-302 Parser should avoid multiple calls
to "toLowerCase"
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-mime4j.git
commit a7a860d3eab7539c53a7d0ed0ea8ddd9e894e532
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Jun 17 15:13:20 2021 +0700
MIME4J-302 Parser should avoid multiple calls to "toLowerCase"
I was surprised MIME4J parsing spends 18% of its time calling toLowerCase on header names. This represents 12% of allocated memory.
By holding the lowerCased name as part of the field name, and doing lazy initialization on it we can get this down to 6%.
---
.../james/mime4j/stream/FallbackBodyDescriptorBuilder.java | 2 +-
core/src/main/java/org/apache/james/mime4j/stream/Field.java | 9 +++++++++
.../main/java/org/apache/james/mime4j/stream/RawField.java | 11 +++++++++++
.../java/org/apache/james/mime4j/field/AbstractField.java | 12 ++++++++++++
.../org/apache/james/mime4j/field/DelegatingFieldParser.java | 10 +++++++++-
.../apache/james/mime4j/internal/AbstractEntityBuilder.java | 4 ++--
.../java/org/apache/james/mime4j/message/AbstractHeader.java | 4 ++--
.../james/mime4j/message/DefaultBodyDescriptorBuilder.java | 2 +-
8 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/FallbackBodyDescriptorBuilder.java b/core/src/main/java/org/apache/james/mime4j/stream/FallbackBodyDescriptorBuilder.java
index 2f0863a..4872654 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/FallbackBodyDescriptorBuilder.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/FallbackBodyDescriptorBuilder.java
@@ -117,7 +117,7 @@ class FallbackBodyDescriptorBuilder implements BodyDescriptorBuilder {
* @param field the MIME field.
*/
public Field addField(RawField field) throws MimeException {
- String name = field.getName().toLowerCase(Locale.US);
+ String name = field.getNameLowerCase();
if (name.equals("content-transfer-encoding") && transferEncoding == null) {
String value = field.getBody();
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/Field.java b/core/src/main/java/org/apache/james/mime4j/stream/Field.java
index 6c58dec..bde3c79 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/Field.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/Field.java
@@ -19,6 +19,8 @@
package org.apache.james.mime4j.stream;
+import java.util.Locale;
+
import org.apache.james.mime4j.util.ByteSequence;
/**
@@ -40,6 +42,13 @@ public interface Field {
String getName();
/**
+ * Returns the name of the field in lower case.
+ */
+ default String getNameLowerCase() {
+ return getName().toLowerCase(Locale.US);
+ }
+
+ /**
* Gets the unparsed and possibly encoded (see RFC 2047) field body string.
*
* @return the unparsed field body string.
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/RawField.java b/core/src/main/java/org/apache/james/mime4j/stream/RawField.java
index f263b99..8bcaa77 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/RawField.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/RawField.java
@@ -19,6 +19,8 @@
package org.apache.james.mime4j.stream;
+import java.util.Locale;
+
import org.apache.james.mime4j.util.ByteSequence;
import org.apache.james.mime4j.util.CharsetUtil;
import org.apache.james.mime4j.util.ContentUtil;
@@ -39,6 +41,7 @@ public final class RawField implements Field {
private final int delimiterIdx;
private final String name;
private final String body;
+ private String nameLowerCase;
RawField(ByteSequence raw, int delimiterIdx, String name, String body) {
if (name == null) {
@@ -62,6 +65,14 @@ public final class RawField implements Field {
return name;
}
+ @Override
+ public String getNameLowerCase() {
+ if (nameLowerCase == null) {
+ nameLowerCase = name.toLowerCase(Locale.US);
+ }
+ return nameLowerCase;
+ }
+
public String getBody() {
if (body != null) {
return body;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/AbstractField.java b/dom/src/main/java/org/apache/james/mime4j/field/AbstractField.java
index d4330d9..f0580a3 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/AbstractField.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/AbstractField.java
@@ -49,6 +49,18 @@ public abstract class AbstractField implements ParsedField {
return rawField.getName();
}
+
+ /**
+ * Gets the name of the field in lower case (<code>subject</code>,
+ * <code>from</code>, etc).
+ *
+ * @return the field name.
+ */
+ @Override
+ public String getNameLowerCase() {
+ return rawField.getNameLowerCase();
+ }
+
/**
* Gets the unfolded, unparsed and possibly encoded (see RFC 2047) field
* body string.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java b/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
index 008918f..727958b 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
@@ -55,8 +55,16 @@ public class DelegatingFieldParser implements FieldParser<ParsedField> {
return field;
}
+ private FieldParser<? extends ParsedField> getParser(final Field rawField) {
+ final FieldParser<? extends ParsedField> field = parsers.get(rawField.getNameLowerCase());
+ if (field == null) {
+ return defaultParser;
+ }
+ return field;
+ }
+
public ParsedField parse(final Field rawField, final DecodeMonitor monitor) {
- final FieldParser<? extends ParsedField> parser = getParser(rawField.getName());
+ final FieldParser<? extends ParsedField> parser = getParser(rawField);
return parser.parse(rawField, monitor);
}
}
diff --git a/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java b/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java
index 5b83625..c8f0871 100644
--- a/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java
+++ b/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java
@@ -65,7 +65,7 @@ public abstract class AbstractEntityBuilder {
* @param field the field to add.
*/
public AbstractEntityBuilder addField(Field field) {
- String lowerCasedFieldName = field.getName().toLowerCase(Locale.US);
+ String lowerCasedFieldName = field.getNameLowerCase();
List<Field> values = fieldMap.get(lowerCasedFieldName);
if (values == null) {
values = new LinkedList<Field>();
@@ -210,7 +210,7 @@ public abstract class AbstractEntityBuilder {
* @param field the field to set.
*/
public AbstractEntityBuilder setField(Field field) {
- final String lowerCaseName = field.getName().toLowerCase(Locale.US);
+ final String lowerCaseName = field.getNameLowerCase();
List<Field> l = fieldMap.get(lowerCaseName);
if (l == null || l.isEmpty()) {
addField(field);
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/AbstractHeader.java b/dom/src/main/java/org/apache/james/mime4j/message/AbstractHeader.java
index 63ac5af..c83de6f 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/AbstractHeader.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/AbstractHeader.java
@@ -67,7 +67,7 @@ public abstract class AbstractHeader implements Header {
* @param field the field to add.
*/
public void addField(Field field) {
- String lowerCaseFieldName = field.getName().toLowerCase(Locale.US);
+ String lowerCaseFieldName = field.getNameLowerCase();
List<Field> values = fieldMap.get(lowerCaseFieldName);
if (values == null) {
values = new LinkedList<Field>();
@@ -220,7 +220,7 @@ public abstract class AbstractHeader implements Header {
* @param field the field to set.
*/
public void setField(Field field) {
- final String lowerCaseName = field.getName().toLowerCase(Locale.US);
+ final String lowerCaseName = field.getNameLowerCase();
List<Field> l = fieldMap.get(lowerCaseName);
if (l == null || l.isEmpty()) {
addField(field);
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/DefaultBodyDescriptorBuilder.java b/dom/src/main/java/org/apache/james/mime4j/message/DefaultBodyDescriptorBuilder.java
index e3d5e7e..de8d5a2 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/DefaultBodyDescriptorBuilder.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/DefaultBodyDescriptorBuilder.java
@@ -88,7 +88,7 @@ public class DefaultBodyDescriptorBuilder implements BodyDescriptorBuilder {
public Field addField(final RawField rawfield) throws MimeException {
ParsedField field = fieldParser.parse(rawfield, monitor);
- String name = field.getName().toLowerCase(Locale.US);
+ String name = field.getNameLowerCase();
if (!fields.containsKey(name)) {
fields.put(name, field);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org