You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2018/12/25 22:49:26 UTC
[myfaces] branch 2.3.x updated: [perf] optimize TagAttributesImpl
access
This is an automated email from the ASF dual-hosted git repository.
tandraschko pushed a commit to branch 2.3.x
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/2.3.x by this push:
new b044b21 [perf] optimize TagAttributesImpl access
b044b21 is described below
commit b044b212f4dde0801e4f7ddb18d1d0b7fb8dd008
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Tue Dec 25 23:49:38 2018 +0100
[perf] optimize TagAttributesImpl access
---
.../view/facelets/tag/TagAttributesImpl.java | 140 +++++++++------------
.../view/facelets/tag/TagAttributesImplTest.java | 59 +++++++++
2 files changed, 119 insertions(+), 80 deletions(-)
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributesImpl.java b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributesImpl.java
index 52694e6..dcdf070 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributesImpl.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributesImpl.java
@@ -20,8 +20,10 @@ package org.apache.myfaces.view.facelets.tag;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.faces.view.facelets.TagAttribute;
@@ -29,12 +31,7 @@ import javax.faces.view.facelets.TagAttributes;
/**
* A set of TagAttributes, usually representing all attributes on a Tag.
- *
- * TODO: PROFILE - Explore the possibility of using HashMap instead of sorted arrays.
- * The footprint should be higher, but the instanciation and access speed should be faster
- * Instanciation: from O(n log n) to O(1)
- * Access: from O(log n) to O(1)
- *
+ *
* See org.apache.myfaces.view.facelets.tag.Tag
* See org.apache.myfaces.view.facelets.tag.TagAttributeImpl
* @author Jacob Hookom
@@ -44,47 +41,52 @@ public final class TagAttributesImpl extends TagAttributes
{
private final static TagAttribute[] EMPTY = new TagAttribute[0];
- private final TagAttribute[] _attributes;
-
- private final String[] _namespaces;
-
- private final List<TagAttribute[]> _nsattrs;
+ private final TagAttribute[] attributes;
+ private final String[] namespaces;
+ private final HashMap<String, TagAttribute[]> namespaceAttributes;
+ private final HashMap<String, Map<String, TagAttribute>> namespaceLocalNameAttributes;
- /**
- *
- */
- public TagAttributesImpl(TagAttribute[] attrs)
+ public TagAttributesImpl(TagAttribute[] attributes)
{
- _attributes = attrs;
-
- // grab namespaces
- Set<String> set = new HashSet<String>();
- for (TagAttribute attribute : _attributes)
- {
- set.add(attribute.getNamespace());
- }
+ this.attributes = attributes;
+ this.namespaceAttributes = new HashMap<>(3);
+ this.namespaceLocalNameAttributes = new HashMap<>(3);
- _namespaces = set.toArray(new String[set.size()]);
- Arrays.sort(_namespaces);
-
- // assign attrs
- int size = _namespaces.length;
- List<List<TagAttribute>> temp = new ArrayList<List<TagAttribute>>(size);
- for (int i = 0; i < size; i++)
- {
- temp.add(new ArrayList<TagAttribute>());
- }
+ Set<String> namespacesSet = new HashSet<>();
+ HashMap<String, List<TagAttribute>> namespaceAttributesAsList = new HashMap<>();
- for (TagAttribute attribute : _attributes)
+ for (TagAttribute attribute : attributes)
{
- temp.get(Arrays.binarySearch(_namespaces, attribute.getNamespace())).add(attribute);
+ namespacesSet.add(attribute.getNamespace());
+
+
+ List<TagAttribute> tagAttributes = namespaceAttributesAsList.get(attribute.getNamespace());
+ if (tagAttributes == null)
+ {
+ tagAttributes = new ArrayList<>(attributes.length);
+ namespaceAttributesAsList.put(attribute.getNamespace(), tagAttributes);
+ }
+ tagAttributes.add(attribute);
+
+
+ Map<String, TagAttribute> localeNameAttributes = namespaceLocalNameAttributes.get(attribute.getNamespace());
+ if (localeNameAttributes == null)
+ {
+ localeNameAttributes = new HashMap<>(attributes.length);
+ namespaceLocalNameAttributes.put(attribute.getNamespace(), localeNameAttributes);
+ }
+ localeNameAttributes.put(attribute.getLocalName(), attribute);
}
+
+
+ this.namespaces = namespacesSet.toArray(new String[namespacesSet.size()]);
+ Arrays.sort(this.namespaces);
- _nsattrs = new ArrayList<TagAttribute[]>(size);
- for (int i = 0; i < size; i++)
+ for (Map.Entry<String, List<TagAttribute>> entry : namespaceAttributesAsList.entrySet())
{
- List<TagAttribute> l = temp.get(i);
- _nsattrs.add(l.toArray(new TagAttribute[l.size()]));
+ String key = entry.getKey();
+ List<TagAttribute> value = entry.getValue();
+ this.namespaceAttributes.put(key, value.toArray(new TagAttribute[value.size()]));
}
}
@@ -93,19 +95,20 @@ public final class TagAttributesImpl extends TagAttributes
*
* @return a non-null array of TagAttributes
*/
+ @Override
public TagAttribute[] getAll()
{
- return _attributes;
+ return attributes;
}
/**
* Using no namespace, find the TagAttribute
*
* See #get(String, String)
- * @param localName
- * tag attribute name
+ * @param localName tag attribute name
* @return the TagAttribute found, otherwise null
*/
+ @Override
public TagAttribute get(String localName)
{
return get("", localName);
@@ -114,57 +117,33 @@ public final class TagAttributesImpl extends TagAttributes
/**
* Find a TagAttribute that matches the passed namespace and local name.
*
- * @param ns
- * namespace of the desired attribute
- * @param localName
- * local name of the attribute
+ * @param ns namespace of the desired attribute
+ * @param localName local name of the attribute
* @return a TagAttribute found, otherwise null
*/
+ @Override
public TagAttribute get(String ns, String localName)
{
- if (ns != null && localName != null)
+ Map<String, TagAttribute> nsAttributes = namespaceLocalNameAttributes.get(ns);
+ if (nsAttributes != null)
{
- int idx = Arrays.binarySearch(_namespaces, ns);
- if (idx >= 0)
- {
- for (TagAttribute attribute : _nsattrs.get(idx))
- {
- if (localName.equals(attribute.getLocalName()))
- {
- return attribute;
- }
- }
- }
+ return nsAttributes.get(localName);
}
-
+
return null;
}
/**
* Get all TagAttributes for the passed namespace
*
- * @param namespace
- * namespace to search
+ * @param namespace namespace to search
* @return a non-null array of TagAttributes
*/
+ @Override
public TagAttribute[] getAll(String namespace)
{
- int idx = 0;
- if (namespace == null)
- {
- idx = Arrays.binarySearch(_namespaces, "");
- }
- else
- {
- idx = Arrays.binarySearch(_namespaces, namespace);
- }
-
- if (idx >= 0)
- {
- return _nsattrs.get(idx);
- }
-
- return EMPTY;
+ TagAttribute[] retVal = namespaceAttributes.get(namespace);
+ return retVal == null ? EMPTY : retVal;
}
/**
@@ -172,9 +151,10 @@ public final class TagAttributesImpl extends TagAttributes
*
* @return a list of Namespaces found in this set
*/
+ @Override
public String[] getNamespaces()
{
- return _namespaces;
+ return namespaces;
}
/*
@@ -185,8 +165,8 @@ public final class TagAttributesImpl extends TagAttributes
@Override
public String toString()
{
- StringBuffer sb = new StringBuffer();
- for (TagAttribute attribute : _attributes)
+ StringBuilder sb = new StringBuilder();
+ for (TagAttribute attribute : attributes)
{
sb.append(attribute);
sb.append(' ');
diff --git a/impl/src/test/java/org/apache/myfaces/view/facelets/tag/TagAttributesImplTest.java b/impl/src/test/java/org/apache/myfaces/view/facelets/tag/TagAttributesImplTest.java
new file mode 100644
index 0000000..86f5717
--- /dev/null
+++ b/impl/src/test/java/org/apache/myfaces/view/facelets/tag/TagAttributesImplTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.myfaces.view.facelets.tag;
+
+import java.util.Arrays;
+import javax.faces.view.facelets.TagAttribute;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TagAttributesImplTest
+{
+ @Test
+ public void testNamespaceMapping()
+ {
+ TagAttributeImpl test1 = new TagAttributeImpl(null, "", "test1", null, "");
+ TagAttributeImpl test2 = new TagAttributeImpl(null, "", "test2", null, "");
+ TagAttributeImpl testTest1 = new TagAttributeImpl(null, "test", "test1", null, "");
+
+ TagAttributesImpl impl = new TagAttributesImpl(new TagAttribute[] { test1, test2, testTest1 });
+ Assert.assertEquals(test1, impl.get("test1"));
+ Assert.assertEquals(test2, impl.get("test2"));
+
+ Assert.assertEquals(testTest1, impl.get("test", "test1"));
+
+
+ Assert.assertEquals(3, Arrays.asList(impl.getAll()).size());
+ Assert.assertTrue(Arrays.asList(impl.getAll()).contains(test1));
+ Assert.assertTrue(Arrays.asList(impl.getAll()).contains(test2));
+ Assert.assertTrue(Arrays.asList(impl.getAll()).contains(testTest1));
+
+ Assert.assertEquals(2, Arrays.asList(impl.getAll("")).size());
+ Assert.assertTrue(Arrays.asList(impl.getAll()).contains(test1));
+ Assert.assertTrue(Arrays.asList(impl.getAll()).contains(test2));
+ }
+
+ @Test
+ public void testNotAvailable()
+ {
+ TagAttributesImpl impl = new TagAttributesImpl(new TagAttribute[] { });
+ Assert.assertEquals(null, impl.get("test1"));
+ Assert.assertEquals(null, impl.get("test", "test2"));
+ }
+}