Skip to content

Commit f118ab5

Browse files
committed
Improve 4x performance of ContextManagerExtendService.createTraceContext()
1 parent 3a96458 commit f118ab5

File tree

4 files changed

+126
-6
lines changed

4 files changed

+126
-6
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Release Notes.
1919
* Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin.
2020
* Fixed the invalid issue in the isInterface method in PluginFinder.
2121
* Fix the opentracing toolkit SPI config
22+
* Improve 4x performance of ContextManagerExtendService.createTraceContext()
2223

2324
All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1)
2425

apm-sniffer/apm-agent-core/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@
138138
<groupId>org.slf4j</groupId>
139139
<artifactId>slf4j-api</artifactId>
140140
</dependency>
141+
<dependency>
142+
<groupId>org.openjdk.jmh</groupId>
143+
<artifactId>jmh-generator-annprocess</artifactId>
144+
<scope>test</scope>
145+
</dependency>
141146
</dependencies>
142147
<dependencyManagement>
143148
<dependencies>

apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818

1919
package org.apache.skywalking.apm.agent.core.context;
2020

21-
import java.util.Arrays;
21+
import java.util.Set;
22+
import java.util.stream.Collectors;
23+
import java.util.stream.Stream;
24+
2225
import org.apache.skywalking.apm.agent.core.boot.BootService;
2326
import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
2427
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
@@ -35,7 +38,7 @@
3538
@DefaultImplementor
3639
public class ContextManagerExtendService implements BootService, GRPCChannelListener {
3740

38-
private volatile String[] ignoreSuffixArray = new String[0];
41+
private volatile Set ignoreSuffixSet;
3942

4043
private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT;
4144

@@ -50,7 +53,7 @@ public void prepare() {
5053

5154
@Override
5255
public void boot() {
53-
ignoreSuffixArray = Config.Agent.IGNORE_SUFFIX.split(",");
56+
ignoreSuffixSet = Stream.of(Config.Agent.IGNORE_SUFFIX.split(",")).collect(Collectors.toSet());
5457
ignoreSuffixPatternsWatcher = new IgnoreSuffixPatternsWatcher("agent.ignore_suffix", this);
5558
spanLimitWatcher = new SpanLimitWatcher("agent.span_limit_per_segment");
5659

@@ -82,8 +85,7 @@ public AbstractTracerContext createTraceContext(String operationName, boolean fo
8285
}
8386

8487
int suffixIdx = operationName.lastIndexOf(".");
85-
if (suffixIdx > -1 && Arrays.stream(ignoreSuffixArray)
86-
.anyMatch(a -> a.equals(operationName.substring(suffixIdx)))) {
88+
if (suffixIdx > -1 && ignoreSuffixSet.contains(operationName.substring(suffixIdx))) {
8789
context = new IgnoredTracerContext();
8890
} else {
8991
SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
@@ -104,7 +106,7 @@ public void statusChanged(final GRPCChannelStatus status) {
104106

105107
public void handleIgnoreSuffixPatternsChanged() {
106108
if (StringUtil.isNotBlank(ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns())) {
107-
ignoreSuffixArray = ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns().split(",");
109+
ignoreSuffixSet = Stream.of(ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns().split(",")).collect(Collectors.toSet());
108110
}
109111
}
110112
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.agent.core.context;
20+
21+
import org.openjdk.jmh.annotations.*;
22+
import org.openjdk.jmh.results.format.ResultFormatType;
23+
import org.openjdk.jmh.runner.Runner;
24+
import org.openjdk.jmh.runner.options.Options;
25+
import org.openjdk.jmh.runner.options.OptionsBuilder;
26+
import org.openjdk.jmh.runner.options.TimeValue;
27+
28+
import java.util.Arrays;
29+
import java.util.Set;
30+
import java.util.concurrent.TimeUnit;
31+
import java.util.stream.Collectors;
32+
import java.util.stream.Stream;
33+
34+
/**
35+
* ISSUE-12355
36+
*/
37+
@State(Scope.Benchmark)
38+
@BenchmarkMode({Mode.Throughput, Mode.SampleTime})
39+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
40+
public class IgnoreSuffixBenchmark {
41+
public static String IGNORE_SUFFIX = ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg";
42+
private String[] ignoreSuffixArray;
43+
private Set ignoreSuffixSet;
44+
45+
private String operationName = "test.api";
46+
47+
@Setup
48+
public void setup() {
49+
ignoreSuffixArray = IGNORE_SUFFIX.split(",");
50+
ignoreSuffixSet = Stream.of(ignoreSuffixArray).collect(Collectors.toSet());
51+
}
52+
53+
@Benchmark
54+
public boolean testArray() {
55+
int suffixIdx = operationName.lastIndexOf(".");
56+
return Arrays.stream(ignoreSuffixArray)
57+
.anyMatch(a -> a.equals(operationName.substring(suffixIdx)));
58+
}
59+
60+
@Benchmark
61+
public boolean testHashSet() {
62+
int suffixIdx = operationName.lastIndexOf(".");
63+
return ignoreSuffixSet.contains(operationName.substring(suffixIdx));
64+
}
65+
66+
public static void main(String[] args) throws Exception {
67+
Options opt = new OptionsBuilder()
68+
.include(IgnoreSuffixBenchmark.class.getName())
69+
.warmupIterations(3)
70+
.warmupTime(TimeValue.seconds(10))
71+
.measurementIterations(3)
72+
.measurementTime(TimeValue.seconds(10))
73+
.forks(1)
74+
.build();
75+
new Runner(opt).run();
76+
}
77+
/**
78+
* # JMH version: 1.33
79+
* # VM version: JDK 11.0.21, Java HotSpot(TM) 64-Bit Server VM, 11.0.21+9-LTS-193
80+
* # VM invoker: /Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/java
81+
* # 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
82+
* # Blackhole mode: full + dont-inline hint (default, use -Djmh.blackhole.autoDetect=true to auto-detect)
83+
* # Warmup: 3 iterations, 10 s each
84+
* # Measurement: 3 iterations, 10 s each
85+
* # Timeout: 10 min per iteration
86+
* # Threads: 1 thread, will synchronize iterations
87+
* # Benchmark mode: Sampling time
88+
* # Benchmark: org.apache.skywalking.apm.agent.core.context.IgnoreSuffixBenchmark.testHashSet
89+
*
90+
* Benchmark Mode Cnt Score Error Units
91+
* IgnoreSuffixBenchmark.testArray thrpt 3 0.007 ± 0.003 ops/ns
92+
* IgnoreSuffixBenchmark.testHashSet thrpt 3 0.084 ± 0.035 ops/ns
93+
* IgnoreSuffixBenchmark.testArray sample 823984 183.234 ± 11.201 ns/op
94+
* IgnoreSuffixBenchmark.testArray:testArray·p0.00 sample 41.000 ns/op
95+
* IgnoreSuffixBenchmark.testArray:testArray·p0.50 sample 166.000 ns/op
96+
* IgnoreSuffixBenchmark.testArray:testArray·p0.90 sample 167.000 ns/op
97+
* IgnoreSuffixBenchmark.testArray:testArray·p0.95 sample 209.000 ns/op
98+
* IgnoreSuffixBenchmark.testArray:testArray·p0.99 sample 375.000 ns/op
99+
* IgnoreSuffixBenchmark.testArray:testArray·p0.999 sample 1124.630 ns/op
100+
* IgnoreSuffixBenchmark.testArray:testArray·p0.9999 sample 29971.248 ns/op
101+
* IgnoreSuffixBenchmark.testArray:testArray·p1.00 sample 1130496.000 ns/op
102+
* IgnoreSuffixBenchmark.testHashSet sample 972621 27.117 ± 1.788 ns/op
103+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.00 sample ≈ 0 ns/op
104+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.50 sample 41.000 ns/op
105+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.90 sample 42.000 ns/op
106+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.95 sample 42.000 ns/op
107+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.99 sample 83.000 ns/op
108+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.999 sample 167.000 ns/op
109+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.9999 sample 6827.950 ns/op
110+
* IgnoreSuffixBenchmark.testHashSet:testHashSet·p1.00 sample 478208.000 ns/op
111+
*/
112+
}

0 commit comments

Comments
 (0)