diff --git a/CHANGES.md b/CHANGES.md index 0961d7be1..d62ac173f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Release Notes. * fix the bug that plugin record wrong time elapse for lettuce plugin * fix the bug that the wrong db.instance value displayed on Skywalking-UI when existing multi-database-instance on same host port pair. * Add thrift plugin support thrift TMultiplexedProcessor. +* Add benchmark result for `exception-ignore` plugin and polish plugin guide. #### Documentation diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/status/HierarchyMatchExceptionBenchmark.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/status/HierarchyMatchExceptionBenchmark.java new file mode 100644 index 000000000..01e3b84e4 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/status/HierarchyMatchExceptionBenchmark.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.skywalking.apm.agent.core.context.status; + +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.concurrent.TimeUnit; + +/** + * # JMH version: 1.33 + * # VM version: JDK 1.8.0_292, OpenJDK 64-Bit Server VM, 25.292-b10 + * # VM invoker: /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/bin/java + * # VM options: -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54972:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 + * # Blackhole mode: full + dont-inline hint (default, use -Djmh.blackhole.autoDetect=true to auto-detect) + * # Warmup: 5 iterations, 10 s each + * # Measurement: 5 iterations, 10 s each + * # Timeout: 10 min per iteration + * # Threads: 1 thread, will synchronize iterations + * # Benchmark mode: Average time, time/op + *

+ * Benchmark Mode Cnt Score Error Units + * HierarchyMatchExceptionBenchmark.depthOneBenchmark avgt 25 31.050 ± 0.731 ns/op + * HierarchyMatchExceptionBenchmark.depthTwoBenchmark avgt 25 64.918 ± 2.537 ns/op + * HierarchyMatchExceptionBenchmark.depthThreeBenchmark avgt 25 89.645 ± 2.556 ns/op + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class HierarchyMatchExceptionBenchmark { + + @State(Scope.Benchmark) + public static class ThrowableState { + static { + Config.StatusCheck.IGNORED_EXCEPTIONS = "java.lang.NullPointerException"; + Config.StatusCheck.MAX_RECURSIVE_DEPTH = 2; + ServiceManager.INSTANCE.boot(); + } + + private final Throwable singleT = new NullPointerException(); + private final Throwable doubleT = new RuntimeException(new NullPointerException()); + private final Throwable tripleT = new RuntimeException(new RuntimeException(new NullPointerException())); + } + + @Benchmark + public void depthOneBenchmark(Blackhole bh, ThrowableState state) { + bh.consume(ServiceManager.INSTANCE.findService(StatusCheckService.class).isError(state.singleT)); + } + + @Benchmark + public void depthTwoBenchmark(Blackhole bh, ThrowableState state) { + bh.consume(ServiceManager.INSTANCE.findService(StatusCheckService.class).isError(state.doubleT)); + } + + @Benchmark + public void depthThreeBenchmark(Blackhole bh, ThrowableState state) { + bh.consume(ServiceManager.INSTANCE.findService(StatusCheckService.class).isError(state.tripleT)); + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(HierarchyMatchExceptionBenchmark.class.getSimpleName()).build(); + new Runner(options).run(); + } +} diff --git a/docs/en/setup/service-agent/java-agent/How-to-tolerate-exceptions.md b/docs/en/setup/service-agent/java-agent/How-to-tolerate-exceptions.md index e80f73c3d..9d64770de 100644 --- a/docs/en/setup/service-agent/java-agent/How-to-tolerate-exceptions.md +++ b/docs/en/setup/service-agent/java-agent/How-to-tolerate-exceptions.md @@ -107,8 +107,34 @@ If an exception has the `@IgnoredException` annotation, the exception wouldn't b `org.apache.skywalking.apm.agent.core.context.status.TestAnnotatedException` | false | ## Recursive check -Due to the wrapper nature of Java exceptions, sometimes users need recursive checking. Skywalking also supports it. Typically, we don't recommend setting this more than 10, which could cause a performance issue. Negative value and 0 would be ignored, which means all exceptions would make the span tagged in error status. +Due to the wrapper nature of Java exceptions, sometimes users need recursive checking. Skywalking also supports it. ``` - statuscheck.max_recursive_depth=${SW_STATUSCHECK_MAX_RECURSIVE_DEPTH:1} +statuscheck.max_recursive_depth=${SW_STATUSCHECK_MAX_RECURSIVE_DEPTH:1} ``` + +The following report shows the benchmark results of the exception checks with different recursive depths, + +``` +# JMH version: 1.33 +# VM version: JDK 1.8.0_292, OpenJDK 64-Bit Server VM, 25.292-b10 +# VM invoker: /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/bin/java +# VM options: -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54972:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 +# Blackhole mode: full + dont-inline hint (default, use -Djmh.blackhole.autoDetect=true to auto-detect) +# Warmup: 5 iterations, 10 s each +# Measurement: 5 iterations, 10 s each +# Timeout: 10 min per iteration +# Threads: 1 thread, will synchronize iterations +# Benchmark mode: Average time, time/op +Benchmark Mode Cnt Score Error Units +HierarchyMatchExceptionBenchmark.depthOneBenchmark avgt 25 31.050 ± 0.731 ns/op +HierarchyMatchExceptionBenchmark.depthTwoBenchmark avgt 25 64.918 ± 2.537 ns/op +HierarchyMatchExceptionBenchmark.depthThreeBenchmark avgt 25 89.645 ± 2.556 ns/op +``` + +According to the reported results above, the exception check time is nearly proportional to the recursive depth being set. +For each single check, it costs about ten of nanoseconds (~30 nanoseconds in the report, but may vary according +to different hardware and platforms). + +Typically, we don't recommend setting this more than 10, which could cause a performance issue. +Negative value and 0 would be ignored, which means all exceptions would make the span tagged in error status. diff --git a/pom.xml b/pom.xml index d16eeb685..c961212db 100755 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,7 @@ 2.5 4.3.0 3.1.0 - 1.21 + 1.33 1.5 true @@ -414,8 +414,8 @@ org/apache/skywalking/oal/rt/grammar/*.java, org/apache/skywalking/oap/server/exporter/grpc/*.java, org/apache/skywalking/oap/server/configuration/service/*.java, - **/generated/*_jmhType*.java, - **/generated/*_jmhTest.java + **/jmh_generated/*_jmhType*.java, + **/jmh_generated/*_jmhTest.java import.control=${maven.multiModuleProjectDirectory}/apm-checkstyle/importControl.xml