package de.jpaw.bonaparte.benchmarks.propsVsAnnos; import java.lang.reflect.Field; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.OperationsPerInvocation; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.infra.Blackhole; import de.jpaw.bonaparte.core.BonaPortable; import de.jpaw.bonaparte.pojos.proptest.ClassWithProperties; //Benchmarks to investigate if the bonaparte properties are really worth it or if we should just use standard Java annotations //java -jar target/bonaparte-benchmarks.jar -i 3 -f 3 -wf 1 -wi 3 //# Run complete. Total time: 00:02:08 // //Benchmark Mode Samples Mean Mean error Units //d.j.b.b.propsVsAnnos.Properties.getClassAnnotationValue thrpt 9 31035.833 978.143 ops/ms //d.j.b.b.propsVsAnnos.Properties.getClassPropertyValue thrpt 9 237147.954 9583.001 ops/ms //d.j.b.b.propsVsAnnos.Properties.getFieldAnnotationValue thrpt 9 197.387 5.528 ops/ms //d.j.b.b.propsVsAnnos.Properties.getFieldPropertyValue thrpt 9 19634.948 1260.742 ops/ms // This benchmark suggests it is! Data on class level is retrieved 7.5 times faster, field values are retrieved about 100 times faster, // most likely caused by the security checks which are done within reflection @State(value = Scope.Thread) @OperationsPerInvocation(Properties.OPERATIONS_PER_INVOCATION) public class Properties { static public final int OPERATIONS_PER_INVOCATION = 100000; // // // Java Annotations / reflections tests // // private String getClassAnnotation(Object x) throws Exception { BenchAnnoClass anno = x.getClass().getAnnotation(BenchAnnoClass.class); return anno == null ? null : anno.value(); } @Benchmark public void getClassAnnotationValue(Blackhole bh) throws Exception { Object obj = new ClassWithAnnotations(); assert("Hello, class".equals(getClassAnnotation(obj))); for (int i = 0; i < OPERATIONS_PER_INVOCATION; ++i) { bh.consume(getClassAnnotation(obj)); } } private String getFieldAnnotation(Object x) throws Exception { Field f = x.getClass().getField("myField"); if (f == null) return null; BenchAnnoField anno = f.getAnnotation(BenchAnnoField.class); return anno == null ? null : anno.value(); } @Benchmark public void getFieldAnnotationValue(Blackhole bh) throws Exception { Object obj = new ClassWithAnnotations(); assert("Hello, field".equals(getFieldAnnotation(obj))); for (int i = 0; i < OPERATIONS_PER_INVOCATION; ++i) { bh.consume(getFieldAnnotation(obj)); } } // // // Bonaparte property tests // // private String getClassProperty(BonaPortable obj) throws Exception { return obj.ret$BonaPortableClass().getProperty("myClassProp"); } @Benchmark public void getClassPropertyValue(Blackhole bh) throws Exception { BonaPortable obj = new ClassWithProperties(); assert("Hello, class".equals(getClassProperty(obj))); for (int i = 0; i < OPERATIONS_PER_INVOCATION; ++i) { bh.consume(getClassProperty(obj)); } } private String getFieldProperty(BonaPortable obj) throws Exception { return obj.ret$BonaPortableClass().getProperty("myField.myFieldProp"); } @Benchmark public void getFieldPropertyValue(Blackhole bh) throws Exception { BonaPortable obj = new ClassWithProperties(); assert("Hello, field".equals(getFieldProperty(obj))); for (int i = 0; i < OPERATIONS_PER_INVOCATION; ++i) { bh.consume(getFieldProperty(obj)); } } }