Skip to content

Commit 5d7e06e

Browse files
shakuzenphilwebb
authored andcommitted
Avoid Stream API in performance critical tracing code
Update composite tracing support to remove Stream API calls from injection and extraction methods which happen on each request. See gh-46838
1 parent 3534d13 commit 5d7e06e

File tree

2 files changed

+47
-22
lines changed

2 files changed

+47
-22
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositePropagationFactory.java

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Collection;
2020
import java.util.Collections;
2121
import java.util.List;
22-
import java.util.function.Predicate;
2322
import java.util.stream.Stream;
2423

2524
import brave.propagation.B3Propagation;
@@ -76,11 +75,19 @@ public Propagation<String> get() {
7675

7776
@Override
7877
public TraceContext decorate(TraceContext context) {
79-
return Stream.concat(this.injectors.stream(), this.extractors.stream())
80-
.map((factory) -> factory.decorate(context))
81-
.filter((decorated) -> decorated != context)
82-
.findFirst()
83-
.orElse(context);
78+
for (Propagation.Factory factory : this.injectors.factories) {
79+
TraceContext decorated = factory.decorate(context);
80+
if (decorated != context) {
81+
return decorated;
82+
}
83+
}
84+
for (Propagation.Factory factory : this.extractors.factories) {
85+
TraceContext decorated = factory.decorate(context);
86+
if (decorated != context) {
87+
return decorated;
88+
}
89+
}
90+
return context;
8491
}
8592

8693
/**
@@ -179,11 +186,21 @@ private static class PropagationFactories {
179186
}
180187

181188
boolean requires128BitTraceId() {
182-
return stream().anyMatch(Propagation.Factory::requires128BitTraceId);
189+
for (Propagation.Factory factory : this.factories) {
190+
if (factory.requires128BitTraceId()) {
191+
return true;
192+
}
193+
}
194+
return false;
183195
}
184196

185197
boolean supportsJoin() {
186-
return stream().allMatch(Propagation.Factory::supportsJoin);
198+
for (Propagation.Factory factory : this.factories) {
199+
if (!factory.supportsJoin()) {
200+
return false;
201+
}
202+
}
203+
return true;
187204
}
188205

189206
List<Propagation<String>> get() {
@@ -224,19 +241,24 @@ public List<String> keys() {
224241

225242
@Override
226243
public <R> TraceContext.Injector<R> injector(Setter<R, String> setter) {
227-
return (traceContext, request) -> this.injectors.stream()
228-
.map((propagation) -> propagation.injector(setter))
229-
.forEach((injector) -> injector.inject(traceContext, request));
244+
return (traceContext, request) -> {
245+
for (Propagation<String> propagation : this.injectors) {
246+
propagation.injector(setter).inject(traceContext, request);
247+
}
248+
};
230249
}
231250

232251
@Override
233252
public <R> TraceContext.Extractor<R> extractor(Getter<R, String> getter) {
234-
return (request) -> this.extractors.stream()
235-
.map((propagation) -> propagation.extractor(getter))
236-
.map((extractor) -> extractor.extract(request))
237-
.filter(Predicate.not(TraceContextOrSamplingFlags.EMPTY::equals))
238-
.findFirst()
239-
.orElse(TraceContextOrSamplingFlags.EMPTY);
253+
return (request) -> {
254+
for (Propagation<String> propagation : this.extractors) {
255+
TraceContextOrSamplingFlags extracted = propagation.extractor(getter).extract(request);
256+
if (!TraceContextOrSamplingFlags.EMPTY.equals(extracted)) {
257+
return extracted;
258+
}
259+
}
260+
return TraceContextOrSamplingFlags.EMPTY;
261+
};
240262
}
241263

242264
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/CompositeTextMapPropagator.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,14 @@ public <C> Context extract(Context context, C carrier, TextMapGetter<C> getter)
106106
if (getter == null) {
107107
return context;
108108
}
109-
Context result = this.extractors.stream()
110-
.map((extractor) -> extractor.extract(context, carrier, getter))
111-
.filter((extracted) -> extracted != context)
112-
.findFirst()
113-
.orElse(context);
109+
Context result = context;
110+
for (TextMapPropagator extractor : this.extractors) {
111+
Context extracted = extractor.extract(context, carrier, getter);
112+
if (extracted != context) {
113+
result = extracted;
114+
break;
115+
}
116+
}
114117
if (this.baggagePropagator != null) {
115118
result = this.baggagePropagator.extract(result, carrier, getter);
116119
}

0 commit comments

Comments
 (0)