Hibernate Validation 6.0 ListValueExtractor.extractValues 似乎对大列表的性能很差

问题描述

我使用的是 Hibernate Validation 6.x。我正在验证的对象中有一个字段,其中包含一个列表,例如 List<@NotNull Double> doubles。我面临的问题是,当列表非常大时,性能下降很大。为了调查这个问题,我将列表元素的验证实现为列表 @ValidDoubles List<Double> doubles 上的自定义验证器,使用流迭代元素,并为该验证器实现了约 65% 的性能提升。

分析应用程序后,我可以看到大部分时间都花在了 ListValueExtractor.extractValues 上,可以在 here 中找到。我希望有人能解释为什么这种方法看起来如此昂贵,以及是否有任何已知的解决方法。

一个示例对象:

public class myDataObject {

    private List<@NotNull Double> doubles // List which can contain thousands of values

    // Getters and Setters
}

更新

经过进一步的分析和调查,我认为该问题与 Hibernate 在执行级联验证时跟踪哪些 bean 已经被验证有关,特别是在这样做时使用 System.identityHashCode (Here is the code) .

查看我的分析器,我可以看到 11.6% 的 CPU 时间用于验证输入 bean。其中,11.3% 的时间花在调用 System.identityHashCode 上。有趣的是,它是花费时间的第二个子对象,即使它们包含相对简单的验证。我想知道我是否错误地配置了验证器或 bean,因为这看起来很奇怪。

我的验证器配置如下所示:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
         <property name="validationPropertyMap">
             <util:map>
                 <entry key="hibernate.validator.fail_fast" value="true"/>
             </util:map>
         </property>
</bean>

验证器调用:

Set<ConstraintViolation<InputObject>> violations = validator.validate(input);

示例对象结构

public class InputObject {
    @NotNull
    String name;

    @Valid
    List<FirstChild> firstChildren; // on average 10 objects but can be up to very large

    // Getters and Setters
}

public class FirstChild {
    @SomeCustomValidator // Not important
    Integer someValue;

    // 3 to 4 further fields with simple validators

    @Valid
    List<SecondChild> secondChildren; // On average around 40 objects but can be very large

    // Getters and Setters
}

public class SecondChild {
    @NotBlank
    String foo;

    @NotBlank
    String bar;

    // Getters and Setters
}

总结:

  • 从分析器来看,问题在于从列表上的 @Valid 注释中发现的级联验证。
  • 问题似乎在于 Hibernate 在执行级联验证时跟踪哪些对象已经过验证。
  • 分析器将 System.identityHashCode 显示为占用大部分验证时间的方法。

这是 Hibernate 的优化问题还是我可以以某种方式配置我的验证器或输入对象结构以产生更好的性能?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)