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

标签 java hibernate bean-validation

我正在使用 Hibernate Validation 6.x。我正在验证的对象中有一个字段,其中包含一个列表 List<@NotNull Double> doubles例如。我面临的问题是,当列表非常大时,性能下降是很大的。为了调查这个问题,我将列表元素的验证实现为列表上的自定义 validator ,@ValidDoubles List<Double> doubles ,使用流迭代元素,并为该 validator 实现了约 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 .有趣的是,尽管它们包含相对简单的验证,但花费时间的是第二个子对象。我想知道我是否错误地配置了 validator 或 bean,因为这似乎很奇怪。
我的 validator 配置如下所示:
<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>
validator 调用:
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 中找到的级联验证。 list 上的注释。
  • 问题似乎在于 Hibernate 在执行级联验证时跟踪哪些对象已经过验证。
  • 分析器显示 System.identityHashCode因为该方法占用了大部分验证时间。

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

    最佳答案

    艰难的一个。
    所以你看到的问题是我们创建了一个 BeanGroupProcessedUnit每个列表值,所以当你有很多时,它不能很好地扩展。
    将内容移出列表时不会出现问题,因为我们只为整个列表保留一个已处理的单元。
    我不完全确定是否有一个简单的解决方案不会破坏其他用例,但我们至少应该检查我们是否可以在您遇到的情况下改善情况。
    话虽如此,如果您能花时间在我们的跟踪器 https://hibernate.atlassian.net/projects/HV/issues 上打开一个问题,我将不胜感激。使用基于 https://github.com/hibernate/hibernate-test-case-templates/tree/master/validator 的复制器?这将有助于启动该过程。

    关于java - Hibernate Validation 6.0 ListValueExtractor.extractValues 似乎对大型列表的性能很差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66177098/

    相关文章:

    java - SWT Combo 禁用项目

    java - 对象关系映射和性能

    java - 如何使用 hibernate/jpa 注释将一个类映射到不同的表

    java - java中的自定义bean验证

    java - 谷歌镜像API

    java - 没有选择子句的 Hadoop 插入

    java - 使用Servlet时出现以下错误如何解决?

    java - 通过 Hibernate 存储和检索图像

    Java JSR-303 无需字节码编织的自动 Bean 验证

    java - Spring MVC 和 JSR 303