为什么Android的下注解,例如性能问题(慢)? [英] Why are annotations under Android such a performance issue (slow)?

查看:221
本文介绍了为什么Android的下注解,例如性能问题(慢)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的主要作者 ORMLite 它使用Java注释的类来创建数据库模式。我们包一个大的启动性能问题最终成为了Android 1.6下的注释方法的调用。我看到相同的行为上升至3.0。

I'm the lead author of ORMLite which uses Java annotations on classes to build database schemas. A big startup performance problem for our package turns out to be the calling of annotation methods under Android 1.6. I see the same behavior up through 3.0.

我们看到了下面的简单注解code是的难以置信的GC密集和一个真正的性能问题。 1000调用的标注方法呈现出快速箱几乎是第二个。在我的Mac Pro同样code跑步能做到2800万(原文如此)的同时通话。我们有一个具有25方法,它的注解,我们想要做的50多个,这些第二。

We are seeing that the following simple annotation code is incredibly GC intensive and a real performance problem. 1000 calls to an annotation method takes almost a second on a fast box. The same code running on my Mac Pro can do 28 million (sic) calls in the same time. We have an annotation that has 25 methods in it and we'd like to do more than 50 of these a second.

有谁知道为什么发生这种情况,如果有周围的任何工作?当然,还有事情ORMLite可以在缓存方面做的信息,但有什么,我们可以做的修理的注解Android的下?谢谢你。

Does anyone know why this is happening and if there is any work around? There are certainly things that ORMLite can do in terms of caching this information but is there anything that we can do to "fix" annotations under Android? Thanks.

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;
}

这导致下面的日志输出:

This results in the following log output:

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

编辑:

在@candrews我指出了正确的方向,我做了周围的code一些戳。性能问题看起来是由一些可怕的,总code。在引起Method.equals()。它被调用这两种方法的的toString(),然后比较它们。每个的toString()使用的StringBuilder 一堆的追加方法,而没有一个很好的初始化大小。这样做的 .equals 通过对比的是显著更快。

After @candrews pointed me in the right direction, I did some poking around the code. The performance problem looks to be caused by some terrible, gross code in Method.equals(). It is calling the toString() of both methods and then comparing them. Each toString() use StringBuilder with a bunch of append methods without a good initializing size. Doing the .equals by comparing fields would be significantly faster.

编辑:

这是有趣的反射性能的改善是给我。我们现在使用的是反射偷看里面的 AnnotationFactory 类直接读取字段列表。这使得反射20级的的更快的对我们,因为它绕过它是使用 method.equals()调用的调用。这不是一个通用的解决方案,但这里的Java的code从<一个href="http://ormlite.svn.sourceforge.net/viewvc/ormlite/ormlite-android/trunk/src/main/java/com/j256/ormlite/android/DatabaseTableConfigUtil.java?view=markup">ORMLite SVN仓库。对于一个通用的解决方案,请参见下面。yanchenko的答案

An interesting reflection performance improvement was given to me. We are now using reflection to peek inside the AnnotationFactory class to read the list of fields directly. This makes the reflection class 20 times faster for us since it bypasses the invoke which is using the method.equals() call. It is not a generic solution but here's the Java code from ORMLite SVN repository. For a generic solution, see yanchenko's answer below.

推荐答案

谷歌已经承认这个问题,并固定它后蜂窝

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

<一个href="https://$c$c.google.com/p/android/issues/detail?id=7811">https://$c$c.google.com/p/android/issues/detail?id=7811

所以,至少他们知道这一点,并理应固定它为将来的某个版本。

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

这篇关于为什么Android的下注解,例如性能问题(慢)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆