diff --git a/.gitignore b/.gitignore index cfdc7153d..cd187e01c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .project .settings/ .springBeans +.apt_generated/ target/ _site/ .idea @@ -18,4 +19,4 @@ _site/ .DS_Store /spring-cloud-sleuth-core/nb-configuration.xml /spring-cloud-sleuth-core/nbactions.xml -jmh-result.csv \ No newline at end of file +jmh-result.csv diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index 035bdca35..8a63dc3ca 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -22,7 +22,7 @@ ${project.basedir}/.. - 1.11.3 + 1.16 2.4.3 2.5.2 true @@ -51,13 +51,6 @@ - - org.springframework.cloud - spring-cloud-sleuth-dependencies - ${project.version} - pom - import - ${project.groupId} spring-cloud-sleuth-core @@ -248,7 +241,7 @@ org.springframework.boot spring-boot-maven-plugin - 1.5.1.RELEASE + 1.5.4.RELEASE diff --git a/benchmarks/src/main/java/org/springframework/cloud/sleuth/benchmarks/jmh/benchmarks/ProcessLauncherState.java b/benchmarks/src/main/java/org/springframework/cloud/sleuth/benchmarks/jmh/benchmarks/ProcessLauncherState.java new file mode 100644 index 000000000..8c4f1978f --- /dev/null +++ b/benchmarks/src/main/java/org/springframework/cloud/sleuth/benchmarks/jmh/benchmarks/ProcessLauncherState.java @@ -0,0 +1,143 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cloud.sleuth.benchmarks.jmh.benchmarks; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.openjdk.jmh.util.FileUtils; +import org.openjdk.jmh.util.Utils; + +import org.springframework.cloud.sleuth.benchmarks.app.SleuthBenchmarkingSpringApp; + +public class ProcessLauncherState { + + private Process started; + private List args; + private List extraArgs; + private File home; + private String mainClass = SleuthBenchmarkingSpringApp.class.getName(); + private int length; + + public ProcessLauncherState(String dir, String... args) { + this.args = new ArrayList<>(Arrays.asList(args)); + int count = 0; + this.args.add(count++, System.getProperty("java.home") + "/bin/java"); + this.args.add(count++, "-Xmx128m"); + this.args.add(count++, "-cp"); + this.args.add(count++, getClasspath()); + this.args.add(count++, "-Djava.security.egd=file:/dev/./urandom"); + this.args.add(count++, "-XX:TieredStopAtLevel=1"); // zoom + if (System.getProperty("bench.args") != null) { + this.args.addAll(count++, + Arrays.asList(System.getProperty("bench.args").split(" "))); + } + this.length = args.length; + this.home = new File(dir); + } + + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + public void setExtraArgs(String... extraArgs) { + this.extraArgs = Arrays.asList(extraArgs); + } + + private String getClasspath() { + StringBuilder builder = new StringBuilder(); + for (URL url : ((URLClassLoader) getClass().getClassLoader()).getURLs()) { + if (builder.length() > 0) { + builder.append(File.pathSeparator); + } + builder.append(url.toString()); + } + return builder.toString(); + } + + public void after() throws Exception { + if (started != null && started.isAlive()) { + System.err.println( + "Stopped " + mainClass + ": " + started.destroyForcibly().waitFor()); + } + } + + public Collection capture(String... additional) throws Exception { + List args = new ArrayList<>(this.args); + args.addAll(Arrays.asList(additional)); + ProcessBuilder builder = new ProcessBuilder(args); + builder.directory(home); + builder.redirectErrorStream(true); + customize(builder); + if (!"false".equals(System.getProperty("debug", "false"))) { + System.err.println("Running: " + Utils.join(args, " ")); + } + started = builder.start(); + return FileUtils.readAllLines(started.getInputStream()); + } + + public void run() throws Exception { + List args = new ArrayList<>(this.args); + args.add(args.size() - this.length, this.mainClass); + if (extraArgs!=null) { + args.addAll(extraArgs); + } + ProcessBuilder builder = new ProcessBuilder(args); + builder.directory(home); + builder.redirectErrorStream(true); + customize(builder); + if (!"false".equals(System.getProperty("debug", "false"))) { + System.err.println("Running: " + Utils.join(args, " ")); + } + started = builder.start(); + monitor(); + } + + protected void customize(ProcessBuilder builder) { + } + + protected void monitor() throws IOException { + System.out.println(output(started.getInputStream(), "Started")); + } + + protected static String output(InputStream inputStream, String marker) + throws IOException { + StringBuilder sb = new StringBuilder(); + BufferedReader br = null; + br = new BufferedReader(new InputStreamReader(inputStream)); + String line = null; + while ((line = br.readLine()) != null && !line.contains(marker)) { + sb.append(line + System.getProperty("line.separator")); + } + if (line != null) { + sb.append(line + System.getProperty("line.separator")); + } + return sb.toString(); + } + + public File getHome() { + return home; + } +} \ No newline at end of file diff --git a/benchmarks/src/main/java/org/springframework/cloud/sleuth/benchmarks/jmh/benchmarks/StartupBenchmark.java b/benchmarks/src/main/java/org/springframework/cloud/sleuth/benchmarks/jmh/benchmarks/StartupBenchmark.java new file mode 100644 index 000000000..7ce48a16c --- /dev/null +++ b/benchmarks/src/main/java/org/springframework/cloud/sleuth/benchmarks/jmh/benchmarks/StartupBenchmark.java @@ -0,0 +1,76 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cloud.sleuth.benchmarks.jmh.benchmarks; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +@Measurement(iterations = 5) +@Warmup(iterations = 1) +@Fork(value = 2, warmups = 0) +@BenchmarkMode(Mode.AverageTime) +public class StartupBenchmark { + + @Benchmark + public void withAnnotations(ApplicationState state) throws Exception { + state.run(); + } + + @Benchmark + public void withoutAnnotations(ApplicationState state) throws Exception { + state.setExtraArgs("--spring.sleuth.annotation.enabled=false"); + state.run(); + } + + @Benchmark + public void withoutAsync(ApplicationState state) throws Exception { + state.setExtraArgs("--spring.sleuth.async.enabled=false", "--spring.sleuth.annotation.enabled=false"); + state.run(); + } + + @Benchmark + public void withoutScheduled(ApplicationState state) throws Exception { + state.setExtraArgs("--spring.sleuth.scheduled.enabled=false", "--spring.sleuth.async.enabled=false", "--spring.sleuth.annotation.enabled=false"); + state.run(); + } + + @Benchmark + public void withoutWeb(ApplicationState state) throws Exception { + state.setExtraArgs("--spring.sleuth.web.enabled=false", "--spring.sleuth.scheduled.enabled=false", "--spring.sleuth.async.enabled=false", "--spring.sleuth.annotation.enabled=false"); + state.run(); + } + + @State(Scope.Benchmark) + public static class ApplicationState extends ProcessLauncherState { + public ApplicationState() { + super("target", "--server.port=0"); + } + + @TearDown(Level.Iteration) + public void stop() throws Exception { + super.after(); + } + } + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java index 136f05816..7739ff5e9 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java @@ -20,12 +20,14 @@ import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicBoolean; + import javax.annotation.PostConstruct; import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.aop.ClassFilter; import org.springframework.aop.IntroductionAdvisor; import org.springframework.aop.IntroductionInterceptor; @@ -41,7 +43,6 @@ import org.springframework.cloud.sleuth.ErrorParser; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Tracer; import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -52,9 +53,9 @@ import org.springframework.util.StringUtils; * @author Marcin Grzejszczak * @since 1.2.0 */ +@SuppressWarnings("serial") class SleuthAdvisorConfig extends AbstractPointcutAdvisor implements IntroductionAdvisor, BeanFactoryAware { - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); private Advice advice; @@ -117,33 +118,9 @@ class SleuthAdvisorConfig extends AbstractPointcutAdvisor implements private final class AnnotationClassOrMethodOrArgsPointcut extends DynamicMethodMatcherPointcut { - private final DynamicMethodMatcherPointcut methodResolver; - - AnnotationClassOrMethodOrArgsPointcut() { - this.methodResolver = new DynamicMethodMatcherPointcut() { - @Override public boolean matches(Method method, Class targetClass, - Object... args) { - if (SleuthAnnotationUtils.isMethodAnnotated(method)) { - if (log.isDebugEnabled()) { - log.debug("Found a method with Sleuth annotation"); - } - return true; - } - if (SleuthAnnotationUtils.hasAnnotatedParams(method, args)) { - if (log.isDebugEnabled()) { - log.debug("Found annotated arguments of the method"); - } - return true; - } - return false; - } - }; - } - @Override public boolean matches(Method method, Class targetClass, Object... args) { - return getClassFilter().matches(targetClass) || - this.methodResolver.matches(method, targetClass, args); + return getClassFilter().matches(targetClass); } @Override public ClassFilter getClassFilter() { @@ -155,18 +132,6 @@ class SleuthAdvisorConfig extends AbstractPointcutAdvisor implements }; } - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!(other instanceof AnnotationClassOrMethodOrArgsPointcut)) { - return false; - } - AnnotationClassOrMethodOrArgsPointcut otherAdvisor = (AnnotationClassOrMethodOrArgsPointcut) other; - return ObjectUtils.nullSafeEquals(this.methodResolver, otherAdvisor.methodResolver); - } - } private final class AnnotationClassOrMethodFilter extends AnnotationClassFilter {