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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to