-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize annotation metadata resolution performance #1717
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
plugins { | ||
id "me.champeau.gradle.jmh" version "0.4.8" | ||
} | ||
|
||
dependencies { | ||
annotationProcessor project(":inject-java") | ||
annotationProcessor project(":validation") | ||
compile project(":inject") | ||
compile project(":validation") | ||
compile project(":runtime") | ||
|
||
|
||
jmh 'org.openjdk.jmh:jmh-core:1.21' | ||
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.21' | ||
} | ||
jmh { | ||
duplicateClassesStrategy = 'warn' | ||
warmupIterations = 2 | ||
iterations = 4 | ||
fork = 1 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package io.micronaut.core.annotation; | ||
|
||
public class AnnotationValueBenchmark { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package io.micronaut.core.convert; | ||
|
||
import org.openjdk.jmh.annotations.Benchmark; | ||
import org.openjdk.jmh.annotations.Scope; | ||
import org.openjdk.jmh.annotations.Setup; | ||
import org.openjdk.jmh.annotations.State; | ||
import org.openjdk.jmh.runner.Runner; | ||
import org.openjdk.jmh.runner.RunnerException; | ||
import org.openjdk.jmh.runner.options.Options; | ||
import org.openjdk.jmh.runner.options.OptionsBuilder; | ||
|
||
import java.net.URI; | ||
|
||
@State(Scope.Benchmark) | ||
public class ConversionServiceBenchmark { | ||
|
||
ConversionService conversionService; | ||
|
||
@Setup | ||
public void prepare() { | ||
conversionService = ConversionService.SHARED; | ||
} | ||
|
||
@Benchmark | ||
public void convertCacheHit() { | ||
conversionService.convert("10", Integer.class); | ||
} | ||
|
||
@Benchmark | ||
public void convertCacheMiss() { | ||
conversionService.convert(URI.create("http://test.com"), Integer.class); | ||
} | ||
|
||
public static void main(String[] args) throws RunnerException { | ||
Options opt = new OptionsBuilder() | ||
.include(".*" + ConversionServiceBenchmark.class.getSimpleName() + ".*") | ||
.warmupIterations(3) | ||
.measurementIterations(5) | ||
.forks(1) | ||
// .jvmArgs("-agentpath:/Applications/YourKit-Java-Profiler-2018.04.app/Contents/Resources/bin/mac/libyjpagent.jnilib") | ||
.build(); | ||
|
||
new Runner(opt).run(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
import io.micronaut.core.type.Argument; | ||
import io.micronaut.core.util.ArgumentUtils; | ||
import io.micronaut.core.util.ArrayUtils; | ||
import io.micronaut.core.util.StringUtils; | ||
import io.micronaut.core.value.OptionalValues; | ||
|
||
import javax.annotation.Nonnull; | ||
|
@@ -456,7 +457,7 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
* @return The {@link AnnotationValue} | ||
*/ | ||
@Override | ||
default @Nonnull <T extends Annotation> Optional<AnnotationValue<T>> findAnnotation(@Nonnull Class<T> annotationClass) { | ||
default @Nonnull <T extends Annotation> Optional<AnnotationValue<T>> findAnnotation(@Nonnull Class<T> annotationClass) { | ||
ArgumentUtils.requireNonNull("annotationClass", annotationClass); | ||
Repeatable repeatable = annotationClass.getAnnotation(Repeatable.class); | ||
if (repeatable != null) { | ||
|
@@ -551,7 +552,7 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
* @param annotation The annotation | ||
* @return An {@link Optional} class | ||
*/ | ||
default @Nonnull Optional<Class> classValue(@Nonnull String annotation) { | ||
default @Nonnull Optional<Class<?>> classValue(@Nonnull String annotation) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return classValue(annotation, VALUE_MEMBER); | ||
} | ||
|
@@ -563,11 +564,13 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
* @param member The annotation member | ||
* @return An {@link Optional} class | ||
*/ | ||
default @Nonnull Optional<Class> classValue(@Nonnull String annotation, @Nonnull String member) { | ||
default @Nonnull Optional<Class<?>> classValue(@Nonnull String annotation, @Nonnull String member) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
ArgumentUtils.requireNonNull("member", member); | ||
|
||
return getValue(annotation, member, Class.class); | ||
Optional value = getValue(annotation, member, Class.class); | ||
//noinspection unchecked | ||
return value; | ||
} | ||
|
||
/** | ||
|
@@ -576,10 +579,10 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
* @param annotation The annotation | ||
* @return An {@link Optional} class | ||
*/ | ||
default @Nonnull Optional<Class> classValue(@Nonnull Class<? extends Annotation> annotation) { | ||
default @Nonnull Optional<Class<?>> classValue(@Nonnull Class<? extends Annotation> annotation) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
|
||
return classValue(annotation.getName()); | ||
return classValue(annotation, VALUE_MEMBER); | ||
} | ||
|
||
/** | ||
|
@@ -589,13 +592,15 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
* @param member The annotation member | ||
* @return An {@link Optional} class | ||
*/ | ||
default @Nonnull Optional<Class> classValue(@Nonnull Class<? extends Annotation> annotation, @Nonnull String member) { | ||
default @Nonnull Optional<Class<?>> classValue(@Nonnull Class<? extends Annotation> annotation, @Nonnull String member) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
ArgumentUtils.requireNonNull("member", member); | ||
|
||
return classValue(annotation.getName(), member); | ||
} | ||
|
||
|
||
|
||
/** | ||
* The value as an {@link OptionalInt} for the given annotation and member. | ||
* | ||
|
@@ -611,6 +616,97 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
return result.map(OptionalInt::of).orElseGet(OptionalInt::empty); | ||
} | ||
|
||
/** | ||
* The value as an {@link OptionalInt} for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @param member The member | ||
* @return THe {@link OptionalInt} value | ||
*/ | ||
default @Nonnull OptionalInt intValue(@Nonnull Class<? extends Annotation> annotation, @Nonnull String member) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return intValue(annotation.getName(), member); | ||
} | ||
|
||
/** | ||
* The value as an {@link OptionalInt} for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @return THe {@link OptionalInt} value | ||
*/ | ||
default @Nonnull OptionalInt intValue(@Nonnull Class<? extends Annotation> annotation) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return intValue(annotation, VALUE_MEMBER); | ||
} | ||
|
||
/** | ||
* The value as an optional string for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @param member The member | ||
* @return The string value if it is present | ||
*/ | ||
default @Nonnull Optional<String> stringValue(@Nonnull String annotation, @Nonnull String member) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
ArgumentUtils.requireNonNull("member", member); | ||
|
||
return getValue(annotation, member, String.class); | ||
} | ||
|
||
/** | ||
* The value as an optional string for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @param member The member | ||
* @return The string value if it is present | ||
*/ | ||
default @Nonnull Optional<String> stringValue(@Nonnull Class<? extends Annotation> annotation, @Nonnull String member) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return stringValue(annotation.getName(), member); | ||
} | ||
|
||
/** | ||
* The values as string array for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @param member The member | ||
* @return The string values if it is present | ||
*/ | ||
default @Nonnull String[] stringValues(@Nonnull Class<? extends Annotation> annotation, @Nonnull String member) { | ||
return StringUtils.EMPTY_STRING_ARRAY; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why doesn't this implementation default to getting the values the old way? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could do, but the old ways performance is not good. This method is overridden anyway be the implementation. I put this in there for backwards compatibility so if someone had implemented this interface (unlikely) it would still compile. |
||
} | ||
|
||
/** | ||
* The values as string array for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @return The string values if it is present | ||
*/ | ||
default @Nonnull String[] stringValues(@Nonnull Class<? extends Annotation> annotation) { | ||
return stringValues(annotation, VALUE_MEMBER); | ||
} | ||
|
||
/** | ||
* The value as an optional string for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @return The string value if it is present | ||
*/ | ||
default @Nonnull Optional<String> stringValue(@Nonnull Class<? extends Annotation> annotation) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return stringValue(annotation, VALUE_MEMBER); | ||
} | ||
|
||
/** | ||
* The value as an optional string for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @return The string value if it is present | ||
*/ | ||
default @Nonnull Optional<String> stringValue(@Nonnull String annotation) { | ||
return stringValue(annotation, VALUE_MEMBER); | ||
} | ||
|
||
/** | ||
* The value as an {@link OptionalDouble} for the given annotation and member. | ||
* | ||
|
@@ -626,6 +722,29 @@ default boolean isDeclaredAnnotationPresent(@Nonnull Class<? extends Annotation> | |
return result.map(OptionalDouble::of).orElseGet(OptionalDouble::empty); | ||
} | ||
|
||
/** | ||
* The value as an {@link OptionalDouble} for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @param member The member | ||
* @return THe {@link OptionalDouble} value | ||
*/ | ||
default @Nonnull OptionalDouble doubleValue(@Nonnull Class<? extends Annotation> annotation, @Nonnull String member) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return doubleValue(annotation.getName(), member); | ||
} | ||
|
||
/** | ||
* The value as an {@link OptionalDouble} for the given annotation and member. | ||
* | ||
* @param annotation The annotation | ||
* @return THe {@link OptionalDouble} value | ||
*/ | ||
default @Nonnull OptionalDouble doubleValue(@Nonnull Class<? extends Annotation> annotation) { | ||
ArgumentUtils.requireNonNull("annotation", annotation); | ||
return doubleValue(annotation, VALUE_MEMBER); | ||
} | ||
|
||
/** | ||
* Get the value of default "value" the given annotation. | ||
* | ||
|
@@ -709,7 +828,7 @@ default boolean isPresent(@Nonnull String annotation, @Nonnull String member) { | |
} | ||
|
||
/** | ||
* Returns whether the value of the given member is <em>true</em>. | ||
* Returns whether the value of the given member is present. | ||
* | ||
* @param annotation The annotation class | ||
* @param member The annotation member | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the
@Nonnull
annotation may be redundant here. Kotlin treats Optional as non null without the annotation. I haven't tested OptionalInt, though I assume it works the sameThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks will remove them