我是ORMLite的首席作者,该库使用Java注释在类上构建数据库模式。我们的一个大型创业公司问题是,在Android 1.6下调用注释方法会导致性能问题,并且在3.0版本中仍然存在相同的情况。
我们发现以下简单的注释代码非常耗费GC资源,是真正的性能问题。在快速的Android设备上,1000次注释方法调用几乎需要一秒钟的时间。在我的MacBook Pro上,同样的代码可以在相同时间内完成2800万次(sic)调用。我们有一个包含25个方法的注释,我们希望每秒钟执行超过50个操作。
是否有人知道为什么会出现这种情况,是否有任何解决方法?当然,ORMLite可以在缓存此信息方面做一些事情,但是否有任何方法可以“修复”Android下的注释?谢谢。
我们发现以下简单的注释代码非常耗费GC资源,是真正的性能问题。在快速的Android设备上,1000次注释方法调用几乎需要一秒钟的时间。在我的MacBook Pro上,同样的代码可以在相同时间内完成2800万次(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
编辑:
在@candrews指出正确方向后,我查看了一些代码。性能问题似乎是由Method.equals()
中一些可怕的、丑陋的代码引起的。它调用了两种方法的toString()
,然后进行比较。每个toString()
都使用一个没有良好初始化大小的StringBuilder
和大量的append方法。通过比较字段执行.equals
会更快。
编辑:
有人给我提供了一个有趣的反射性能改进。我们现在使用反射来窥视AnnotationFactory
类,直接读取字段列表。这使得反射类对我们来说快了20倍,因为它绕过了使用method.equals()
的调用。这不是通用的解决方案,但以下是来自ORMLite SVN repository的Java代码。对于通用解决方案,请参见下面yanchenko的答案。
foo
属性更改为int
而不是String
,是否会出现类似的时间?也许这是字符串池的问题? - nicholas.hauschildint
或任何其他类型。这是关于注释而不是它们所注释的内容。谢谢。 - GrayORMLite配置文件
吗? - theblang