[spring-projects/spring-boot]SampleActuatorApplication 在 2.4 中运行速度较慢

2024-04-12 989 views
3

2.4 的性能似乎有所下降。SampleActuatorApplication对我来说,运行时间多了 0.5 秒。

回答

8

CachedIntrospectionResults.getBeanInfo可能是一件值得关注的事情。或者现在似乎更频繁地触发它的任何东西。但这可能是 Spring-Framework 中的回归,而不是 Boot 中的回归。

2.4.0. 图像 快照 2.3.2.发布 图像

目前我的时间有限,否则我会自愿修复此问题或至少进一步调查。

4

不用担心,仅此分析就非常有帮助!

6

@philwebb 顺便说一句,你在比较哪些版本?我目前正在比较 2.3.2 与 2.4.0-SNAPSHOT,并不能真正看到 500 毫秒的差异。也许 100 毫秒——如果有的话。您使用哪个 JDK?我想尽可能接近你的设置 - 也许我可以提供至少一些关于这个的更多见解......

0

根据 #23147 中的讨论,设置-Dspring.beaninfo.ignore=false可能是值得尝试的事情(即使没有预料到会产生这种影响)。

4

:( 我认为我们最初将其设置为true尝试提高性能。

1

这仍然需要一些适当的测试——我还没有走得太远。但单独进行基准测试Introspector.getBeanInfo会产生以下结果。

Benchmark                                                    Mode  Cnt      Score      Error   Units
MyBenchmark.beanInfoWithIgnore                               avgt   10  72207,788 ± 7550,716   ns/op
MyBenchmark.beanInfoWithIgnore:·gc.alloc.rate                avgt   10    677,887 ±   65,626  MB/sec
MyBenchmark.beanInfoWithIgnore:·gc.alloc.rate.norm           avgt   10  63960,015 ±  293,228    B/op
MyBenchmark.beanInfoWithIgnore:·gc.churn.G1_Eden_Space       avgt   10    679,296 ±   94,402  MB/sec
MyBenchmark.beanInfoWithIgnore:·gc.churn.G1_Eden_Space.norm  avgt   10  64132,960 ± 7085,231    B/op
MyBenchmark.beanInfoWithIgnore:·gc.churn.G1_Old_Gen          avgt   10      0,008 ±    0,006  MB/sec
MyBenchmark.beanInfoWithIgnore:·gc.churn.G1_Old_Gen.norm     avgt   10      0,737 ±    0,534    B/op
MyBenchmark.beanInfoWithIgnore:·gc.count                     avgt   10     56,000             counts
MyBenchmark.beanInfoWithIgnore:·gc.time                      avgt   10     26,000                 ms
MyBenchmark.beanInfoWithoutIgnore                            avgt   10     13,241 ±    1,495   ns/op
MyBenchmark.beanInfoWithoutIgnore:·gc.alloc.rate             avgt   10     ≈ 10⁻⁴             MB/sec
MyBenchmark.beanInfoWithoutIgnore:·gc.alloc.rate.norm        avgt   10     ≈ 10⁻⁶               B/op
MyBenchmark.beanInfoWithoutIgnore:·gc.count                  avgt   10        ≈ 0             counts

显然,这并不能以 1:1 的方式转化为每个应用程序 - 事实上,它很大程度上取决于类加载器设置等 - 但可能是应对当前性能下降的一个选项。我很感兴趣这是否会对您的机器产生影响@philwebb

3

好吧,暂时把 beaninfo 的东西放在一边,我现在可以在运行 fat jar 时重现这一点,甚至可以看到从 500 毫秒到 1 秒不等的差异。分析还产生了一些其他非常有趣的结果(顶部 2.4.0.SNAPSHOT 与底部 2.3.2.RELEASE): 图像

当放大 2.4.0 分析时,这再次证实了对可能由于触发更多调用而导致性能下降的初步分析Introspector.getBeanInfo/CachedIntrospectionResults图像

8

不幸的是,从 Spring-Framework 5.1 开始,似乎触发大部分内容的代码已经被弃用:

请参阅https://github.com/spring-projects/spring-framework/blame/master/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java#L1420

for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    if (pvsToUse == null) {
        if (filteredPds == null) {
                         // This seems to trigger most of the expensive usages of CachedIntrospectionResults
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
                 // postProcessPropertyValues() is deprecated as of 5.1 and makes expensive filtering above obsolete
        pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {
            return;
        }
    }
    pvs = pvsToUse;
}
0

我不明白所提到的更改实际上应该如何(负面)影响这一点 - 考虑到它只是改变了 BeanPostProcessors 的迭代方式。事实上,我建议这样做是为了节省一些周期,以便在不相关的处理器上进行不必要的迭代……但也许有一个我还没有看到的奇怪的副作用。

5

很好,@dreis2211 - 我将AbstractAutoProxyCreator使用快捷方式返回值恢复重新声明的方法。不幸的是,这种微妙之处被忽视了,无论如何,我认为这些方法与界面中的默认方法相同。

1

postProcessPropertyValues删除已弃用的@jhoeller怎么样?如果你问我的话,这会解决很多微妙的问题......

0

这是一个非常古老的回调(广泛用于依赖注入目的),所以我宁愿暂时保持它完整并在 6.0 中删除它。不过,是的,移除后会更好。

1

很公平...