From 1bebedf2382811a25836bdd7123d024b9bbbb34f Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 15 Dec 2021 15:22:55 +0100 Subject: Zero out the builders as soon as they are used to avoid keeping both alive when building a large array. --- .../ai/vespa/metricsproxy/core/MetricsManager.java | 17 ++++++++++++++--- .../ai/vespa/metricsproxy/http/ValuesFetcher.java | 5 +++-- .../metricsproxy/http/metrics/MetricsV2Handler.java | 17 ++++++++++------- .../metricsproxy/metric/model/MetricsPacket.java | 20 +++++--------------- 4 files changed, 32 insertions(+), 27 deletions(-) (limited to 'metrics-proxy') 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 getMetrics(List services, Instant startTime) { - return getMetricsAsBuilders(services, startTime).stream() - .map(MetricsPacket.Builder::build) - .collect(Collectors.toList()); + MetricsPacket.Builder [] builderArray = getMetricsBuildersAsArray(services, startTime); + List 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 services, Instant startTime) { + List 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 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 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 builders = valuesFetcher.fetchMetricsAsBuilders(consumer); - List metrics = processAndBuild(builders, + List 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 processAndBuild(List builders, + private static List processAndBuild(MetricsPacket.Builder [] builders, MetricsProcessor... processors) { - return builders.stream() - .map(builder -> applyProcessors(builder, processors)) - .map(MetricsPacket.Builder::build) - .collect(toList()); + List 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 metrics() { - return unmodifiableMap(metrics); - } - - public Map dimensions() { - return unmodifiableMap(dimensions); - } - - public Set consumers() { - return consumers; - } + public Map metrics() { return metrics; } + public Map dimensions() { return dimensions; } + public Set consumers() { return consumers;} @Override public String toString() { -- cgit v1.2.3