Assorted annotation optimizations

Peter Levart peter.levart at gmail.com
Sat Nov 2 21:58:08 UTC 2013


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




More information about the core-libs-dev mailing list