Oliver Drotbohm opened SPR-14926 and commented
When a conversion is invoked using a TypeDescriptor instance that was created for a MethodParameter containing annotations, the lookup of the Converter is significantly slowed down as the TypeDescriptor instances undergo an ….equals(…) check that's quite expensive due to the synthesized annotations.
I wonder whether TypeDescriptor really needs to compare the annotations if the method and the parameter index are well defined as they by definition uniquely identify the parameter.
Here's a sample test case showing the issue:
package org.example.myapi;
import java.lang.reflect.Method;
import java.util.Date;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author Oliver Gierke
*/
public class FooTests {
private static final int ITERATIONS = 1000000;
private static final ConversionService CONVERSION_SERVICE = new DefaultFormattingConversionService();
private static final TypeDescriptor STRING_TYPE = TypeDescriptor.valueOf(String.class);
@Test
public void methodParameterWithAnnotations() {
Date date = new Date();
Method method = ReflectionUtils.findMethod(SomeController.class, "someMethod", Date.class);
TypeDescriptor sourceDescriptor = TypeDescriptor.nested(new MethodParameter(method, 0), 0);
long startTime = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
CONVERSION_SERVICE.convert(date, sourceDescriptor, STRING_TYPE);
}
long duration = (System.currentTimeMillis() - startTime);
System.out.println("With annotations " + duration);
}
@Test
public void methodParameterWithoutAnnotations() {
Method method = ReflectionUtils.findMethod(SomeController.class, "someMethod", String.class);
TypeDescriptor sourceDescriptor = TypeDescriptor.nested(new MethodParameter(method, 0), 0);
long startTime = System.currentTimeMillis();
for (int i = 0; i < ITERATIONS; i++) {
CONVERSION_SERVICE.convert("Foo", sourceDescriptor, STRING_TYPE);
}
long duration = (System.currentTimeMillis() - startTime);
System.out.println("Without annotations " + duration);
}
static class SomeController {
ResponseEntity<Object> someMethod(@RequestParam("foo") @DateTimeFormat(iso = ISO.DATE) Date date) {
return null;
}
ResponseEntity<Object> someMethod(String value) {
return null;
}
}
}
Affects: 4.3.4
Reference URL: spring-projects/spring-hateoas#511
Attachments:
Issue Links:
Oliver Drotbohm opened SPR-14926 and commented
When a conversion is invoked using a
TypeDescriptorinstance that was created for aMethodParametercontaining annotations, the lookup of theConverteris significantly slowed down as theTypeDescriptorinstances undergo an….equals(…)check that's quite expensive due to the synthesized annotations.I wonder whether
TypeDescriptorreally needs to compare the annotations if the method and the parameter index are well defined as they by definition uniquely identify the parameter.Here's a sample test case showing the issue:
Affects: 4.3.4
Reference URL: spring-projects/spring-hateoas#511
Attachments:
Issue Links:
@AliasFor@DateTimeFormat(iso = ISO.DATE_TIME) should use optimized formatter for LocalDateTime