diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2021-12-15 15:22:55 +0100 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2021-12-15 15:22:55 +0100 |
commit | 1bebedf2382811a25836bdd7123d024b9bbbb34f (patch) | |
tree | 13ef68d9c4dae09fbd61edcf70ce0c8f9ef67f29 | |
parent | f9fcfd21fc0521341e2ec6906ffbbc74eabb3c03 (diff) |
Zero out the builders as soon as they are used to avoid keeping both alive when building a large array.
4 files changed, 32 insertions, 27 deletions
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java index 3de4de08424..de8d2c62880 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java @@ -13,6 +13,7 @@ import com.yahoo.component.Vtag; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -22,6 +23,7 @@ import java.util.logging.Logger; import java.util.stream.Collectors; import static ai.vespa.metricsproxy.metric.ExternalMetrics.extractConfigserverDimensions; +import static ai.vespa.metricsproxy.metric.model.processing.MetricsProcessor.applyProcessors; import static java.util.logging.Level.FINE; import static java.util.stream.Collectors.toList; @@ -79,9 +81,18 @@ public class MetricsManager { * @return metrics for all matching services */ public List<MetricsPacket> getMetrics(List<VespaService> services, Instant startTime) { - return getMetricsAsBuilders(services, startTime).stream() - .map(MetricsPacket.Builder::build) - .collect(Collectors.toList()); + MetricsPacket.Builder [] builderArray = getMetricsBuildersAsArray(services, startTime); + List<MetricsPacket> metricsPackets = new ArrayList<>(builderArray.length); + for (int i = 0; i < builderArray.length; i++) { + metricsPackets.add(builderArray[i].build()); + builderArray[i] = null; // Set null to be able to GC the builder when packet has been created + } + return metricsPackets; + } + + public MetricsPacket.Builder [] getMetricsBuildersAsArray(List<VespaService> services, Instant startTime) { + List<MetricsPacket.Builder> builders = getMetricsAsBuilders(services, startTime); + return builders.toArray(new MetricsPacket.Builder[builders.size()]); } /** diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java index 8d5c1655df0..8f7f1c8a779 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/ValuesFetcher.java @@ -47,13 +47,14 @@ public class ValuesFetcher { .collect(Collectors.toList()); } - public List<MetricsPacket.Builder> fetchMetricsAsBuilders(String requestedConsumer) throws JsonRenderingException { + public MetricsPacket.Builder [] fetchMetricsAsBuilders(String requestedConsumer) throws JsonRenderingException { ConsumerId consumer = getConsumerOrDefault(requestedConsumer, metricsConsumers); - return metricsManager.getMetricsAsBuilders(vespaServices.getVespaServices(), Instant.now()) + List<MetricsPacket.Builder> builders = metricsManager.getMetricsAsBuilders(vespaServices.getVespaServices(), Instant.now()) .stream() .filter(builder -> builder.hasConsumer(consumer)) .collect(Collectors.toList()); + return builders.toArray(new MetricsPacket.Builder[builders.size()]); } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/metrics/MetricsV2Handler.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/metrics/MetricsV2Handler.java index eef5d9aaf98..f58c63cd76c 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/metrics/MetricsV2Handler.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/http/metrics/MetricsV2Handler.java @@ -19,6 +19,7 @@ import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.restapi.Path; import java.net.URI; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -66,8 +67,7 @@ public class MetricsV2Handler extends HttpHandlerBase { private JsonResponse valuesResponse(String consumer) { try { - List<MetricsPacket.Builder> builders = valuesFetcher.fetchMetricsAsBuilders(consumer); - List<MetricsPacket> metrics = processAndBuild(builders, + List<MetricsPacket> metrics = processAndBuild(valuesFetcher.fetchMetricsAsBuilders(consumer), new ServiceIdDimensionProcessor(), new ClusterIdDimensionProcessor(), new PublicDimensionsProcessor(MAX_DIMENSIONS)); @@ -81,12 +81,15 @@ public class MetricsV2Handler extends HttpHandlerBase { } } - private static List<MetricsPacket> processAndBuild(List<MetricsPacket.Builder> builders, + private static List<MetricsPacket> processAndBuild(MetricsPacket.Builder [] builders, MetricsProcessor... processors) { - return builders.stream() - .map(builder -> applyProcessors(builder, processors)) - .map(MetricsPacket.Builder::build) - .collect(toList()); + List<MetricsPacket> metricsPackets = new ArrayList<>(builders.length); + for (int i = 0; i < builders.length; i++) { + applyProcessors(builders[i], processors); + metricsPackets.add(builders[i].build()); + builders[i] = null; // Set null to be able to GC the builder when packet has been created + } + return metricsPackets; } } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java index 02ccd2c988c..fff2302f98b 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java @@ -4,7 +4,6 @@ package ai.vespa.metricsproxy.metric.model; import ai.vespa.metricsproxy.metric.Metric; import java.time.Instant; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; @@ -15,7 +14,6 @@ import java.util.Objects; import java.util.Set; import java.util.function.Function; -import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableMap; import static java.util.stream.Collectors.joining; @@ -44,22 +42,14 @@ public class MetricsPacket { this.statusMessage = statusMessage; this.timestamp = timestamp; this.service = service; - this.metrics = metrics; - this.dimensions = dimensions; + this.metrics = Map.copyOf(metrics); + this.dimensions = unmodifiableMap(dimensions); this.consumers = Set.copyOf(consumers); } - public Map<MetricId, Number> metrics() { - return unmodifiableMap(metrics); - } - - public Map<DimensionId, String> dimensions() { - return unmodifiableMap(dimensions); - } - - public Set<ConsumerId> consumers() { - return consumers; - } + public Map<MetricId, Number> metrics() { return metrics; } + public Map<DimensionId, String> dimensions() { return dimensions; } + public Set<ConsumerId> consumers() { return consumers;} @Override public String toString() { |