Browse Source

Improve AnnotationProcessorPerformanceTests with Awaitility

pull/23061/head
Sam Brannen 6 years ago
parent
commit
3794a57651
  1. 101
      spring-context/src/test/java/org/springframework/context/annotation/AnnotationProcessorPerformanceTests.java

101
spring-context/src/test/java/org/springframework/context/annotation/AnnotationProcessorPerformanceTests.java

@ -16,10 +16,14 @@
package org.springframework.context.annotation; package org.springframework.context.annotation;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.awaitility.Awaitility;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -32,19 +36,20 @@ import org.springframework.tests.Assume;
import org.springframework.tests.TestGroup; import org.springframework.tests.TestGroup;
import org.springframework.tests.sample.beans.ITestBean; import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.TestBean; import org.springframework.tests.sample.beans.TestBean;
import org.springframework.util.StopWatch;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Chris Beams * @author Chris Beams
* @author Sam Brannen
* @since 2.5 * @since 2.5
*/ */
public class AnnotationProcessorPerformanceTests { public class AnnotationProcessorPerformanceTests {
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class); private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
@BeforeClass @BeforeClass
public static void commonAssumptions() { public static void commonAssumptions() {
Assume.group(TestGroup.PERFORMANCE); Assume.group(TestGroup.PERFORMANCE);
@ -52,89 +57,79 @@ public class AnnotationProcessorPerformanceTests {
} }
@Test @Test
public void testPrototypeCreationWithResourcePropertiesIsFastEnough() { public void prototypeCreationWithResourcePropertiesIsFastEnough() {
GenericApplicationContext ctx = new GenericApplicationContext(); GenericApplicationContext ctx = createContext();
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);
ctx.refresh();
RootBeanDefinition rbd = new RootBeanDefinition(ResourceAnnotatedTestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(ResourceAnnotatedTestBean.class);
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
ctx.registerBeanDefinition("test", rbd); ctx.registerBeanDefinition("test", rbd);
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
TestBean spouse = (TestBean) ctx.getBean("spouse");
StopWatch sw = new StopWatch(); assertFastEnough(ctx);
sw.start("prototype");
for (int i = 0; i < 100000; i++) {
TestBean tb = (TestBean) ctx.getBean("test");
assertThat(tb.getSpouse()).isSameAs(spouse);
}
sw.stop();
assertThat(sw.getTotalTimeMillis() < 4000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue();
} }
@Test @Test
public void testPrototypeCreationWithOverriddenResourcePropertiesIsFastEnough() { public void prototypeCreationWithOverriddenResourcePropertiesIsFastEnough() {
GenericApplicationContext ctx = new GenericApplicationContext(); GenericApplicationContext ctx = createContext();
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);
ctx.refresh();
RootBeanDefinition rbd = new RootBeanDefinition(ResourceAnnotatedTestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(ResourceAnnotatedTestBean.class);
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse")); rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse"));
ctx.registerBeanDefinition("test", rbd); ctx.registerBeanDefinition("test", rbd);
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
TestBean spouse = (TestBean) ctx.getBean("spouse");
StopWatch sw = new StopWatch(); assertFastEnough(ctx);
sw.start("prototype");
for (int i = 0; i < 100000; i++) {
TestBean tb = (TestBean) ctx.getBean("test");
assertThat(tb.getSpouse()).isSameAs(spouse);
}
sw.stop();
assertThat(sw.getTotalTimeMillis() < 4000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue();
} }
@Test @Test
public void testPrototypeCreationWithAutowiredPropertiesIsFastEnough() { public void prototypeCreationWithAutowiredPropertiesIsFastEnough() {
GenericApplicationContext ctx = new GenericApplicationContext(); GenericApplicationContext ctx = createContext();
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);
ctx.refresh();
RootBeanDefinition rbd = new RootBeanDefinition(AutowiredAnnotatedTestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(AutowiredAnnotatedTestBean.class);
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
ctx.registerBeanDefinition("test", rbd); ctx.registerBeanDefinition("test", rbd);
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
TestBean spouse = (TestBean) ctx.getBean("spouse");
StopWatch sw = new StopWatch(); assertFastEnough(ctx);
sw.start("prototype");
for (int i = 0; i < 100000; i++) {
TestBean tb = (TestBean) ctx.getBean("test");
assertThat(tb.getSpouse()).isSameAs(spouse);
}
sw.stop();
assertThat(sw.getTotalTimeMillis() < 4000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue();
} }
@Test @Test
public void testPrototypeCreationWithOverriddenAutowiredPropertiesIsFastEnough() { public void prototypeCreationWithOverriddenAutowiredPropertiesIsFastEnough() {
GenericApplicationContext ctx = new GenericApplicationContext(); GenericApplicationContext ctx = createContext();
AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);
ctx.refresh();
RootBeanDefinition rbd = new RootBeanDefinition(AutowiredAnnotatedTestBean.class); RootBeanDefinition rbd = new RootBeanDefinition(AutowiredAnnotatedTestBean.class);
rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); rbd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse")); rbd.getPropertyValues().add("spouse", new RuntimeBeanReference("spouse"));
ctx.registerBeanDefinition("test", rbd); ctx.registerBeanDefinition("test", rbd);
ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class)); ctx.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class));
TestBean spouse = (TestBean) ctx.getBean("spouse");
StopWatch sw = new StopWatch(); assertFastEnough(ctx);
sw.start("prototype"); }
for (int i = 0; i < 100000; i++) {
TestBean tb = (TestBean) ctx.getBean("test"); private GenericApplicationContext createContext() {
assertThat(tb.getSpouse()).isSameAs(spouse); GenericApplicationContext ctx = new GenericApplicationContext();
} AnnotationConfigUtils.registerAnnotationConfigProcessors(ctx);
sw.stop(); ctx.refresh();
assertThat(sw.getTotalTimeMillis() < 6000).as("Prototype creation took too long: " + sw.getTotalTimeMillis()).isTrue(); return ctx;
}
private void assertFastEnough(GenericApplicationContext ctx) {
AtomicBoolean done = new AtomicBoolean();
TestBean spouse = ctx.getBean("spouse", TestBean.class);
Executors.newSingleThreadExecutor().submit(() -> {
for (int i = 0; i < 100_000; i++) {
TestBean tb = ctx.getBean("test", TestBean.class);
assertThat(tb.getSpouse()).isSameAs(spouse);
}
done.set(true);
});
// "fast enough" is of course relative, but we're using 6 seconds with the hope
// that these tests typically pass on the CI server.
Awaitility.await()
.atMost(6, TimeUnit.SECONDS)
.pollInterval(100, TimeUnit.MILLISECONDS)
.untilTrue(done);
} }

Loading…
Cancel
Save