Я ведущий автор ORMLite, который использует аннотации Java для классов для построения схем баз данных. Большая проблема производительности стартового пакета для нашего пакета оказывается вызовом методов аннотации в Android 1.6. Я вижу то же поведение до 3,0.
Мы видим, что следующий простой код аннотации невероятно насыщен GC и реальная проблема с производительностью. 1000 вызовов метода аннотации занимают почти секунду на быстром Android-устройстве. Тот же код, который работает на моем Macbook Pro, может выполнять 28 миллионов (sic) звонков в одно и то же время. У нас есть аннотация, в которой есть 25 методов, и мы хотели бы сделать более 50 из них в секунду.
Кто-нибудь знает, почему это происходит, и если есть какая-то работа? Есть вещи, которые ORMLite может сделать с точки зрения кеширования этой информации, но есть ли что-нибудь, что мы можем сделать, чтобы "исправить" аннотации под Android? Спасибо.
public void testAndroidAnnotations() throws Exception {
    Field field = Foo.class.getDeclaredField("field");
    MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class);
    long before = System.currentTimeMillis();
    for (int i = 0; i < 1000; i++)
        myAnnotation.foo();
    Log.i("test", "in " + (System.currentTimeMillis() - before) + "ms");
}
@Target(FIELD) @Retention(RUNTIME)
private static @interface MyAnnotation {
    String foo();
}
private static class Foo {
    @MyAnnotation(foo = "bar")
    String field;
}
В результате получается следующий выход журнала:
I/TestRunner(  895): started: testAndroidAnnotations
D/dalvikvm(  895): GC freed 6567 objects / 476320 bytes in 85ms
D/dalvikvm(  895): GC freed 8951 objects / 599944 bytes in 71ms
D/dalvikvm(  895): GC freed 7721 objects / 524576 bytes in 68ms
D/dalvikvm(  895): GC freed 7709 objects / 523448 bytes in 73ms
I/test    (  895): in 854ms
EDIT:
После того, как @candrews указал мне в правильном направлении, я немного проговорил над кодом. Проблема производительности связана с каким-то ужасным, грубым кодом в Method.equals(). Он вызывает toString() обоих методов, а затем сравнивает их. Каждый toString() использует StringBuilder с кучей методов добавления без хорошего размера инициализации. Выполнение .equals путем сравнения полей будет значительно быстрее.
EDIT:
Мне понравилось интересное улучшение производительности. Мы теперь используем рефлексию, чтобы заглянуть внутрь класса AnnotationFactory, чтобы прочитать список полей напрямую. Это делает класс отражения в 20 раз быстрее для нас, поскольку он обходит вызов, который использует вызов Method.equals(). Это не общее решение, а вот код Java из ORMLite SVN репозиторий. Для общего решения см. ответ Янченко ниже.