Hi,

I propose a set of straightforward optimizations of annotations in the field of minimizing garbage creation and execution performance. Here's a webrev containing the changes:

http://cr.openjdk.java.net/~plevart/jdk8-tl/AnnotationOptimizations/webrev.01/


Changes grouped by class/method:


AnnotationInvocationHandler.invoke(): Use reference comparison among interned strings instead of equals() to dispatch the invocation and use Method.getParameterCount() instead of Method.getParameterTypes() to avoid creating Class[] array for each invocation.

AnnotationInvocationHandler.toStringImpl(): Use StringBuilder instead of StringBuffer

AnnotationInvocationHandler.equalsImpl(): Don't call asOneOfUs(o) in a loop for each member and restructure the code to have basically two independent implementations: the one based on memberValues map if the other annotation is "OneOfUs" (the common case) and the one based on AnnotationType.members() map of member methods. Caching of member methods privately in each AnnotationInvocationHandler instance is not needed - use the AnnotationType.members() map instead - this improves annotation instance footprint too.

AnnotationInvocationHandler.getMemberValue(): new static package-private method used in AnnotationSupport for fast retrieval of shared value array in container annotations.


AnnotationSupport.getDirectlyAndIndirectlyPresent(): minimize number of garbage objects and array copies. This method delegates to getSharedIndirectlyPresent() which might return a shared array which is only cloned if needed.

AnnotationSupport.getSharedIndirectlyPresent(): private method instead of getIndirectlyPresent() that may return a shared array.

AnnotationSupport.getSharedValueArray(): private method that may return a shared array. This method is based on new AnnotationInvocationHandler.getMemberValue() method and now also incorporates a call to checkTypes().

AnnotationSupport.getValueArray(): now based on getSharedValueArray() and cloneArray()

AnnotationSupport.cloneArray(): new private method which clones the array

AnnotationSupport.newArray(): new private constructor for annotation arrays (to localize @SuppressWarnings("unchecked"))


AnnotationType constructor: member Methods are now all made setAccessible(true) in advance so that "value" member method for container annotations doesn't need to be made setAccessible(true) each time a container of a particular type is flattened.


All in all these changes make common operations such as retrieving the annotation member values and obtaining repeatable annotations faster and with less produced garbage objects. Here are the results of some micro-benchmarks:

http://cr.openjdk.java.net/~plevart/jdk8-tl/AnnotationOptimizations/test/perf_results.txt

These results are obtained with the following test:

http://cr.openjdk.java.net/~plevart/jdk8-tl/AnnotationOptimizations/test/AnnotationDispatchPerfTest.java
http://cr.openjdk.java.net/~plevart/jdk8-tl/AnnotationOptimizations/test/si/pele/microbench/TestRunner.java


In short:
- Invoking Annotation.annotationType() is 6x faster
- Retrieving a scalar member value is 2x faster
- Annotation.equals for annotation with 3 int members is 2.5x faster
- Class.getDeclaredAnnotationsByType for direct-only case is 2x faster
- Class.getDeclaredAnnotationsByType for in-direct-only case is 2.2x faster
- Class.getDeclaredAnnotationsByType for mixed case is 1.7x faster



So what do you think?

Regards, Peter

Reply via email to