Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize some iterations in BodyExtractor and BodyInserter #30136

Merged
merged 2 commits into from
Mar 22, 2023

Conversation

yuzawa-san
Copy link
Contributor

Using iterators for trivial findFirst and toList cases uses less CPU and memory (in these cases, not while costing readability)
Here is an icicle graph example of the CPU usage before
image
and here it is after:
image
There was about a 10-15% overhead with the streams usage, which we can save on by doing this.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 18, 2023
@sbrannen sbrannen added in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement labels Mar 19, 2023
@simonbasle simonbasle self-assigned this Mar 21, 2023
Copy link
Contributor

@simonbasle simonbasle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indeed these kind of stream usage can get an order of magnitude slower especially for small collections... this looks good to me overall, thanks for the PR @yuzawa-san 👍
one minor comment to address from a readability standpoint and I think we can merge this in time for 6.0.8

.orElseGet(() -> Mono.error(unsupportedError(bodyType, context, mediaType)));
for (HttpMessageWriter<?> messageWriter : context.messageWriters()) {
if (messageWriter.canWrite(bodyType, mediaType)) {
return write(publisher, bodyType, mediaType, outputMessage, context, cast(messageWriter));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compared to the BodyExtractor case, I find that cast call is a little too buried among all these parameters, making it less visible. would you mind extracting it to an intermediate local variable? this should be efficiently optimized away by the JIT compiler, so that is purely from a readability perspective.

@simonbasle simonbasle removed the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 21, 2023
@simonbasle simonbasle added this to the 6.0.8 milestone Mar 21, 2023
use an intermediate variable for readability
@yuzawa-san
Copy link
Contributor Author

@simonbasle updated with intermediate variable.

#29972 also gets around another (I would say more expensive) streams usage in ReadOnlyHttpHeaders.

@Override
public Set<Entry<String, List<String>>> entrySet() {
return this.headers.entrySet().stream().map(SimpleImmutableEntry::new)
.collect(Collectors.collectingAndThen(
Collectors.toCollection(LinkedHashSet::new), // Retain original ordering of entries
Collections::unmodifiableSet));
}

I left this one there because that PR avoids that entrySet and also I have been working on a branch where I got ReadOnlyHttpHeaders to use CollectionUtils.unmodifiableMultiValueMap internally.

Copy link
Contributor

@simonbasle simonbasle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the change @yuzawa-san 👍

@simonbasle simonbasle changed the title Use iterators in BodyExtractor and BodyInserter Optimize some iterations in BodyExtractor and BodyInserter Mar 22, 2023
@simonbasle simonbasle merged commit 800b134 into spring-projects:main Mar 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants