This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 8200cf2b51 Improve 4x performance of 
ContextManagerExtendService.createTraceContext() (#698)
8200cf2b51 is described below

commit 8200cf2b5194f31981249351b1e306e8b2303a45
Author: jiangyunpeng <[email protected]>
AuthorDate: Sat Jun 22 10:34:41 2024 +0800

    Improve 4x performance of ContextManagerExtendService.createTraceContext() 
(#698)
---
 CHANGES.md                                         |   1 +
 apm-sniffer/apm-agent-core/pom.xml                 |   5 +
 .../core/context/ContextManagerExtendService.java  |  14 +--
 .../agent/core/context/IgnoreSuffixBenchmark.java  | 117 +++++++++++++++++++++
 4 files changed, 131 insertions(+), 6 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index c7d88b0784..54f7900e25 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -19,6 +19,7 @@ Release Notes.
 * Support for tracing the callbacks of asynchronous methods in 
elasticsearch-6.x-plugin/elasticsearch-7.x-plugin.
 * Fixed the invalid issue in the isInterface method in PluginFinder.
 * Fix the opentracing toolkit SPI config
+* Improve 4x performance of ContextManagerExtendService.createTraceContext()
 
 All issues and pull requests are 
[here](https://github.com/apache/skywalking/milestone/213?closed=1)
 
diff --git a/apm-sniffer/apm-agent-core/pom.xml 
b/apm-sniffer/apm-agent-core/pom.xml
index 132e2dbfd0..2ea7df432e 100644
--- a/apm-sniffer/apm-agent-core/pom.xml
+++ b/apm-sniffer/apm-agent-core/pom.xml
@@ -138,6 +138,11 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.openjdk.jmh</groupId>
+            <artifactId>jmh-generator-annprocess</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <dependencyManagement>
         <dependencies>
diff --git 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java
 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java
index 1e408df81b..49faebdc0c 100644
--- 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java
+++ 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java
@@ -18,7 +18,10 @@
 
 package org.apache.skywalking.apm.agent.core.context;
 
-import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 import org.apache.skywalking.apm.agent.core.boot.BootService;
 import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
@@ -35,7 +38,7 @@ import org.apache.skywalking.apm.util.StringUtil;
 @DefaultImplementor
 public class ContextManagerExtendService implements BootService, 
GRPCChannelListener {
 
-    private volatile String[] ignoreSuffixArray = new String[0];
+    private volatile Set ignoreSuffixSet;
 
     private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT;
 
@@ -50,7 +53,7 @@ public class ContextManagerExtendService implements 
BootService, GRPCChannelList
 
     @Override
     public void boot() {
-        ignoreSuffixArray = Config.Agent.IGNORE_SUFFIX.split(",");
+        ignoreSuffixSet = 
Stream.of(Config.Agent.IGNORE_SUFFIX.split(",")).collect(Collectors.toSet());
         ignoreSuffixPatternsWatcher = new 
IgnoreSuffixPatternsWatcher("agent.ignore_suffix", this);
         spanLimitWatcher = new 
SpanLimitWatcher("agent.span_limit_per_segment");
 
@@ -82,8 +85,7 @@ public class ContextManagerExtendService implements 
BootService, GRPCChannelList
         }
 
         int suffixIdx = operationName.lastIndexOf(".");
-        if (suffixIdx > -1 && Arrays.stream(ignoreSuffixArray)
-                                    .anyMatch(a -> 
a.equals(operationName.substring(suffixIdx)))) {
+        if (suffixIdx > -1 && 
ignoreSuffixSet.contains(operationName.substring(suffixIdx))) {
             context = new IgnoredTracerContext();
         } else {
             SamplingService samplingService = 
ServiceManager.INSTANCE.findService(SamplingService.class);
@@ -104,7 +106,7 @@ public class ContextManagerExtendService implements 
BootService, GRPCChannelList
 
     public void handleIgnoreSuffixPatternsChanged() {
         if 
(StringUtil.isNotBlank(ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns())) {
-            ignoreSuffixArray = 
ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns().split(",");
+            ignoreSuffixSet = 
Stream.of(ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns().split(",")).collect(Collectors.toSet());
         }
     }
 }
diff --git 
a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java
 
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java
new file mode 100644
index 0000000000..623d674d06
--- /dev/null
+++ 
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+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.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+import org.openjdk.jmh.runner.options.TimeValue;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * ISSUE-12355
+ */
+@State(Scope.Benchmark)
+@BenchmarkMode({Mode.Throughput, Mode.SampleTime})
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+public class IgnoreSuffixBenchmark {
+    public static String IGNORE_SUFFIX = 
".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg";
+    private String[] ignoreSuffixArray;
+    private Set ignoreSuffixSet;
+
+    private String operationName = "test.api";
+
+    @Setup
+    public void setup() {
+        ignoreSuffixArray = IGNORE_SUFFIX.split(",");
+        ignoreSuffixSet = 
Stream.of(ignoreSuffixArray).collect(Collectors.toSet());
+    }
+
+    @Benchmark
+    public boolean testArray() {
+        int suffixIdx = operationName.lastIndexOf(".");
+        return Arrays.stream(ignoreSuffixArray)
+                .anyMatch(a -> a.equals(operationName.substring(suffixIdx)));
+    }
+
+    @Benchmark
+    public boolean testHashSet() {
+        int suffixIdx = operationName.lastIndexOf(".");
+        return ignoreSuffixSet.contains(operationName.substring(suffixIdx));
+    }
+
+    public static void main(String[] args) throws Exception {
+        Options opt = new OptionsBuilder()
+                .include(IgnoreSuffixBenchmark.class.getName())
+                .warmupIterations(3)
+                .warmupTime(TimeValue.seconds(10))
+                .measurementIterations(3)
+                .measurementTime(TimeValue.seconds(10))
+                .forks(1)
+                .build();
+        new Runner(opt).run();
+    }
+    /**
+     * # JMH version: 1.33
+     * # VM version: JDK 11.0.21, Java HotSpot(TM) 64-Bit Server VM, 
11.0.21+9-LTS-193
+     * # VM invoker: 
/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/java
+     * # VM options: -javaagent:/Applications/IntelliJ IDEA 
CE.app/Contents/lib/idea_rt.jar=60939:/Applications/IntelliJ IDEA 
CE.app/Contents/bin -Dfile.encoding=UTF-8
+     * # Blackhole mode: full + dont-inline hint (default, use 
-Djmh.blackhole.autoDetect=true to auto-detect)
+     * # Warmup: 3 iterations, 10 s each
+     * # Measurement: 3 iterations, 10 s each
+     * # Timeout: 10 min per iteration
+     * # Threads: 1 thread, will synchronize iterations
+     * # Benchmark mode: Sampling time
+     * # Benchmark: 
org.apache.skywalking.apm.agent.core.context.IgnoreSuffixBenchmark.testHashSet
+     *
+     * Benchmark                                                Mode     Cnt   
     Score    Error   Units
+     * IgnoreSuffixBenchmark.testArray                         thrpt       3   
     0.007 ±  0.003  ops/ns
+     * IgnoreSuffixBenchmark.testHashSet                       thrpt       3   
     0.084 ±  0.035  ops/ns
+     * IgnoreSuffixBenchmark.testArray                        sample  823984   
   183.234 ± 11.201   ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.00        sample           
    41.000            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.50        sample           
   166.000            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.90        sample           
   167.000            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.95        sample           
   209.000            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.99        sample           
   375.000            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.999       sample           
  1124.630            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p0.9999      sample           
 29971.248            ns/op
+     * IgnoreSuffixBenchmark.testArray:testArray·p1.00        sample          
1130496.000            ns/op
+     * IgnoreSuffixBenchmark.testHashSet                      sample  972621   
    27.117 ±  1.788   ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.00    sample           
       ≈ 0            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.50    sample           
    41.000            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.90    sample           
    42.000            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.95    sample           
    42.000            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.99    sample           
    83.000            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.999   sample           
   167.000            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.9999  sample           
  6827.950            ns/op
+     * IgnoreSuffixBenchmark.testHashSet:testHashSet·p1.00    sample           
478208.000            ns/op
+     */
+}

Reply via email to