Why are annotations under Android such a performance issue (slow)? Why are annotations under Android such a performance issue (slow)? android android

Why are annotations under Android such a performance issue (slow)?


Google has acknowledged the issue and fixed it "post-Honeycomb"

https://code.google.com/p/android/issues/detail?id=7811

So at least they know about it and have supposedly fixed it for some future version.


Here's a generic version of Gray's & user931366's idea:

public class AnnotationElementsReader {    private static Field elementsField;    private static Field nameField;    private static Method validateValueMethod;    public static HashMap<String, Object> getElements(Annotation annotation)            throws Exception {        HashMap<String, Object> map = new HashMap<String, Object>();        InvocationHandler handler = Proxy.getInvocationHandler(annotation);        if (elementsField == null) {            elementsField = handler.getClass().getDeclaredField("elements");            elementsField.setAccessible(true);        }        Object[] annotationMembers = (Object[]) elementsField.get(handler);        for (Object annotationMember : annotationMembers) {            if (nameField == null) {                Class<?> cl = annotationMember.getClass();                nameField = cl.getDeclaredField("name");                nameField.setAccessible(true);                validateValueMethod = cl.getDeclaredMethod("validateValue");                validateValueMethod.setAccessible(true);            }            String name = (String) nameField.get(annotationMember);            Object val = validateValueMethod.invoke(annotationMember);            map.put(name, val);        }        return map;    }}

I've benchmarked an annotation with 4 elements.
Millisecond times for 10000 iterations of either getting values of all of them or calling the method above:

     Device        Default  HackHTC Desire 2.3.7    11094   730Emulator 4.0.4      3157    528Galaxy Nexus 4.3    1248    392

Here's how I've integrated it into DroidParts: https://github.com/yanchenko/droidparts/commit/93fd1a1d6c76c2f4abf185f92c5c59e285f8bc69.


To follow up on this, there's still a problem here when calling methods on annotations. The bug listed above by candrews fixes the getAnnotation() slowness, but calling a method on the annotation is still a problem due to the Method.equals() issues.

Couldn't find a bug report for Method.equals() so I created one here:https://code.google.com/p/android/issues/detail?id=37380

Edit:So my work around for this (thanks for the ideas @Gray), is actually pretty simple.(this is trunkcated code, some caching and such is omitted)

annotationFactory = Class.forName("org.apache.harmony.lang.annotation.AnnotationFactory");getElementDesc = annotationFactory.getMethod("getElementsDescription", Class.class);Object[] members = (Object[])getElementDesc.invoke(annotationFactory, clz); // these are AnnotationMember[]Object element = null;for (Object e:members){ // AnnotationMembers    Field f = e.getClass().getDeclaredField("name");    f.setAccessible(true);    String fname = (String) f.get(e);    if (methodName.equals(fname)){        element = e;    break;    }}if (element == null) throw new Exception("Element was not found");Method m = element.getClass().getMethod("validateValue");return m.invoke(element, args);

You mileage will vary based on use, but in may case this was about 15-20 times faster then doing it the "right way"