This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch groovy-replace in repository https://gitbox.apache.org/repos/asf/skywalking.git
commit f82db7fbc63e8ed43d5fa6d96fc3a1e8331b33bc Author: Wu Sheng <[email protected]> AuthorDate: Sun Mar 1 19:49:01 2026 +0800 Remove microbench module; relocate JMH benchmarks to target modules Move benchmarks from the standalone oap-server/microbench module into the src/test/ directories of the modules they actually test (server-core and library-util). Drop AbstractMicrobenchmark base class in favor of self-contained @Test run() methods. Bump JMH 1.21 -> 1.37 and remove the obsolete -XX:BiasedLockingStartupDelay=0 JVM flag (removed in JDK 18). Co-Authored-By: Claude Opus 4.6 <[email protected]> --- oap-server/microbench/pom.xml | 105 ------ .../microbench/base/AbstractMicrobenchmark.java | 116 ------ .../openapi/EndpointGrouping4OpenapiBenchmark.java | 138 ------- .../group/uri/RegexVSQuickMatchBenchmark.java | 195 ---------- .../ebpf/EBPFProfilingAnalyzerBenchmark.java | 409 --------------------- .../library/util/StringFormatGroupBenchmark.java | 124 ------- oap-server/pom.xml | 9 - oap-server/server-core/pom.xml | 5 + .../openapi/EndpointGroupingBenchmark4Openapi.java | 110 ++++++ .../group/uri/RegexVSQuickMatchBenchmark.java | 135 +++++++ .../analyze/EBPFProfilingAnalyzerBenchmark.java | 199 ++++++++++ oap-server/server-library/library-util/pom.xml | 5 + .../library/util/StringFormatGroupBenchmark.java | 74 ++++ pom.xml | 2 +- 14 files changed, 529 insertions(+), 1097 deletions(-) diff --git a/oap-server/microbench/pom.xml b/oap-server/microbench/pom.xml deleted file mode 100644 index b720d7e84c..0000000000 --- a/oap-server/microbench/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ 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. - ~ - --> - -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <parent> - <artifactId>oap-server</artifactId> - <groupId>org.apache.skywalking</groupId> - <version>9.6.0-SNAPSHOT</version> - </parent> - <modelVersion>4.0.0</modelVersion> - <artifactId>microbench</artifactId> - - <properties> - <jmh.version>1.36</jmh.version> - <slf4j.version>1.7.30</slf4j.version> - <uberjar.name>benchmarks</uberjar.name> - <maven-shade-plugin.version>3.2.3</maven-shade-plugin.version> - </properties> - - <dependencies> - <dependency> - <groupId>org.apache.skywalking</groupId> - <artifactId>server-core</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.skywalking</groupId> - <artifactId>library-util</artifactId> - <version>${project.version}</version> - </dependency> - <!--JMH--> - <dependency> - <groupId>org.openjdk.jmh</groupId> - <artifactId>jmh-core</artifactId> - <version>${jmh.version}</version> - </dependency> - <dependency> - <groupId>org.openjdk.jmh</groupId> - <artifactId>jmh-generator-annprocess</artifactId> - <version>${jmh.version}</version> - <scope>provided</scope> - </dependency> - <!--SLF4j--> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> - <version>${slf4j.version}</version> - </dependency> - <!--JUNIT--> - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter</artifactId> - <scope>compile</scope> - </dependency> - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>${maven-shade-plugin.version}</version> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - <configuration> - <finalName>${uberjar.name}</finalName> - <transformers> - <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> - <mainClass>org.openjdk.jmh.Main</mainClass> - </transformer> - </transformers> - <filters> - <filter> - <artifact>*:*</artifact> - <excludes> - <exclude>**/Log4j2Plugins.dat</exclude> - </excludes> - </filter> - </filters> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> -</project> diff --git a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/base/AbstractMicrobenchmark.java b/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/base/AbstractMicrobenchmark.java deleted file mode 100644 index 6e55b3a05a..0000000000 --- a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/base/AbstractMicrobenchmark.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.oap.server.microbench.base; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; -import org.openjdk.jmh.profile.GCProfiler; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.options.ChainedOptionsBuilder; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import lombok.extern.slf4j.Slf4j; - -/** - * All JMH tests need to extend this class to make it easier for you to complete JMHTest, you can also choose to - * customize runtime conditions (Measurement, Fork, Warmup, etc.) - * <p> - * You can run any of the JMH tests as a normal UT, or you can package it and get all the reported results via `java - * -jar benchmark.jar`, or get the results of a particular Test via `java -jar /benchmarks.jar exampleClassName`. - */ -@Warmup(iterations = AbstractMicrobenchmark.DEFAULT_WARMUP_ITERATIONS) -@Measurement(iterations = AbstractMicrobenchmark.DEFAULT_MEASURE_ITERATIONS) -@Fork(AbstractMicrobenchmark.DEFAULT_FORKS) -@State(Scope.Thread) -@Slf4j -public abstract class AbstractMicrobenchmark { - static final int DEFAULT_WARMUP_ITERATIONS = 10; - - static final int DEFAULT_MEASURE_ITERATIONS = 10; - - static final int DEFAULT_FORKS = 2; - - public static class JmhThreadExecutor extends ThreadPoolExecutor { - public JmhThreadExecutor(int size, String name) { - super(size, size, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory()); - } - } - - private ChainedOptionsBuilder newOptionsBuilder() { - - String className = getClass().getSimpleName(); - - ChainedOptionsBuilder optBuilder = new OptionsBuilder() - // set benchmark class name - .include(".*" + className + ".*") - // add GC profiler - .addProfiler(GCProfiler.class) - //set jvm args - .jvmArgsAppend("-Xmx512m", "-Xms512m", "-XX:MaxDirectMemorySize=512m", - "-XX:BiasedLockingStartupDelay=0", - "-Djmh.executor=CUSTOM", - "-Djmh.executor.class=org.apache.skywalking.oap.server.microbench.base.AbstractMicrobenchmark$JmhThreadExecutor" - ); - - String output = getReportDir(); - if (output != null) { - boolean writeFileStatus; - String filePath = getReportDir() + className + ".json"; - File file = new File(filePath); - - if (file.exists()) { - writeFileStatus = file.delete(); - } else { - writeFileStatus = file.getParentFile().mkdirs(); - try { - writeFileStatus = file.createNewFile(); - } catch (IOException e) { - log.warn("jmh test create file error", e); - } - } - if (writeFileStatus) { - optBuilder.resultFormat(ResultFormatType.JSON) - .result(filePath); - } - } - return optBuilder; - } - - @Test - public void run() throws Exception { - new Runner(newOptionsBuilder().build()).run(); - } - - private static String getReportDir() { - return System.getProperty("perfReportDir"); - } - -} diff --git a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/config/group/openapi/EndpointGrouping4OpenapiBenchmark.java b/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/config/group/openapi/EndpointGrouping4OpenapiBenchmark.java deleted file mode 100644 index c5ed373d17..0000000000 --- a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/config/group/openapi/EndpointGrouping4OpenapiBenchmark.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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.oap.server.microbench.core.config.group.openapi; - -import org.apache.skywalking.oap.server.core.config.group.openapi.EndpointGroupingRule4Openapi; -import org.apache.skywalking.oap.server.core.config.group.openapi.EndpointGroupingRuleReader4Openapi; -import org.apache.skywalking.oap.server.library.util.StringFormatGroup.FormatResult; -import org.apache.skywalking.oap.server.microbench.base.AbstractMicrobenchmark; - -import java.util.Collections; -import java.util.Map; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Threads; -import org.openjdk.jmh.infra.Blackhole; - -@BenchmarkMode({Mode.Throughput}) -@Threads(4) -public class EndpointGrouping4OpenapiBenchmark extends AbstractMicrobenchmark { - private static final String APT_TEST_DATA = " /products1/{id}/%d:\n" + " get:\n" + " post:\n" - + " /products2/{id}/%d:\n" + " get:\n" + " post:\n" - + " /products3/{id}/%d:\n" + " get:\n"; - - private static Map<String, String> createTestFile(int size) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("paths:\n"); - for (int i = 0; i <= size; i++) { - stringBuilder.append(String.format(APT_TEST_DATA, i, i, i)); - } - return Collections.singletonMap("whatever", stringBuilder.toString()); - } - - @State(Scope.Benchmark) - public static class FormatClassPaths20 { - private final EndpointGroupingRule4Openapi rule = new EndpointGroupingRuleReader4Openapi(createTestFile(3)).read(); - - public FormatResult format(String serviceName, String endpointName) { - return rule.format(serviceName, endpointName); - } - } - - @State(Scope.Benchmark) - public static class FormatClassPaths50 { - private final EndpointGroupingRule4Openapi rule = new EndpointGroupingRuleReader4Openapi(createTestFile(9)).read(); - - public FormatResult format(String serviceName, String endpointName) { - return rule.format(serviceName, endpointName); - } - } - - @State(Scope.Benchmark) - public static class FormatClassPaths200 { - private final EndpointGroupingRule4Openapi rule = new EndpointGroupingRuleReader4Openapi(createTestFile(39)).read(); - - public FormatResult format(String serviceName, String endpointName) { - return rule.format(serviceName, endpointName); - } - } - - @Benchmark - public void formatEndpointNameMatchedPaths20(Blackhole bh, FormatClassPaths20 formatClass) { - bh.consume(formatClass.format("serviceA", "GET:/products1/123")); - } - - @Benchmark - public void formatEndpointNameMatchedPaths50(Blackhole bh, FormatClassPaths50 formatClass) { - bh.consume(formatClass.format("serviceA", "GET:/products1/123")); - } - - @Benchmark - public void formatEndpointNameMatchedPaths200(Blackhole bh, FormatClassPaths200 formatClass) { - bh.consume(formatClass.format("serviceA", "GET:/products1/123")); - } - -} - -/* -* The test is assumed each endpoint need to run all match within it's rules group. -* -# JMH version: 1.21 -# 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 CE.app/Contents/lib/idea_rt.jar=58702:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -Xmx512m -Xms512m -# Warmup: 5 iterations, 10 s each -# Measurement: 5 iterations, 10 s each -# Timeout: 10 min per iteration -# Threads: 4 threads, will synchronize iterations -# Benchmark mode: Throughput, ops/time - -Benchmark Mode Cnt Score Error Units -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20 thrpt 5 4318121.026 ± 529374.132 ops/s -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.alloc.rate thrpt 5 4579.740 ± 561.095 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.alloc.rate.norm thrpt 5 1168.000 ± 0.001 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.churn.PS_Eden_Space thrpt 5 4604.284 ± 560.596 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.churn.PS_Eden_Space.norm thrpt 5 1174.266 ± 6.626 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.churn.PS_Survivor_Space thrpt 5 0.476 ± 0.122 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.churn.PS_Survivor_Space.norm thrpt 5 0.121 ± 0.031 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.count thrpt 5 1427.000 counts -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths20:·gc.time thrpt 5 839.000 ms -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200 thrpt 5 551316.187 ± 60567.899 ops/s -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.alloc.rate thrpt 5 3912.675 ± 429.916 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.alloc.rate.norm thrpt 5 7816.000 ± 0.001 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.churn.PS_Eden_Space thrpt 5 3932.895 ± 421.307 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.churn.PS_Eden_Space.norm thrpt 5 7856.526 ± 45.989 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.churn.PS_Survivor_Space thrpt 5 0.396 ± 0.101 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.churn.PS_Survivor_Space.norm thrpt 5 0.791 ± 0.172 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.count thrpt 5 1219.000 counts -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths200:·gc.time thrpt 5 737.000 ms -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50 thrpt 5 2163149.470 ± 67179.001 ops/s -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.alloc.rate thrpt 5 4508.870 ± 141.755 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.alloc.rate.norm thrpt 5 2296.000 ± 0.001 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.churn.PS_Eden_Space thrpt 5 4532.354 ± 146.421 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.churn.PS_Eden_Space.norm thrpt 5 2307.956 ± 10.377 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.churn.PS_Survivor_Space thrpt 5 0.454 ± 0.116 MB/sec -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.churn.PS_Survivor_Space.norm thrpt 5 0.231 ± 0.066 B/op -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.count thrpt 5 1405.000 counts -EndpointGroupingBenchmark4Openapi.formatEndpointNameMatchedPaths50:·gc.time thrpt 5 841.000 ms - */ diff --git a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/config/group/uri/RegexVSQuickMatchBenchmark.java b/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/config/group/uri/RegexVSQuickMatchBenchmark.java deleted file mode 100644 index 60e676783e..0000000000 --- a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/config/group/uri/RegexVSQuickMatchBenchmark.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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.oap.server.microbench.core.config.group.uri; - -import org.apache.skywalking.oap.server.core.config.group.EndpointGroupingRule; -import org.apache.skywalking.oap.server.core.config.group.uri.quickmatch.QuickUriGroupingRule; -import org.apache.skywalking.oap.server.library.util.StringFormatGroup; -import org.apache.skywalking.oap.server.microbench.base.AbstractMicrobenchmark; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -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.Threads; -import org.openjdk.jmh.annotations.Warmup; -import org.openjdk.jmh.infra.Blackhole; - -@Warmup(iterations = 1) -@Measurement(iterations = 1) -@Fork(1) -@State(Scope.Thread) -@BenchmarkMode({Mode.Throughput}) -@Threads(4) -public class RegexVSQuickMatchBenchmark extends AbstractMicrobenchmark { - - @State(Scope.Benchmark) - public static class RegexMatch { - private final EndpointGroupingRule rule = new EndpointGroupingRule(); - - public RegexMatch() { - rule.addRule("service1", "/products/{var}", "/products/.+"); - rule.addRule("service1", "/products/{var}/detail", "/products/.+/detail"); - rule.addRule("service1", "/sales/{var}/1", "/sales/.+/1"); - rule.addRule("service1", "/sales/{var}/2", "/sales/.+/2"); - rule.addRule("service1", "/sales/{var}/3", "/sales/.+/3"); - rule.addRule("service1", "/sales/{var}/4", "/sales/.+/4"); - rule.addRule("service1", "/sales/{var}/5", "/sales/.+/5"); - rule.addRule("service1", "/sales/{var}/6", "/sales/.+/6"); - rule.addRule("service1", "/sales/{var}/7", "/sales/.+/7"); - rule.addRule("service1", "/sales/{var}/8", "/sales/.+/8"); - rule.addRule("service1", "/sales/{var}/9", "/sales/.+/9"); - rule.addRule("service1", "/sales/{var}/10", "/sales/.+/10"); - rule.addRule("service1", "/sales/{var}/11", "/sales/.+/11"); - rule.addRule("service1", "/employees/{var}/profile", "/employees/.+/profile"); - } - - public StringFormatGroup.FormatResult match(String serviceName, String endpointName) { - return rule.format(serviceName, endpointName); - } - } - - @State(Scope.Benchmark) - public static class QuickMatch { - private final QuickUriGroupingRule rule = new QuickUriGroupingRule(); - - public QuickMatch() { - rule.addRule("service1", "/products/{var}"); - rule.addRule("service1", "/products/{var}/detail"); - rule.addRule("service1", "/sales/{var}/1"); - rule.addRule("service1", "/sales/{var}/2"); - rule.addRule("service1", "/sales/{var}/3"); - rule.addRule("service1", "/sales/{var}/4"); - rule.addRule("service1", "/sales/{var}/5"); - rule.addRule("service1", "/sales/{var}/6"); - rule.addRule("service1", "/sales/{var}/7"); - rule.addRule("service1", "/sales/{var}/8"); - rule.addRule("service1", "/sales/{var}/9"); - rule.addRule("service1", "/sales/{var}/10"); - rule.addRule("service1", "/sales/{var}/11"); - rule.addRule("service1", "/employees/{var}/profile"); - } - - public StringFormatGroup.FormatResult match(String serviceName, String endpointName) { - return rule.format(serviceName, endpointName); - } - } - - @Benchmark - public void matchFirstRegex(Blackhole bh, RegexVSQuickMatchBenchmark.RegexMatch formatClass) { - bh.consume(formatClass.match("service1", "/products/123")); - } - - @Benchmark - public void matchFirstQuickUriGrouping(Blackhole bh, RegexVSQuickMatchBenchmark.QuickMatch formatClass) { - bh.consume(formatClass.match("service1", "/products/123")); - } - - @Benchmark - public void matchFourthRegex(Blackhole bh, RegexVSQuickMatchBenchmark.RegexMatch formatClass) { - bh.consume(formatClass.match("service1", "/sales/123/2")); - } - - @Benchmark - public void matchFourthQuickUriGrouping(Blackhole bh, RegexVSQuickMatchBenchmark.QuickMatch formatClass) { - bh.consume(formatClass.match("service1", "/sales/123/2")); - } - - @Benchmark - public void notMatchRegex(Blackhole bh, RegexVSQuickMatchBenchmark.RegexMatch formatClass) { - bh.consume(formatClass.match("service1", "/employees/123")); - } - - @Benchmark - public void notMatchQuickUriGrouping(Blackhole bh, RegexVSQuickMatchBenchmark.QuickMatch formatClass) { - bh.consume(formatClass.match("service1", "/employees/123")); - } -} - -/** - * # JMH version: 1.25 - * # VM version: JDK 16.0.1, OpenJDK 64-Bit Server VM, 16.0.1+9-24 - * # VM invoker: C:\Users\Sky\.jdks\openjdk-16.0.1\bin\java.exe - * # VM options: -ea --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED -Didea.test.cyclic.buffer.size=1048576 -javaagent:Y:\jetbrains\apps\IDEA-U\ch-0\231.8109.175\lib\idea_rt.jar=54938:Y:\jetbrains\apps\IDEA-U\ch-0\231.8109.175\bin -Dfile.encoding=UTF-8 -Xmx512m -Xms512m -XX:MaxDirectMemorySize=512m -XX:BiasedLockingStartupDelay=0 -Djmh.executor=CUSTOM -Djmh.executor.class=org.apache.skywalking.oap.server.microbench.base.AbstractMicrobenchmark$JmhTh [...] - * # Warmup: 1 iterations, 10 s each - * # Measurement: 1 iterations, 10 s each - * # Timeout: 10 min per iteration - * # Threads: 4 threads, will synchronize iterations - * # Benchmark mode: Throughput, ops/time - * # Benchmark: org.apache.skywalking.oap.server.microbench.core.config.group.uri.RegexVSQuickMatchBenchmark.notMatchRegex - * Benchmark Mode Cnt Score Error Units - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping thrpt 48317763.786 ops/s - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.alloc.rate thrpt 8773.225 MB/sec - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.alloc.rate.norm thrpt 200.014 B/op - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.churn.G1_Eden_Space thrpt 8807.405 MB/sec - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.churn.G1_Eden_Space.norm thrpt 200.794 B/op - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.churn.G1_Survivor_Space thrpt 0.050 MB/sec - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.churn.G1_Survivor_Space.norm thrpt 0.001 B/op - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.count thrpt 303.000 counts - * RegexVSQuickMatchBenchmark.matchFirstQuickUriGrouping:·gc.time thrpt 325.000 ms - * RegexVSQuickMatchBenchmark.matchFirstRegex thrpt 41040542.288 ops/s - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.alloc.rate thrpt 8348.690 MB/sec - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.alloc.rate.norm thrpt 224.016 B/op - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.churn.G1_Eden_Space thrpt 8378.454 MB/sec - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.churn.G1_Eden_Space.norm thrpt 224.815 B/op - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.churn.G1_Survivor_Space thrpt 0.057 MB/sec - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.churn.G1_Survivor_Space.norm thrpt 0.002 B/op - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.count thrpt 288.000 counts - * RegexVSQuickMatchBenchmark.matchFirstRegex:·gc.time thrpt 282.000 ms - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping thrpt 35658131.267 ops/s - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.alloc.rate thrpt 8020.546 MB/sec - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.alloc.rate.norm thrpt 248.018 B/op - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.churn.G1_Eden_Space thrpt 8043.279 MB/sec - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.churn.G1_Eden_Space.norm thrpt 248.721 B/op - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.churn.G1_Survivor_Space thrpt 0.045 MB/sec - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.churn.G1_Survivor_Space.norm thrpt 0.001 B/op - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.count thrpt 277.000 counts - * RegexVSQuickMatchBenchmark.matchFourthQuickUriGrouping:·gc.time thrpt 302.000 ms - * RegexVSQuickMatchBenchmark.matchFourthRegex thrpt 11066068.208 ops/s - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.alloc.rate thrpt 8273.312 MB/sec - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.alloc.rate.norm thrpt 824.060 B/op - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.churn.G1_Eden_Space thrpt 8279.984 MB/sec - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.churn.G1_Eden_Space.norm thrpt 824.724 B/op - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.churn.G1_Survivor_Space thrpt 0.052 MB/sec - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.churn.G1_Survivor_Space.norm thrpt 0.005 B/op - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.count thrpt 285.000 counts - * RegexVSQuickMatchBenchmark.matchFourthRegex:·gc.time thrpt 324.000 ms - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping thrpt 45843193.472 ops/s - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.alloc.rate thrpt 8653.215 MB/sec - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.alloc.rate.norm thrpt 208.015 B/op - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.churn.G1_Eden_Space thrpt 8652.365 MB/sec - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.churn.G1_Eden_Space.norm thrpt 207.995 B/op - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.churn.G1_Survivor_Space thrpt 0.048 MB/sec - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.churn.G1_Survivor_Space.norm thrpt 0.001 B/op - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.count thrpt 298.000 counts - * RegexVSQuickMatchBenchmark.notMatchQuickUriGrouping:·gc.time thrpt 358.000 ms - * RegexVSQuickMatchBenchmark.notMatchRegex thrpt 3434953.426 ops/s - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.alloc.rate thrpt 8898.075 MB/sec - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.alloc.rate.norm thrpt 2856.206 B/op - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.churn.G1_Eden_Space thrpt 8886.568 MB/sec - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.churn.G1_Eden_Space.norm thrpt 2852.512 B/op - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.churn.G1_Survivor_Space thrpt 0.052 MB/sec - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.churn.G1_Survivor_Space.norm thrpt 0.017 B/op - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.count thrpt 306.000 counts - * RegexVSQuickMatchBenchmark.notMatchRegex:·gc.time thrpt 377.000 ms - * - * Process finished with exit code 0 - */ \ No newline at end of file diff --git a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/profiling/ebpf/EBPFProfilingAnalyzerBenchmark.java b/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/profiling/ebpf/EBPFProfilingAnalyzerBenchmark.java deleted file mode 100644 index 3ec3fa8388..0000000000 --- a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/core/profiling/ebpf/EBPFProfilingAnalyzerBenchmark.java +++ /dev/null @@ -1,409 +0,0 @@ -/* - * 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.oap.server.microbench.core.profiling.ebpf; - -import org.apache.skywalking.oap.server.core.profiling.ebpf.analyze.EBPFProfilingAnalyzer; -import org.apache.skywalking.oap.server.core.profiling.ebpf.analyze.EBPFProfilingStack; -import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingStackType; -import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzation; -import org.apache.skywalking.oap.server.microbench.base.AbstractMicrobenchmark; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Threads; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode({Mode.Throughput}) -@Threads(4) -public class EBPFProfilingAnalyzerBenchmark extends AbstractMicrobenchmark { - - private static final Random RANDOM = new Random(System.currentTimeMillis()); - private static final int SYMBOL_LENGTH = 10; - private static final char[] SYMBOL_TABLE = "abcdefgABCDEFG1234567890_[]<>.".toCharArray(); - private static final EBPFProfilingStackType[] STACK_TYPES = new EBPFProfilingStackType[]{ - EBPFProfilingStackType.KERNEL_SPACE, EBPFProfilingStackType.USER_SPACE}; - - private static List<EBPFProfilingStack> generateStacks(int totalStackCount, - int perStackMinDepth, int perStackMaxDepth, - double[] stackSymbolDuplicateRate, - double stackDuplicateRate) { - int uniqStackCount = (int) (100 / stackDuplicateRate); - final List<EBPFProfilingStack> stacks = new ArrayList<>(totalStackCount); - final StackSymbolGenerator stackSymbolGenerator = new StackSymbolGenerator(stackSymbolDuplicateRate, perStackMaxDepth); - for (int inx = 0; inx < uniqStackCount; inx++) { - final EBPFProfilingStack s = generateStack(perStackMinDepth, perStackMaxDepth, stackSymbolGenerator); - stacks.add(s); - } - for (int inx = uniqStackCount; inx < totalStackCount; inx++) { - stacks.add(stacks.get(RANDOM.nextInt(uniqStackCount))); - } - return stacks; - } - - private static class StackSymbolGenerator { - private final Map<Integer, Integer> stackDepthSymbolCount; - private final Map<Integer, List<String>> existingSymbolMap; - - public StackSymbolGenerator(double[] stackSymbolDuplicateRate, int maxDepth) { - this.stackDepthSymbolCount = new HashMap<>(); - for (int depth = 0; depth < maxDepth; depth++) { - double rate = stackSymbolDuplicateRate[stackSymbolDuplicateRate.length - 1]; - if (stackSymbolDuplicateRate.length > depth) { - rate = stackSymbolDuplicateRate[depth]; - } - int uniqStackCount = (int) (100 / rate); - stackDepthSymbolCount.put(depth, uniqStackCount); - } - this.existingSymbolMap = new HashMap<>(); - } - - public String generate(int depth) { - List<String> symbols = existingSymbolMap.get(depth); - if (symbols == null) { - existingSymbolMap.put(depth, symbols = new ArrayList<>()); - } - final Integer needCount = this.stackDepthSymbolCount.get(depth); - if (symbols.size() < needCount) { - final StringBuilder sb = new StringBuilder(SYMBOL_LENGTH); - for (int j = 0; j < SYMBOL_LENGTH; j++) { - sb.append(SYMBOL_TABLE[RANDOM.nextInt(SYMBOL_TABLE.length)]); - } - final String s = sb.toString(); - symbols.add(s); - return s; - } else { - return symbols.get(RANDOM.nextInt(symbols.size())); - } - } - } - - private static EBPFProfilingStack generateStack(int stackMinDepth, int stackMaxDepth, - StackSymbolGenerator stackSymbolGenerator) { - int stackDepth = stackMinDepth + RANDOM.nextInt(stackMaxDepth - stackMinDepth); - final List<EBPFProfilingStack.Symbol> symbols = new ArrayList<>(stackDepth); - for (int i = 0; i < stackDepth; i++) { - final EBPFProfilingStack.Symbol symbol = new EBPFProfilingStack.Symbol( - stackSymbolGenerator.generate(i), buildStackType(i, stackDepth)); - symbols.add(symbol); - } - final EBPFProfilingStack stack = new EBPFProfilingStack(); - stack.setDumpCount(RANDOM.nextInt(100)); - stack.setSymbols(symbols); - return stack; - } - - private static EBPFProfilingStackType buildStackType(int currentDepth, int totalDepth) { - final int partition = totalDepth / STACK_TYPES.length; - for (int i = 1; i <= STACK_TYPES.length; i++) { - if (currentDepth < i * partition) { - return STACK_TYPES[i - 1]; - } - } - return STACK_TYPES[STACK_TYPES.length - 1]; - } - - public static class DataSource { - private final List<EBPFProfilingStack> stackStream; - - public DataSource(List<EBPFProfilingStack> stackStream) { - this.stackStream = stackStream; - } - - public void analyze() { - new EBPFProfilingAnalyzer(null, 100, 5).generateTrees(new EBPFProfilingAnalyzation(), stackStream.parallelStream()); - } - } - - private static int calculateStackCount(int stackReportPeriodSecond, int totalTimeMinute, int combineInstanceCount) { - return (int) (TimeUnit.MINUTES.toSeconds(totalTimeMinute) / stackReportPeriodSecond * combineInstanceCount); - } - - @State(Scope.Benchmark) - public static class LowDataSource extends DataSource { - // rover report period: 5s - // dump duration: 60m - // 10 instance analyze - // stack depth range: 15, 30 - // stack duplicate rate: 5% - // stack symbol duplicate rate: 100%, 40%, 35%, 30%, 15%, 10%, 7%, 5% - public LowDataSource() { - super(generateStacks(calculateStackCount(5, 60, 10), 15, 30, - new double[]{100, 50, 45, 40, 35, 30, 15, 10, 5}, 5)); - } - } - - @State(Scope.Benchmark) - public static class MedianDatasource extends DataSource { - // rover report period: 5s - // dump duration: 100m - // 200 instance analyze - // stack depth range: 15, 30 - // stack duplicate rate: 3% - // stack symbol duplicate rate: 50%, 40%, 35%, 30%, 20%, 10%, 7%, 5%, 2% - public MedianDatasource() { - super(generateStacks(calculateStackCount(5, 100, 200), 15, 30, - new double[]{50, 40, 35, 30, 20, 10, 7, 5, 2}, 3)); - } - } - - @State(Scope.Benchmark) - public static class HighDatasource extends DataSource { - // rover report period: 5s - // dump time: 2h - // 2000 instance analyze - // stack depth range: 15, 40 - // stack duplicate rate: 1% - // stack symbol duplicate rate: 30%, 27%, 25%, 20%, 17%, 15%, 10%, 7%, 5%, 2%, 1% - public HighDatasource() { - super(generateStacks(calculateStackCount(5, 2 * 60, 2000), 15, 40, - new double[]{30, 27, 25, 20, 17, 15, 10, 7, 5, 2, 1}, 1)); - } - } - - @Benchmark - public void analyzeLowDataSource(LowDataSource lowDataSource) { - lowDataSource.analyze(); - } - - @Benchmark - public void analyzeMedianDataSource(MedianDatasource medianDatasource) { - medianDatasource.analyze(); - } - - @Benchmark - public void analyzeMaxDataSource(HighDatasource highDataSource) { - highDataSource.analyze(); - } - -} - -/* -# JMH version: 1.25 -# VM version: JDK 1.8.0_292, OpenJDK 64-Bit Server VM, 25.292-b10 -# VM invoker: /Users/hanliu/.sdkman/candidates/java/8.0.292.hs-adpt/jre/bin/java -# VM options: <none> -# Warmup: 10 iterations, 10 s each -# Measurement: 10 iterations, 10 s each -# Timeout: 10 min per iteration -# Threads: 4 threads, will synchronize iterations -# Benchmark mode: Throughput, ops/time -# Benchmark: org.apache.skywalking.oap.server.microbench.core.profiling.ebpf.EBPFProfilingAnalyzerBenchmark.analyzeLowDataSource - -# Run progress: 0.00% complete, ETA 00:20:00 -# Fork: 1 of 2 -# Warmup Iteration 1: 2774.619 ops/s -# Warmup Iteration 2: 2652.912 ops/s -# Warmup Iteration 3: 2651.943 ops/s -# Warmup Iteration 4: 2670.755 ops/s -# Warmup Iteration 5: 2632.884 ops/s -# Warmup Iteration 6: 2597.808 ops/s -# Warmup Iteration 7: 2256.900 ops/s -# Warmup Iteration 8: 2105.842 ops/s -# Warmup Iteration 9: 2084.963 ops/s -# Warmup Iteration 10: 2142.089 ops/s -Iteration 1: 2168.913 ops/s -Iteration 2: 2161.030 ops/s -Iteration 3: 2170.136 ops/s -Iteration 4: 2161.335 ops/s -Iteration 5: 2167.978 ops/s -Iteration 6: 2154.508 ops/s -Iteration 7: 2136.985 ops/s -Iteration 8: 2107.246 ops/s -Iteration 9: 2084.855 ops/s -Iteration 10: 2071.664 ops/s - -# Run progress: 16.67% complete, ETA 00:16:44 -# Fork: 2 of 2 -# Warmup Iteration 1: 2094.858 ops/s -# Warmup Iteration 2: 2324.678 ops/s -# Warmup Iteration 3: 2238.370 ops/s -# Warmup Iteration 4: 2252.727 ops/s -# Warmup Iteration 5: 2149.959 ops/s -# Warmup Iteration 6: 2155.332 ops/s -# Warmup Iteration 7: 2141.820 ops/s -# Warmup Iteration 8: 2154.514 ops/s -# Warmup Iteration 9: 2145.600 ops/s -# Warmup Iteration 10: 2129.701 ops/s -Iteration 1: 2157.904 ops/s -Iteration 2: 2145.461 ops/s -Iteration 3: 2155.163 ops/s -Iteration 4: 2154.556 ops/s -Iteration 5: 2161.428 ops/s -Iteration 6: 2150.353 ops/s -Iteration 7: 2161.267 ops/s -Iteration 8: 2092.811 ops/s -Iteration 9: 2059.780 ops/s -Iteration 10: 2061.371 ops/s - - -Result "org.apache.skywalking.oap.server.microbench.core.profiling.ebpf.EBPFProfilingAnalyzerBenchmark.analyzeLowDataSource": - 2134.237 ±(99.9%) 33.583 ops/s [Average] - (min, avg, max) = (2059.780, 2134.237, 2170.136), stdev = 38.674 - CI (99.9%): [2100.654, 2167.820] (assumes normal distribution) - - -# JMH version: 1.25 -# VM version: JDK 1.8.0_292, OpenJDK 64-Bit Server VM, 25.292-b10 -# VM invoker: /Users/hanliu/.sdkman/candidates/java/8.0.292.hs-adpt/jre/bin/java -# VM options: <none> -# Warmup: 10 iterations, 10 s each -# Measurement: 10 iterations, 10 s each -# Timeout: 10 min per iteration -# Threads: 4 threads, will synchronize iterations -# Benchmark mode: Throughput, ops/time -# Benchmark: org.apache.skywalking.oap.server.microbench.core.profiling.ebpf.EBPFProfilingAnalyzerBenchmark.analyzeMaxDataSource - -# Run progress: 33.33% complete, ETA 00:13:24 -# Fork: 1 of 2 -# Warmup Iteration 1: 6.534 ops/s -# Warmup Iteration 2: 6.695 ops/s -# Warmup Iteration 3: 6.722 ops/s -# Warmup Iteration 4: 6.473 ops/s -# Warmup Iteration 5: 6.431 ops/s -# Warmup Iteration 6: 6.391 ops/s -# Warmup Iteration 7: 6.401 ops/s -# Warmup Iteration 8: 6.290 ops/s -# Warmup Iteration 9: 6.087 ops/s -# Warmup Iteration 10: 6.143 ops/s -Iteration 1: 5.989 ops/s -Iteration 2: 6.386 ops/s -Iteration 3: 6.397 ops/s -Iteration 4: 6.395 ops/s -Iteration 5: 6.374 ops/s -Iteration 6: 6.192 ops/s -Iteration 7: 6.111 ops/s -Iteration 8: 6.049 ops/s -Iteration 9: 6.104 ops/s -Iteration 10: 6.130 ops/s - -# Run progress: 50.00% complete, ETA 00:10:20 -# Fork: 2 of 2 -# Warmup Iteration 1: 5.981 ops/s -# Warmup Iteration 2: 6.433 ops/s -# Warmup Iteration 3: 6.421 ops/s -# Warmup Iteration 4: 6.215 ops/s -# Warmup Iteration 5: 6.139 ops/s -# Warmup Iteration 6: 6.165 ops/s -# Warmup Iteration 7: 6.153 ops/s -# Warmup Iteration 8: 6.123 ops/s -# Warmup Iteration 9: 6.107 ops/s -# Warmup Iteration 10: 6.044 ops/s -Iteration 1: 5.869 ops/s -Iteration 2: 5.837 ops/s -Iteration 3: 5.836 ops/s -Iteration 4: 5.994 ops/s -Iteration 5: 6.187 ops/s -Iteration 6: 6.129 ops/s -Iteration 7: 6.111 ops/s -Iteration 8: 6.150 ops/s -Iteration 9: 6.154 ops/s -Iteration 10: 6.165 ops/s - - -Result "org.apache.skywalking.oap.server.microbench.core.profiling.ebpf.EBPFProfilingAnalyzerBenchmark.analyzeMaxDataSource": - 6.128 ±(99.9%) 0.149 ops/s [Average] - (min, avg, max) = (5.836, 6.128, 6.397), stdev = 0.172 - CI (99.9%): [5.979, 6.277] (assumes normal distribution) - - -# JMH version: 1.25 -# VM version: JDK 1.8.0_292, OpenJDK 64-Bit Server VM, 25.292-b10 -# VM invoker: /Users/hanliu/.sdkman/candidates/java/8.0.292.hs-adpt/jre/bin/java -# VM options: <none> -# Warmup: 10 iterations, 10 s each -# Measurement: 10 iterations, 10 s each -# Timeout: 10 min per iteration -# Threads: 4 threads, will synchronize iterations -# Benchmark mode: Throughput, ops/time -# Benchmark: org.apache.skywalking.oap.server.microbench.core.profiling.ebpf.EBPFProfilingAnalyzerBenchmark.analyzeMedianDataSource - -# Run progress: 66.67% complete, ETA 00:06:59 -# Fork: 1 of 2 -# Warmup Iteration 1: 98.581 ops/s -# Warmup Iteration 2: 101.972 ops/s -# Warmup Iteration 3: 102.758 ops/s -# Warmup Iteration 4: 102.755 ops/s -# Warmup Iteration 5: 102.637 ops/s -# Warmup Iteration 6: 102.341 ops/s -# Warmup Iteration 7: 101.472 ops/s -# Warmup Iteration 8: 101.128 ops/s -# Warmup Iteration 9: 97.455 ops/s -# Warmup Iteration 10: 96.327 ops/s -Iteration 1: 95.448 ops/s -Iteration 2: 100.029 ops/s -Iteration 3: 101.103 ops/s -Iteration 4: 101.236 ops/s -Iteration 5: 100.893 ops/s -Iteration 6: 101.052 ops/s -Iteration 7: 100.859 ops/s -Iteration 8: 101.174 ops/s -Iteration 9: 101.237 ops/s -Iteration 10: 101.146 ops/s - -# Run progress: 83.33% complete, ETA 00:03:28 -# Fork: 2 of 2 -# Warmup Iteration 1: 92.453 ops/s -# Warmup Iteration 2: 95.494 ops/s -# Warmup Iteration 3: 95.363 ops/s -# Warmup Iteration 4: 95.391 ops/s -# Warmup Iteration 5: 95.126 ops/s -# Warmup Iteration 6: 94.867 ops/s -# Warmup Iteration 7: 94.034 ops/s -# Warmup Iteration 8: 89.720 ops/s -# Warmup Iteration 9: 87.873 ops/s -# Warmup Iteration 10: 89.747 ops/s -Iteration 1: 93.948 ops/s -Iteration 2: 93.365 ops/s -Iteration 3: 94.219 ops/s -Iteration 4: 94.004 ops/s -Iteration 5: 94.352 ops/s -Iteration 6: 94.299 ops/s -Iteration 7: 94.336 ops/s -Iteration 8: 93.926 ops/s -Iteration 9: 93.592 ops/s -Iteration 10: 92.966 ops/s - - -Result "org.apache.skywalking.oap.server.microbench.core.profiling.ebpf.EBPFProfilingAnalyzerBenchmark.analyzeMedianDataSource": - 97.159 ±(99.9%) 3.105 ops/s [Average] - (min, avg, max) = (92.966, 97.159, 101.237), stdev = 3.575 - CI (99.9%): [94.055, 100.264] (assumes normal distribution) - - -# Run complete. Total time: 00:20:43 - -REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on -why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial -experiments, perform baseline and negative tests that provide experimental control, make sure -the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. -Do not assume the numbers tell you what you want them to tell. - -Benchmark Mode Cnt Score Error Units -EBPFProfilingAnalyzerBenchmark.analyzeLowDataSource thrpt 20 2134.237 ± 33.583 ops/s -EBPFProfilingAnalyzerBenchmark.analyzeMaxDataSource thrpt 20 6.128 ± 0.149 ops/s -EBPFProfilingAnalyzerBenchmark.analyzeMedianDataSource thrpt 20 97.159 ± 3.105 ops/s - */ diff --git a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/library/util/StringFormatGroupBenchmark.java b/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/library/util/StringFormatGroupBenchmark.java deleted file mode 100644 index 71837e69dc..0000000000 --- a/oap-server/microbench/src/main/java/org/apache/skywalking/oap/server/microbench/library/util/StringFormatGroupBenchmark.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.oap.server.microbench.library.util; - -import org.apache.skywalking.oap.server.library.util.StringFormatGroup; -import org.apache.skywalking.oap.server.microbench.base.AbstractMicrobenchmark; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -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 java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -public class StringFormatGroupBenchmark extends AbstractMicrobenchmark { - @Benchmark - @Test - public void testMatch() { - StringFormatGroup group = new StringFormatGroup(); - group.addRule("/name/*/add", "/name/.+/add"); - Assertions.assertEquals("/name/*/add", group.format("/name/test/add").getName()); - - group = new StringFormatGroup(); - group.addRule("/name/*/add/{orderId}", "/name/.+/add/.*"); - Assertions.assertEquals("/name/*/add/{orderId}", group.format("/name/test/add/12323").getName()); - } - - @Benchmark - @Test - public void test100Rule() { - StringFormatGroup group = new StringFormatGroup(); - group.addRule("/name/*/add/{orderId}", "/name/.+/add/.*"); - for (int i = 0; i < 100; i++) { - group.addRule("/name/*/add/{orderId}" + "/" + 1, "/name/.+/add/.*" + "/abc"); - } - Assertions.assertEquals("/name/*/add/{orderId}", group.format("/name/test/add/12323").getName()); - } - - /********************************* - * # JMH version: 1.21 - * # VM version: JDK 1.8.0_91, Java HotSpot(TM) 64-Bit Server VM, 25.91-b14 - * # VM invoker: /Users/wusheng/Documents/applications/jdk1.8.0_91.jdk/Contents/Home/jre/bin/java - * # VM options: -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54841:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 - * # Warmup: <none> - * # Measurement: 5 iterations, 10 s each - * # Timeout: 10 min per iteration - * # Threads: 1 thread, will synchronize iterations - * # Benchmark mode: Throughput, ops/time - * # Benchmark: org.apache.skywalking.apm.util.StringFormatGroupTest.test100Rule - * - * # Run progress: 0.00% complete, ETA 00:01:40 - * # Fork: 1 of 1 - * Iteration 1: 32016.496 ops/s - * Iteration 2: 36703.873 ops/s - * Iteration 3: 37121.543 ops/s - * Iteration 4: 36898.225 ops/s - * Iteration 5: 34712.564 ops/s - * - * - * Result "org.apache.skywalking.apm.util.StringFormatGroupTest.test100Rule": - * 35490.540 ±(99.9%) 8345.368 ops/s [Average] - * (min, avg, max) = (32016.496, 35490.540, 37121.543), stdev = 2167.265 - * CI (99.9%): [27145.173, 43835.908] (assumes normal distribution) - * - * - * # JMH version: 1.21 - * # VM version: JDK 1.8.0_91, Java HotSpot(TM) 64-Bit Server VM, 25.91-b14 - * # VM invoker: /Users/wusheng/Documents/applications/jdk1.8.0_91.jdk/Contents/Home/jre/bin/java - * # VM options: -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54841:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 - * # Warmup: <none> - * # Measurement: 5 iterations, 10 s each - * # Timeout: 10 min per iteration - * # Threads: 1 thread, will synchronize iterations - * # Benchmark mode: Throughput, ops/time - * # Benchmark: org.apache.skywalking.apm.util.StringFormatGroupTest.testMatch - * - * # Run progress: 50.00% complete, ETA 00:00:50 - * # Fork: 1 of 1 - * Iteration 1: 1137158.205 ops/s - * Iteration 2: 1192936.161 ops/s - * Iteration 3: 1218773.403 ops/s - * Iteration 4: 1222966.452 ops/s - * Iteration 5: 1235609.354 ops/s - * - * - * Result "org.apache.skywalking.apm.util.StringFormatGroupTest.testMatch": - * 1201488.715 ±(99.9%) 150813.461 ops/s [Average] - * (min, avg, max) = (1137158.205, 1201488.715, 1235609.354), stdev = 39165.777 - * CI (99.9%): [1050675.254, 1352302.176] (assumes normal distribution) - * - * - * # Run complete. Total time: 00:01:41 - * - * REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on - * why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial - * experiments, perform baseline and negative tests that provide experimental control, make sure - * the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. - * Do not assume the numbers tell you what you want them to tell. - * - * Benchmark Mode Cnt Score Error Units - * StringFormatGroupTest.test100Rule thrpt 5 35490.540 ± 8345.368 ops/s - * StringFormatGroupTest.testMatch thrpt 5 1201488.715 ± 150813.461 ops/s - * - */ -} diff --git a/oap-server/pom.xml b/oap-server/pom.xml index c457b90391..93cc75452b 100755 --- a/oap-server/pom.xml +++ b/oap-server/pom.xml @@ -51,15 +51,6 @@ <module>mqe-rt</module> </modules> - <profiles> - <profile> - <id>benchmark</id> - <modules> - <module>microbench</module> - </modules> - </profile> - </profiles> - <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> diff --git a/oap-server/server-core/pom.xml b/oap-server/server-core/pom.xml index fd12143671..484507e63b 100644 --- a/oap-server/server-core/pom.xml +++ b/oap-server/server-core/pom.xml @@ -103,6 +103,11 @@ <artifactId>grpc-testing</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-generator-annprocess</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>io.zipkin.zipkin2</groupId> <artifactId>zipkin</artifactId> diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/openapi/EndpointGroupingBenchmark4Openapi.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/openapi/EndpointGroupingBenchmark4Openapi.java new file mode 100644 index 0000000000..15c1e7a623 --- /dev/null +++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/openapi/EndpointGroupingBenchmark4Openapi.java @@ -0,0 +1,110 @@ +/* + * 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.oap.server.core.config.group.openapi; + +import org.apache.skywalking.oap.server.library.util.StringFormatGroup.FormatResult; + +import java.util.Collections; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +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.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@Fork(2) +@State(Scope.Thread) +@BenchmarkMode({Mode.Throughput}) +@Threads(4) +public class EndpointGroupingBenchmark4Openapi { + private static final String APT_TEST_DATA = " /products1/{id}/%d:\n" + " get:\n" + " post:\n" + + " /products2/{id}/%d:\n" + " get:\n" + " post:\n" + + " /products3/{id}/%d:\n" + " get:\n"; + + private static Map<String, String> createTestFile(int size) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("paths:\n"); + for (int i = 0; i <= size; i++) { + stringBuilder.append(String.format(APT_TEST_DATA, i, i, i)); + } + return Collections.singletonMap("whatever", stringBuilder.toString()); + } + + @State(Scope.Benchmark) + public static class FormatClassPaths20 { + private final EndpointGroupingRule4Openapi rule = new EndpointGroupingRuleReader4Openapi(createTestFile(3)).read(); + + public FormatResult format(String serviceName, String endpointName) { + return rule.format(serviceName, endpointName); + } + } + + @State(Scope.Benchmark) + public static class FormatClassPaths50 { + private final EndpointGroupingRule4Openapi rule = new EndpointGroupingRuleReader4Openapi(createTestFile(9)).read(); + + public FormatResult format(String serviceName, String endpointName) { + return rule.format(serviceName, endpointName); + } + } + + @State(Scope.Benchmark) + public static class FormatClassPaths200 { + private final EndpointGroupingRule4Openapi rule = new EndpointGroupingRuleReader4Openapi(createTestFile(39)).read(); + + public FormatResult format(String serviceName, String endpointName) { + return rule.format(serviceName, endpointName); + } + } + + @Benchmark + public void formatEndpointNameMatchedPaths20(Blackhole bh, FormatClassPaths20 formatClass) { + bh.consume(formatClass.format("serviceA", "GET:/products1/123")); + } + + @Benchmark + public void formatEndpointNameMatchedPaths50(Blackhole bh, FormatClassPaths50 formatClass) { + bh.consume(formatClass.format("serviceA", "GET:/products1/123")); + } + + @Benchmark + public void formatEndpointNameMatchedPaths200(Blackhole bh, FormatClassPaths200 formatClass) { + bh.consume(formatClass.format("serviceA", "GET:/products1/123")); + } + + @Test + public void run() throws Exception { + new Runner(new OptionsBuilder() + .include(".*" + getClass().getSimpleName() + ".*") + .jvmArgsAppend("-Xmx512m", "-Xms512m") + .build()).run(); + } + +} diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/uri/RegexVSQuickMatchBenchmark.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/uri/RegexVSQuickMatchBenchmark.java new file mode 100644 index 0000000000..d4525bfe5a --- /dev/null +++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/config/group/uri/RegexVSQuickMatchBenchmark.java @@ -0,0 +1,135 @@ +/* + * 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.oap.server.core.config.group.uri; + +import org.apache.skywalking.oap.server.core.config.group.EndpointGroupingRule; +import org.apache.skywalking.oap.server.core.config.group.uri.quickmatch.QuickUriGroupingRule; +import org.apache.skywalking.oap.server.library.util.StringFormatGroup; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +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.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +@Warmup(iterations = 1) +@Measurement(iterations = 1) +@Fork(1) +@State(Scope.Thread) +@BenchmarkMode({Mode.Throughput}) +@Threads(4) +public class RegexVSQuickMatchBenchmark { + + @State(Scope.Benchmark) + public static class RegexMatch { + private final EndpointGroupingRule rule = new EndpointGroupingRule(); + + public RegexMatch() { + rule.addRule("service1", "/products/{var}", "/products/.+"); + rule.addRule("service1", "/products/{var}/detail", "/products/.+/detail"); + rule.addRule("service1", "/sales/{var}/1", "/sales/.+/1"); + rule.addRule("service1", "/sales/{var}/2", "/sales/.+/2"); + rule.addRule("service1", "/sales/{var}/3", "/sales/.+/3"); + rule.addRule("service1", "/sales/{var}/4", "/sales/.+/4"); + rule.addRule("service1", "/sales/{var}/5", "/sales/.+/5"); + rule.addRule("service1", "/sales/{var}/6", "/sales/.+/6"); + rule.addRule("service1", "/sales/{var}/7", "/sales/.+/7"); + rule.addRule("service1", "/sales/{var}/8", "/sales/.+/8"); + rule.addRule("service1", "/sales/{var}/9", "/sales/.+/9"); + rule.addRule("service1", "/sales/{var}/10", "/sales/.+/10"); + rule.addRule("service1", "/sales/{var}/11", "/sales/.+/11"); + rule.addRule("service1", "/employees/{var}/profile", "/employees/.+/profile"); + } + + public StringFormatGroup.FormatResult match(String serviceName, String endpointName) { + return rule.format(serviceName, endpointName); + } + } + + @State(Scope.Benchmark) + public static class QuickMatch { + private final QuickUriGroupingRule rule = new QuickUriGroupingRule(); + + public QuickMatch() { + rule.addRule("service1", "/products/{var}"); + rule.addRule("service1", "/products/{var}/detail"); + rule.addRule("service1", "/sales/{var}/1"); + rule.addRule("service1", "/sales/{var}/2"); + rule.addRule("service1", "/sales/{var}/3"); + rule.addRule("service1", "/sales/{var}/4"); + rule.addRule("service1", "/sales/{var}/5"); + rule.addRule("service1", "/sales/{var}/6"); + rule.addRule("service1", "/sales/{var}/7"); + rule.addRule("service1", "/sales/{var}/8"); + rule.addRule("service1", "/sales/{var}/9"); + rule.addRule("service1", "/sales/{var}/10"); + rule.addRule("service1", "/sales/{var}/11"); + rule.addRule("service1", "/employees/{var}/profile"); + } + + public StringFormatGroup.FormatResult match(String serviceName, String endpointName) { + return rule.format(serviceName, endpointName); + } + } + + @Benchmark + public void matchFirstRegex(Blackhole bh, RegexMatch formatClass) { + bh.consume(formatClass.match("service1", "/products/123")); + } + + @Benchmark + public void matchFirstQuickUriGrouping(Blackhole bh, QuickMatch formatClass) { + bh.consume(formatClass.match("service1", "/products/123")); + } + + @Benchmark + public void matchFourthRegex(Blackhole bh, RegexMatch formatClass) { + bh.consume(formatClass.match("service1", "/sales/123/2")); + } + + @Benchmark + public void matchFourthQuickUriGrouping(Blackhole bh, QuickMatch formatClass) { + bh.consume(formatClass.match("service1", "/sales/123/2")); + } + + @Benchmark + public void notMatchRegex(Blackhole bh, RegexMatch formatClass) { + bh.consume(formatClass.match("service1", "/employees/123")); + } + + @Benchmark + public void notMatchQuickUriGrouping(Blackhole bh, QuickMatch formatClass) { + bh.consume(formatClass.match("service1", "/employees/123")); + } + + @Test + public void run() throws Exception { + new Runner(new OptionsBuilder() + .include(".*" + getClass().getSimpleName() + ".*") + .jvmArgsAppend("-Xmx512m", "-Xms512m") + .build()).run(); + } +} diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profiling/ebpf/analyze/EBPFProfilingAnalyzerBenchmark.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profiling/ebpf/analyze/EBPFProfilingAnalyzerBenchmark.java new file mode 100644 index 0000000000..c359f4cdc1 --- /dev/null +++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profiling/ebpf/analyze/EBPFProfilingAnalyzerBenchmark.java @@ -0,0 +1,199 @@ +/* + * 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.oap.server.core.profiling.ebpf.analyze; + +import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingStackType; +import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingAnalyzation; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +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.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@Fork(2) +@State(Scope.Thread) +@BenchmarkMode({Mode.Throughput}) +@Threads(4) +public class EBPFProfilingAnalyzerBenchmark { + + private static final Random RANDOM = new Random(System.currentTimeMillis()); + private static final int SYMBOL_LENGTH = 10; + private static final char[] SYMBOL_TABLE = "abcdefgABCDEFG1234567890_[]<>.".toCharArray(); + private static final EBPFProfilingStackType[] STACK_TYPES = new EBPFProfilingStackType[]{ + EBPFProfilingStackType.KERNEL_SPACE, EBPFProfilingStackType.USER_SPACE}; + + private static List<EBPFProfilingStack> generateStacks(int totalStackCount, + int perStackMinDepth, int perStackMaxDepth, + double[] stackSymbolDuplicateRate, + double stackDuplicateRate) { + int uniqStackCount = (int) (100 / stackDuplicateRate); + final List<EBPFProfilingStack> stacks = new ArrayList<>(totalStackCount); + final StackSymbolGenerator stackSymbolGenerator = new StackSymbolGenerator(stackSymbolDuplicateRate, perStackMaxDepth); + for (int inx = 0; inx < uniqStackCount; inx++) { + final EBPFProfilingStack s = generateStack(perStackMinDepth, perStackMaxDepth, stackSymbolGenerator); + stacks.add(s); + } + for (int inx = uniqStackCount; inx < totalStackCount; inx++) { + stacks.add(stacks.get(RANDOM.nextInt(uniqStackCount))); + } + return stacks; + } + + private static class StackSymbolGenerator { + private final Map<Integer, Integer> stackDepthSymbolCount; + private final Map<Integer, List<String>> existingSymbolMap; + + public StackSymbolGenerator(double[] stackSymbolDuplicateRate, int maxDepth) { + this.stackDepthSymbolCount = new HashMap<>(); + for (int depth = 0; depth < maxDepth; depth++) { + double rate = stackSymbolDuplicateRate[stackSymbolDuplicateRate.length - 1]; + if (stackSymbolDuplicateRate.length > depth) { + rate = stackSymbolDuplicateRate[depth]; + } + int uniqStackCount = (int) (100 / rate); + stackDepthSymbolCount.put(depth, uniqStackCount); + } + this.existingSymbolMap = new HashMap<>(); + } + + public String generate(int depth) { + List<String> symbols = existingSymbolMap.get(depth); + if (symbols == null) { + existingSymbolMap.put(depth, symbols = new ArrayList<>()); + } + final Integer needCount = this.stackDepthSymbolCount.get(depth); + if (symbols.size() < needCount) { + final StringBuilder sb = new StringBuilder(SYMBOL_LENGTH); + for (int j = 0; j < SYMBOL_LENGTH; j++) { + sb.append(SYMBOL_TABLE[RANDOM.nextInt(SYMBOL_TABLE.length)]); + } + final String s = sb.toString(); + symbols.add(s); + return s; + } else { + return symbols.get(RANDOM.nextInt(symbols.size())); + } + } + } + + private static EBPFProfilingStack generateStack(int stackMinDepth, int stackMaxDepth, + StackSymbolGenerator stackSymbolGenerator) { + int stackDepth = stackMinDepth + RANDOM.nextInt(stackMaxDepth - stackMinDepth); + final List<EBPFProfilingStack.Symbol> symbols = new ArrayList<>(stackDepth); + for (int i = 0; i < stackDepth; i++) { + final EBPFProfilingStack.Symbol symbol = new EBPFProfilingStack.Symbol( + stackSymbolGenerator.generate(i), buildStackType(i, stackDepth)); + symbols.add(symbol); + } + final EBPFProfilingStack stack = new EBPFProfilingStack(); + stack.setDumpCount(RANDOM.nextInt(100)); + stack.setSymbols(symbols); + return stack; + } + + private static EBPFProfilingStackType buildStackType(int currentDepth, int totalDepth) { + final int partition = totalDepth / STACK_TYPES.length; + for (int i = 1; i <= STACK_TYPES.length; i++) { + if (currentDepth < i * partition) { + return STACK_TYPES[i - 1]; + } + } + return STACK_TYPES[STACK_TYPES.length - 1]; + } + + public static class DataSource { + private final List<EBPFProfilingStack> stackStream; + + public DataSource(List<EBPFProfilingStack> stackStream) { + this.stackStream = stackStream; + } + + public void analyze() { + new EBPFProfilingAnalyzer(null, 100, 5).generateTrees(new EBPFProfilingAnalyzation(), stackStream.parallelStream()); + } + } + + private static int calculateStackCount(int stackReportPeriodSecond, int totalTimeMinute, int combineInstanceCount) { + return (int) (TimeUnit.MINUTES.toSeconds(totalTimeMinute) / stackReportPeriodSecond * combineInstanceCount); + } + + @State(Scope.Benchmark) + public static class LowDataSource extends DataSource { + public LowDataSource() { + super(generateStacks(calculateStackCount(5, 60, 10), 15, 30, + new double[]{100, 50, 45, 40, 35, 30, 15, 10, 5}, 5)); + } + } + + @State(Scope.Benchmark) + public static class MedianDatasource extends DataSource { + public MedianDatasource() { + super(generateStacks(calculateStackCount(5, 100, 200), 15, 30, + new double[]{50, 40, 35, 30, 20, 10, 7, 5, 2}, 3)); + } + } + + @State(Scope.Benchmark) + public static class HighDatasource extends DataSource { + public HighDatasource() { + super(generateStacks(calculateStackCount(5, 2 * 60, 2000), 15, 40, + new double[]{30, 27, 25, 20, 17, 15, 10, 7, 5, 2, 1}, 1)); + } + } + + @Benchmark + public void analyzeLowDataSource(LowDataSource lowDataSource) { + lowDataSource.analyze(); + } + + @Benchmark + public void analyzeMedianDataSource(MedianDatasource medianDatasource) { + medianDatasource.analyze(); + } + + @Benchmark + public void analyzeMaxDataSource(HighDatasource highDataSource) { + highDataSource.analyze(); + } + + @Test + public void run() throws Exception { + new Runner(new OptionsBuilder() + .include(".*" + getClass().getSimpleName() + ".*") + .jvmArgsAppend("-Xmx512m", "-Xms512m") + .build()).run(); + } + +} diff --git a/oap-server/server-library/library-util/pom.xml b/oap-server/server-library/library-util/pom.xml index 56481e27b3..82f81740a8 100644 --- a/oap-server/server-library/library-util/pom.xml +++ b/oap-server/server-library/library-util/pom.xml @@ -61,5 +61,10 @@ <artifactId>system-stubs-jupiter</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.openjdk.jmh</groupId> + <artifactId>jmh-generator-annprocess</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/StringFormatGroupBenchmark.java b/oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/StringFormatGroupBenchmark.java new file mode 100644 index 0000000000..ab7005b417 --- /dev/null +++ b/oap-server/server-library/library-util/src/test/java/org/apache/skywalking/oap/server/library/util/StringFormatGroupBenchmark.java @@ -0,0 +1,74 @@ +/* + * 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.oap.server.library.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +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.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@Fork(2) +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class StringFormatGroupBenchmark { + @Benchmark + @Test + public void testMatch() { + StringFormatGroup group = new StringFormatGroup(); + group.addRule("/name/*/add", "/name/.+/add"); + Assertions.assertEquals("/name/*/add", group.format("/name/test/add").getName()); + + group = new StringFormatGroup(); + group.addRule("/name/*/add/{orderId}", "/name/.+/add/.*"); + Assertions.assertEquals("/name/*/add/{orderId}", group.format("/name/test/add/12323").getName()); + } + + @Benchmark + @Test + public void test100Rule() { + StringFormatGroup group = new StringFormatGroup(); + group.addRule("/name/*/add/{orderId}", "/name/.+/add/.*"); + for (int i = 0; i < 100; i++) { + group.addRule("/name/*/add/{orderId}" + "/" + 1, "/name/.+/add/.*" + "/abc"); + } + Assertions.assertEquals("/name/*/add/{orderId}", group.format("/name/test/add/12323").getName()); + } + + @Test + public void run() throws Exception { + new Runner(new OptionsBuilder() + .include(".*" + getClass().getSimpleName() + ".*") + .jvmArgsAppend("-Xmx512m", "-Xms512m") + .build()).run(); + } +} diff --git a/pom.xml b/pom.xml index c517f685d2..fa5f258ccb 100755 --- a/pom.xml +++ b/pom.xml @@ -194,7 +194,7 @@ <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version> <build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version> <maven-checkstyle-plugin.version>3.1.0</maven-checkstyle-plugin.version> - <jmh.version>1.21</jmh.version> + <jmh.version>1.37</jmh.version> <checkstyle.fails.on.error>true</checkstyle.fails.on.error> <assertj-core.version>3.20.2</assertj-core.version> <cyclonedx-maven-plugin.version>2.8.0</cyclonedx-maven-plugin.version>
