Peter Walser (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%...
) *created* an issue
Hibernate Validator (
https://hibernate.atlassian.net/browse/HV?atlOrigin=eyJpIjoiMDRjNDA3ZmE4N...
) / Bug (
https://hibernate.atlassian.net/browse/HV-1928?atlOrigin=eyJpIjoiMDRjNDA3...
) HV-1928 (
https://hibernate.atlassian.net/browse/HV-1928?atlOrigin=eyJpIjoiMDRjNDA3...
) Bad validator performance when adding obsolete @Validated to Java value objects (
https://hibernate.atlassian.net/browse/HV-1928?atlOrigin=eyJpIjoiMDRjNDA3...
)
Issue Type: Bug Affects Versions: 6.2.0.Final Assignee: Unassigned Components: performance
Created: 08/Nov/2022 02:18 AM Environment: Java 11, Linux, Hibernate Validator 6.2.0.Final
Priority: Major Reporter: Peter Walser (
https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%...
)
I ran into a performance issue with Java Bean Validation (Hibernate Validator) on a large
object, which caused the validation to run *several orders slower*.
I was able to isolate and reproduce it with the following example code:
Example DTOs
------------
Let's say we have a Order with Items:
public class Order {
private List<Item> items = new ArrayList<>();
@Valid public List<Item> getItems() { return items; }
public void setItems(List<Item> items) { this.items = items; }
}
The Items look like this:
public class Item {
private Long id;
private int quantity;
@NotNull @Valid public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Min(1) @Valid public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
}
Bean Validation and Benchmark
-----------------------------
Let's create an order with 20000 items, and benchmark how long it takes to validate it
(while also verifying that it is validated):
class ValidationBenchmarkTest {
private static Validator validator =
Validation.buildDefaultValidatorFactory().getValidator();
@Test
void shouldValidateLargeMessage() {
Order order = new Order();
AtomicLong sequence = new AtomicLong();
for (int i = 0; i < 20000; i++) {
Item item = new Item();
item.setId(sequence.getAndIncrement());
item.setQuantity(1);
order.getItems().add(item);
}
// add invalid item
Item item = new Item();
item.setId(sequence.getAndIncrement());
item.setQuantity(-5);
order.getItems().add(item);
for (int i = 1; i <= 100; i++) {
long time = System.nanoTime();
var constraintViolations = validator.validate(order);
time = System.nanoTime() - time;
System.out.println("validate: " + (time / 1000000d) + "
ms");
Assertions.assertThat(constraintViolations.size()).isEqualTo(1);
}
}
}
Benchmark times:
validate: 8469.735456 ms
validate: 8703.256756 ms
validate: 8544.319874 ms
validate: 8452.748767 ms
validate: 8572.898554 ms
The issue
---------
Obviously, the @Valid annotations on the Item id (Long) and quantity (int) are obsolete
(this annotation hints that the validation should recurse into a bean or collection, which
neither of these values are). If I remove them and run the validation benchmark again, the
times look good (while still having the correct validation outcome):
public class Item {
private Long id;
private int quantity;
@NotNull public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@Min(1) public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
}
validate: 23.015353 ms
validate: 23.239134 ms
validate: 22.970314 ms
validate: 22.875604 ms
This basically affects all value objects, where a @Valid was annotated:
* String and Character
* all Number classes ( Integer , Long , …, BigInteger , BigDecimal )
* all enum types
* Java Date/Time value objects ( LocalDate , LocalTime , LocalDateTime , OffsetDateTime ,
…)
* other Java value objects ( UUID , InetAddress , …)
The performance impact is non-linear, and seems to grow exponentially with the number of
items in that list.
Expectation: the @Valid should be ignored for Java-internal value objects (as listed
above), as it is obsolete, and has a critical performance impact.
(
https://hibernate.atlassian.net/browse/HV-1928#add-comment?atlOrigin=eyJp...
) Add Comment (
https://hibernate.atlassian.net/browse/HV-1928#add-comment?atlOrigin=eyJp...
)
Get Jira notifications on your phone! Download the Jira Cloud app for Android (
https://play.google.com/store/apps/details?id=com.atlassian.android.jira....
) or iOS (
https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=Em...
) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100210- sha1:ffe1a02 )