Use constant for baggage validation bitsets (#3274)

* Use constant for baggage validation bitsets

* Spot

* Move to element

* private
This commit is contained in:
Anuraag Agrawal 2021-06-04 09:26:00 +09:00 committed by GitHub
parent d044890a7c
commit d6849219a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 32 deletions

View File

@ -8,8 +8,11 @@ package io.opentelemetry.api.baggage.propagation;
import io.opentelemetry.context.Context; import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.context.propagation.TextMapGetter;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.BenchmarkMode;
@ -25,12 +28,14 @@ import org.openjdk.jmh.annotations.Warmup;
@State(Scope.Thread) @State(Scope.Thread)
public class W3CBaggagePropagatorBenchmark { public class W3CBaggagePropagatorBenchmark {
// pre-allocate the keys & values to remove one possible confounding factor private static final Map<String, String> SMALL_BAGGAGE;
private static String header; private static final Map<String, String> LARGE_BAGGAGE;
static { static {
for (int i = 0; i < 100; i++) { List<String> baggages =
header += IntStream.range(0, 100)
.mapToObj(
i ->
"key" "key"
+ i + i
+ " = value" + " = value"
@ -41,8 +46,10 @@ public class W3CBaggagePropagatorBenchmark {
+ i + i
+ ",broken)key" + ",broken)key"
+ i + i
+ "=value,"; + "=value")
} .collect(Collectors.toList());
SMALL_BAGGAGE = Collections.singletonMap("baggage", String.join(",", baggages.subList(0, 5)));
LARGE_BAGGAGE = Collections.singletonMap("baggage", String.join(",", baggages));
} }
private static final TextMapGetter<Map<String, String>> getter = private static final TextMapGetter<Map<String, String>> getter =
@ -61,13 +68,23 @@ public class W3CBaggagePropagatorBenchmark {
@Benchmark @Benchmark
@BenchmarkMode({Mode.AverageTime}) @BenchmarkMode({Mode.AverageTime})
@Fork(1) @Fork(3)
@Measurement(iterations = 15, time = 1) @Measurement(iterations = 15, time = 1)
@OutputTimeUnit(TimeUnit.NANOSECONDS) @OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 5, time = 1) @Warmup(iterations = 5, time = 1)
public Context defaultPropagatorExtractBenchmark() { public Context smallBaggage() {
W3CBaggagePropagator propagator = W3CBaggagePropagator.getInstance(); W3CBaggagePropagator propagator = W3CBaggagePropagator.getInstance();
return propagator.extract(Context.root(), SMALL_BAGGAGE, getter);
}
return propagator.extract(Context.root(), Collections.singletonMap("baggage", header), getter); @Benchmark
@BenchmarkMode({Mode.AverageTime})
@Fork(3)
@Measurement(iterations = 15, time = 1)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 5, time = 1)
public Context largeBaggage() {
W3CBaggagePropagator propagator = W3CBaggagePropagator.getInstance();
return propagator.extract(Context.root(), LARGE_BAGGAGE, getter);
} }
} }

View File

@ -14,7 +14,22 @@ import java.util.BitSet;
*/ */
class Element { class Element {
private final BitSet excluded = new BitSet(128); private static final BitSet EXCLUDED_KEY_CHARS = new BitSet(128);
private static final BitSet EXCLUDED_VALUE_CHARS = new BitSet(128);
static {
for (char c :
new char[] {
'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}'
}) {
EXCLUDED_KEY_CHARS.set(c);
}
for (char c : new char[] {'"', ',', ';', '\\'}) {
EXCLUDED_VALUE_CHARS.set(c);
}
}
private final BitSet excluded;
private boolean leadingSpace; private boolean leadingSpace;
private boolean readingValue; private boolean readingValue;
@ -23,15 +38,21 @@ class Element {
private int end; private int end;
private String value; private String value;
static Element createKeyElement() {
return new Element(EXCLUDED_KEY_CHARS);
}
static Element createValueElement() {
return new Element(EXCLUDED_VALUE_CHARS);
}
/** /**
* Constructs element instance. * Constructs element instance.
* *
* @param excludedChars characters that are not allowed for this type of an element * @param excluded characters that are not allowed for this type of an element
*/ */
Element(char[] excludedChars) { private Element(BitSet excluded) {
for (char excludedChar : excludedChars) { this.excluded = excluded;
excluded.set(excludedChar);
}
reset(0); reset(0);
} }

View File

@ -26,12 +26,8 @@ class Parser {
private final String baggageHeader; private final String baggageHeader;
private final Element key = private final Element key = Element.createKeyElement();
new Element( private final Element value = Element.createValueElement();
new char[] {
'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}'
});
private final Element value = new Element(new char[] {'"', ',', ';', '\\'});
private String meta; private String meta;
private State state; private State state;