这是我们最后一篇关于Spring的缓存抽象的文章的后续文章 。
作为工程师,您可以通过了解所使用的某些工具的内部知识来获得宝贵的经验。 了解工具的行为有助于您在做出设计选择时变得更加成熟。 在这篇文章中,我们描述了一个基准测试实验和结果,这些结果将帮助您了解Spring的内置缓存注释。
看一下以下两种方法:
@Cacheable (value = "time" , key = "#p0.concat(#p1)" ) public long annotationWithSpel(String dummy1, String dummy2) { "#p0.concat(#p1)" annotationWithSpel(String dummy1, String dummy2) { return System.currentTimeMillis(); } System.currentTimeMillis(); } @Cacheable (value = "time" ) public long annotationBased(String dummy1, String dummy2) { @Cacheable (value = annotationBased(String dummy1, String dummy2) { return System.currentTimeMillis(); } System.currentTimeMillis(); }
在这里,我们有两种非常相似的方法,每种方法都使用Spring Cache的内置@Cacheable注释进行注释。 第一个包含使用Spring Expression Language编写的表达式。 该表达式用于配置如何使用方法参数计算缓存键。 第二个依赖于Spring的默认行为,即“所有方法参数均视为键”。 实际上,以上两种方法实际上都导致完全相同的外部行为。
我们进行了一些基准测试,从而可以评估其性能:
Benchmark Mode Cnt Score Error Units CacheBenchmark.annotationBased avgt 5 271.975 ± 11.586 ns/op CacheBenchmark.spel avgt 5 1196.744 ± 93.765 ns/op CacheBenchmark.manual avgt 5 16.325 ± 0.856 ns/op CacheBenchmark.nocache avgt 5 40.142 ± 4.012 ns/op
事实证明,具有手动配置的缓存的方法运行速度慢4.4倍! 事后看来,由于间接费用,这种结果似乎是合理的。 Spring框架必须解析任意复杂的表达式,并且在此计算中消耗了一些周期。
我们为什么要写这个故事? 好 -
- 我们非常关心软件性能。
- 我们自己的代码库中有一些这样的实例,我们不得不权衡性能以获得零收益。
您应该检查您的代码库,并进行检查或审核。 杰蒂森(Jettison)也在其中一些实例中获得了性能提升。 您很可能在某些实例中也手动配置了缓存键。 请记住,这与Spring Cache默认为您提供的行为完全相同。 绝对的双赢局面!
翻译自: https://www.javacodegeeks.com/2019/04/more-about-spring-cache-performance.html