多次调用 Method/Field.getAnnotation(Class) 与在 Map 中预缓存此数据的性能
我想知道是否有关于重复调用(在Java中)Method.getAnnotation(Class)
和Field.getAnnotation(Class) 方法,而不是存储(在程序启动时)带有类的元数据信息的预先计算的 Map 并稍后重复查询。哪一种可以提供最佳的运行时性能?
这个性能在 Java 5、6 和 7 下是一样的吗?
I'd like to know if there are any comparison/studies about the performance of repeatidly calling (in Java) the Method.getAnnotation(Class)
and Field.getAnnotation(Class)
methods, versus storing (at program start up time) a precomputed Map with this metadata information of the classes and querying it repeatidly later. Which one would provide the best runtime performance?
And this performance would be the same under Java 5, 6 and 7?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
地图应该是一种更可取的方法。主要问题不仅仅是缓存。而且还改善了多线程争用。在Method.getAnnotation()中,它调用同步私有方法declaredAnnotations()。同步方法对高线程应用程序有不好的影响。
Map should be a more preferable approach. The main issue is not only about caching. But also improve the multi thread contention. In the Method.getAnnotation(), it calls a synchronized private method declaredAnnotations(). Synchronized method have bad impact on highly threaded application.
我知道这是一个相当老的问题,但最新 JDK 的结果可能仍然令人感兴趣。
我编写了一些 JMH 基准测试,以了解注释信息缓存可能产生的影响:
JDK 1.8.0_172、Java HotSpot(TM) 64 位服务器 VM、25.172-b11:
JDK 13、OpenJDK 64 位服务器 VM、13 +33:
与 1.8 和 13 相比,您可以清楚地看到 JDK 缓存注释的效果。最近的 JDK 也是如此无需关心缓存此信息,因为它只会带来额外的开销。
I know this is some rather old question but the result for more recent JDKs might still be of interest.
I wrote some JMH benchmark to get an idea of the impact caching of annotation information might have:
JDK 1.8.0_172, Java HotSpot(TM) 64-Bit Server VM, 25.172-b11:
JDK 13, OpenJDK 64-Bit Server VM, 13+33:
You can clearly see the effect of annotations being cached by the JDK comparing 1.8 to 13. So with recent JDKs there is no need to care about caching this information as it would only introduce additional overhead.
我想这在一定程度上取决于 JVM 的实现。但以 Oracle JVM 为例,它维护了方法和字段实例上所有注释的缓存,这相当于你所说的映射方法。
但这里有一个问题:由于方法/字段实例对于每个对象都是唯一的,因此如果您最终为给定类创建大量对象,您几乎会失去所提供的性能优势。在这种情况下,类名+方法名/类名+字段名到相关注释列表的静态映射胜过所使用的内置缓存方法。
顺便说一句,你是如何预先计算地图的?是在应用程序启动时完成还是在某些自动生成的代码中完成?您是否真的确认在您的案例中缓存注释实例是安全的?
与往常一样,对于此类问题,最好的解决方案是使用您的应用程序在线进行分析/测量,并采用在给定用例中看起来像是胜利的解决方案。
I guess this depends a bit on the JVM implementation. But taking the example of Oracle JVM, it maintains a cache of all the annotations on the method and field instances which is equivalent to the map approach you speak of.
But there is a catch here; since method/field instances are unique to each object, in case you end up creating a lot of objects for a given class, you pretty much lose out on the performance benefit offered. It is in this case a static map of class-name + method-name / class-name + field name to the relevant annotation list trumps the in-built caching approach used.
BTW, how are you pre-computing the map? Is it done on application start-up or some auto-generated code? Have you really confirmed that it is safe to cache the annotation instances in your case?
As always, for such questions, the best solution is to profile/measure with your app on the line and go with the solution which looks like win in the given use case.