Skip to content

Commit

Permalink
Avoid allocating lambda in PercentileTimer.computeIfAbsent (#1128)
Browse files Browse the repository at this point in the history
PercentileTimer.computeIfAbsent would delegate to Utils.computeIfAbsent, which actually
eagerly calls get and then putIfAbsent if the timer is not in the underlying map. Just directly
do that to avoid needing to allocate a lambda in the case the timer is present. The same
change has been applied to PercentileDistributionSummary.

---------

Co-authored-by: Brian Harrington <brharrington@gmail.com>
  • Loading branch information
kilink and brharrington committed Mar 22, 2024
1 parent 77566c5 commit 921da23
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ subprojects {
profilers = ['stack', 'gc']
includeTests = false
duplicateClassesStrategy = DuplicatesStrategy.WARN
includes = ['.*Caching.*']
includes = ['.*PercentileTimers.*']
}

checkstyle {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 Netflix, Inc.
* Copyright 2014-2024 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,7 +22,6 @@
import com.netflix.spectator.api.Measurement;
import com.netflix.spectator.api.Registry;
import com.netflix.spectator.api.Statistic;
import com.netflix.spectator.api.Utils;
import com.netflix.spectator.api.patterns.IdBuilder;
import com.netflix.spectator.api.patterns.TagsBuilder;

Expand Down Expand Up @@ -66,8 +65,20 @@ public final class PercentileDistributionSummary implements DistributionSummary
*/
private static PercentileDistributionSummary computeIfAbsent(
Registry registry, Id id, long min, long max) {
Object summary = Utils.computeIfAbsent(
registry.state(), id, i -> new PercentileDistributionSummary(registry, id, min, max));
// Inlined:
// Object summary = Utils.computeIfAbsent(
// registry.state(), id, i -> new PercentileDistributionSummary(registry, id, min, max));
//
// The lambda needs to capture the parameters for registry, min, and max which can lead to
// a high allocation rate for the lambda instance.
Object summary = registry.state().get(id);
if (summary == null) {
PercentileDistributionSummary newSummary = new PercentileDistributionSummary(registry, id, min, max);
summary = registry.state().putIfAbsent(id, newSummary);
if (summary == null) {
return newSummary;
}
}
return (summary instanceof PercentileDistributionSummary)
? ((PercentileDistributionSummary) summary).withRange(min, max)
: new PercentileDistributionSummary(registry, id, min, max);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2023 Netflix, Inc.
* Copyright 2014-2024 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,7 +23,6 @@
import com.netflix.spectator.api.Registry;
import com.netflix.spectator.api.Statistic;
import com.netflix.spectator.api.Timer;
import com.netflix.spectator.api.Utils;
import com.netflix.spectator.api.patterns.IdBuilder;
import com.netflix.spectator.api.patterns.TagsBuilder;

Expand Down Expand Up @@ -72,8 +71,20 @@ public final class PercentileTimer implements Timer {
* site.
*/
private static PercentileTimer computeIfAbsent(Registry registry, Id id, long min, long max) {
Object timer = Utils.computeIfAbsent(
registry.state(), id, i -> new PercentileTimer(registry, id, min, max));
// Inlined:
// Object timer = Utils.computeIfAbsent(
// registry.state(), id, i -> new PercentileTimer(registry, id, min, max));
//
// The lambda needs to capture the parameters for registry, min, and max which can lead to
// a high allocation rate for the lambda instance.
Object timer = registry.state().get(id);
if (timer == null) {
PercentileTimer newTimer = new PercentileTimer(registry, id, min, max);
timer = registry.state().putIfAbsent(id, newTimer);
if (timer == null) {
return newTimer;
}
}
return (timer instanceof PercentileTimer)
? ((PercentileTimer) timer).withRange(min, max)
: new PercentileTimer(registry, id, min, max);
Expand Down

0 comments on commit 921da23

Please sign in to comment.