You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by st...@apache.org on 2015/12/11 16:29:08 UTC
svn commit: r1719457 - in /openwebbeans/trunk/webbeans-impl/src:
main/java/org/apache/webbeans/container/
test/java/org/apache/webbeans/test/annotation/binding/
test/java/org/apache/webbeans/test/performance/
Author: struberg
Date: Fri Dec 11 15:29:08 2015
New Revision: 1719457
URL: http://svn.apache.org/viewvc?rev=1719457&view=rev
Log:
OWB-1034 improve BeanCacheKey performance
we actually don't need such a good qualifier hash as all gets compared
later anyways. So we now only look at the annotationTypes hash
and be good.
I also enabled a special handling for qualifiers which are known
to have no parameters.
Added:
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/performance/BeanResolvingPerformanceTest.java (with props)
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java?rev=1719457&r1=1719456&r2=1719457&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/container/BeanCacheKey.java Fri Dec 11 15:29:08 2015
@@ -18,6 +18,7 @@
*/
package org.apache.webbeans.container;
+import org.apache.webbeans.annotation.EmptyAnnotationLiteral;
import org.apache.webbeans.util.AnnotationUtil;
import javax.enterprise.util.Nonbinding;
@@ -177,96 +178,16 @@ public final class BeanCacheKey
}
/**
- * Calculate the hashCode() of a qualifier, which ignores {@link Nonbinding} members.
+ * Calculate the hashCode() of a qualifier.
+ * We do not do any in-depth hashCode down to member hashes
+ * but only use the hashcode of the AnnotationType itself.
+ * This is WAY faster and spreads well enough in practice.
+ * We can do this as we do not need to return a perfectly unique
+ * result anyway.
*/
private int getQualifierHashCode(Annotation a)
{
- Class annotationClass = getAnnotationClass(a.getClass());
-
- if (annotationClass == null)
- {
- return getTypeHashCode(a.getClass());
- }
-
- // the hashCode of an Annotation is calculated solely via the hashCodes
- // of it's members. If there are no members, it is 0.
- // thus we first need to get the annotation-class hashCode
- int hashCode = getTypeHashCode(annotationClass);
-
- // and now add the hashCode of all it's Nonbinding members
- // the following algorithm is defined by the Annotation class definition
- // see the JavaDoc for Annotation!
- // we only change it so far that we skip evaluating @Nonbinding members
- final Method[] members = annotationClass.getDeclaredMethods();
-
- for (Method member : members)
- {
- if (member.isAnnotationPresent(Nonbinding.class))
- {
- // ignore the non binding
- continue;
- }
-
- // Member value
- final Object object = callMethod(a, member);
- final int value;
- if(object.getClass().isArray())
- {
- Class<?> type = object.getClass().getComponentType();
- if(type.isPrimitive())
- {
- if(Long.TYPE == type)
- {
- value = Arrays.hashCode((long[]) object);
- }
- else if(Integer.TYPE == type)
- {
- value = Arrays.hashCode((int[])object);
- }
- else if(Short.TYPE == type)
- {
- value = Arrays.hashCode((short[])object);
- }
- else if(Double.TYPE == type)
- {
- value = Arrays.hashCode((double[])object);
- }
- else if(Float.TYPE == type)
- {
- value = Arrays.hashCode((float[])object);
- }
- else if(Boolean.TYPE == type)
- {
- value = Arrays.hashCode((boolean[])object);
- }
- else if(Byte.TYPE == type)
- {
- value = Arrays.hashCode((byte[])object);
- }
- else if(Character.TYPE == type)
- {
- value = Arrays.hashCode((char[])object);
- }
- else
- {
- value = 0;
- }
- }
- else
- {
- value = Arrays.hashCode((Object[])object);
- }
- }
- else
- {
- value = object.hashCode();
- }
-
- hashCode = 29 * hashCode + value;
- hashCode = 29 * hashCode + member.getName().hashCode();
- }
-
- return hashCode;
+ return a.annotationType().hashCode();
}
/**
@@ -277,17 +198,6 @@ public final class BeanCacheKey
return ANNOTATION_COMPARATOR.compare(qualifier1, qualifier2) == 0;
}
- private static Class getAnnotationClass(Class a)
- {
- for (Class i : a.getInterfaces())
- {
- if (i.isAnnotation())
- {
- return i;
- }
- }
- return null;
- }
/**
* Helper method for calculating the hashCode of an annotation.
@@ -338,6 +248,13 @@ public final class BeanCacheKey
{
return temp;
}
+ if (annotation1 instanceof EmptyAnnotationLiteral || annotation2 instanceof EmptyAnnotationLiteral)
+ {
+ // if any of those 2 annotations are known to have no members
+ // then we can immediately return as we know the 2 annotations mean the same
+ return 0;
+ }
+
final Method[] member1 = type1.getDeclaredMethods();
final Method[] member2 = type2.getDeclaredMethods();
Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java?rev=1719457&r1=1719456&r2=1719457&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/annotation/binding/BeanCacheKeyUnitTest.java Fri Dec 11 15:29:08 2015
@@ -175,7 +175,6 @@ public class BeanCacheKeyUnitTest
BeanCacheKey a = new BeanCacheKey(true, String.class, null, a1);
BeanCacheKey b = new BeanCacheKey(true, String.class, null, a2);
Assert.assertFalse(a.equals(b));
- Assert.assertFalse(a.hashCode() == b.hashCode());
}
@Test
@@ -230,7 +229,6 @@ public class BeanCacheKeyUnitTest
BeanCacheKey a = new BeanCacheKey(true, String.class, null, a4);
BeanCacheKey b = new BeanCacheKey(true, String.class, null, a5);
Assert.assertFalse(a.equals(b));
- Assert.assertFalse(a.hashCode() == b.hashCode());
}
@Test
@@ -257,7 +255,6 @@ public class BeanCacheKeyUnitTest
BeanCacheKey a = new BeanCacheKey(true, String.class, null, a7);
BeanCacheKey b = new BeanCacheKey(true, String.class, null, a8);
Assert.assertFalse(a.equals(b));
- Assert.assertFalse(a.hashCode() == b.hashCode());
}
@Test
@@ -266,7 +263,6 @@ public class BeanCacheKeyUnitTest
BeanCacheKey a = new BeanCacheKey(true, String.class, null, a9);
BeanCacheKey b = new BeanCacheKey(true, String.class, null, aa);
Assert.assertFalse(a.equals(b));
- Assert.assertFalse(a.hashCode() == b.hashCode());
}
@Test
@@ -275,7 +271,6 @@ public class BeanCacheKeyUnitTest
BeanCacheKey a = new BeanCacheKey(true, String.class, null, ab);
BeanCacheKey b = new BeanCacheKey(true, String.class, null, ac);
Assert.assertFalse(a.equals(b));
- Assert.assertFalse(a.hashCode() == b.hashCode());
}
@Test
Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/performance/BeanResolvingPerformanceTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/performance/BeanResolvingPerformanceTest.java?rev=1719457&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/performance/BeanResolvingPerformanceTest.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/performance/BeanResolvingPerformanceTest.java Fri Dec 11 15:29:08 2015
@@ -0,0 +1,79 @@
+/*
+ * 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.webbeans.test.performance;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.spi.BeanManager;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import org.apache.webbeans.test.AbstractUnitTest;
+import org.junit.Test;
+
+/**
+ * Test to benchmark the performance of bean resolving
+ */
+public class BeanResolvingPerformanceTest extends AbstractUnitTest
+{
+ private static final Logger logger = Logger.getLogger(BeanResolvingPerformanceTest.class.getName());
+
+ private static final int WARMUP_ITERATIONS = 10000;
+
+ // tune up to larger values to
+ private static final int BENCHMARK_ITERATIONS = 1000000;
+
+ /**
+ * original times with 10000000 iterations on my MBP
+ * started with 9885,9776,9868
+ * after qualifier hashCode tuning: 6177,6144,6075
+ * after qualifier-Comparator tuning: 1573,1453,1471
+ */
+ @Test
+ public void testBeanResolverPerformance()
+ {
+ startContainer(BeanWithDefaultQualifier.class);
+ BeanManager bm = getBeanManager();
+
+ for (int i= 0; i < WARMUP_ITERATIONS; i++)
+ {
+ getBeans(bm);
+ }
+
+ long start = System.nanoTime();
+ for (int i= 0; i < BENCHMARK_ITERATIONS; i++)
+ {
+ getBeans(bm);
+ }
+ long end = System.nanoTime();
+ logger.info("Resolving a bean " + BENCHMARK_ITERATIONS + " times took ms: " + TimeUnit.NANOSECONDS.toMillis(end - start));
+ }
+
+ private void getBeans(BeanManager bm)
+ {
+ bm.getBeans(BeanWithDefaultQualifier.class);
+ }
+
+
+ @RequestScoped
+ public static class BeanWithDefaultQualifier
+ {
+ // no content needed
+ }
+}
Propchange: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/test/performance/BeanResolvingPerformanceTest.java
------------------------------------------------------------------------------
svn:eol-style = native