Avoid java.util.stream.Stream usage in hot paths

Prior to this commit, profiling sessions would show that using
`java.util.stream.Stream` in some hot code paths creates significant
garbage.

Where streams aren't really required, this commit turns those snippets
into imperative logic  because those are likely to be called once or
multiple times per request.

Closes gh-22341
This commit is contained in:
Brian Clozel
2019-02-05 12:14:51 +01:00
parent 4ec2f3cd17
commit 862fa557bd
4 changed files with 39 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -141,15 +141,17 @@ public class ReactiveAdapterRegistry {
if (clazz == null) {
return null;
}
return this.adapters.stream()
.filter(adapter -> adapter.getReactiveType() == clazz)
.findFirst()
.orElseGet(() ->
this.adapters.stream()
.filter(adapter -> adapter.getReactiveType().isAssignableFrom(clazz))
.findFirst()
.orElse(null));
for(ReactiveAdapter adapter : this.adapters) {
if (adapter.getReactiveType() == clazz) {
return adapter;
}
}
for(ReactiveAdapter adapter : this.adapters) {
if (adapter.getReactiveType().isAssignableFrom(clazz)) {
return adapter;
}
}
return null;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,7 +74,12 @@ public abstract class AbstractEncoder<T> implements Encoder<T> {
if (mimeType == null) {
return true;
}
return this.encodableMimeTypes.stream().anyMatch(candidate -> candidate.isCompatibleWith(mimeType));
for(MimeType candidate : this.encodableMimeTypes) {
if (candidate.isCompatibleWith(mimeType)) {
return true;
}
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -63,7 +63,12 @@ final class CompositeLog implements Log {
}
private static Log initLogger(List<Log> loggers, Predicate<Log> predicate) {
return loggers.stream().filter(predicate).findFirst().orElse(NO_OP_LOG);
for (Log logger : loggers) {
if (predicate.test(logger)) {
return logger;
}
}
return NO_OP_LOG;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
package org.springframework.web.reactive.result.method.annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
@@ -137,7 +137,8 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
MediaType bestMediaType = selectMediaType(exchange, () -> getMediaTypesFor(elementType));
List<MediaType> writableMediaTypes = getMediaTypesFor(elementType);
MediaType bestMediaType = selectMediaType(exchange, () -> writableMediaTypes);
if (bestMediaType != null) {
String logPrefix = exchange.getLogPrefix();
if (logger.isDebugEnabled()) {
@@ -152,12 +153,12 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa
}
}
else {
if (getMediaTypesFor(elementType).isEmpty()) {
if (writableMediaTypes.isEmpty()) {
return Mono.error(new IllegalStateException("No writer for : " + elementType));
}
}
return Mono.error(new NotAcceptableStatusException(getMediaTypesFor(elementType)));
return Mono.error(new NotAcceptableStatusException(writableMediaTypes));
}
private ResolvableType getElementType(ReactiveAdapter adapter, ResolvableType genericType) {
@@ -173,10 +174,13 @@ public abstract class AbstractMessageWriterResultHandler extends HandlerResultHa
}
private List<MediaType> getMediaTypesFor(ResolvableType elementType) {
return getMessageWriters().stream()
.filter(converter -> converter.canWrite(elementType, null))
.flatMap(converter -> converter.getWritableMediaTypes().stream())
.collect(Collectors.toList());
List<MediaType> writableMediaTypes = new ArrayList<>();
for (HttpMessageWriter<?> converter : getMessageWriters()) {
if (converter.canWrite(elementType, null)) {
writableMediaTypes.addAll(converter.getWritableMediaTypes());
}
}
return writableMediaTypes;
}
}