From 985e7c38cd848c5f4f3adcdc454bbe62ba817323 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Thu, 24 Sep 2020 10:32:46 +0200 Subject: Add node object cache --- .../provision/persistence/NodeSerializer.java | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'node-repository') diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java index 0ce81e49bda..0882bf7ad3a 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java @@ -1,7 +1,11 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.persistence; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableSet; +import com.google.common.hash.Hashing; +import com.google.common.util.concurrent.UncheckedExecutionException; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; @@ -32,11 +36,13 @@ import com.yahoo.vespa.hosted.provision.node.Reports; import com.yahoo.vespa.hosted.provision.node.Status; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.function.UnaryOperator; /** @@ -107,6 +113,12 @@ public class NodeSerializer { // Network port fields private static final String networkPortsKey = "networkPorts"; + // A cache of deserialized Node objects. The cache is keyed on the hash of serialized node data. + // + // Deserializing a Node from slime is expensive, and happens frequently. Node instances that have already been + // deserialized are returned from this cache instead of being deserialized again. + private final Cache cache = CacheBuilder.newBuilder().maximumSize(1000).build(); + // ---------------- Serialization ---------------------------------------------------- public NodeSerializer(NodeFlavors flavors) { @@ -196,7 +208,15 @@ public class NodeSerializer { // ---------------- Deserialization -------------------------------------------------- public Node fromJson(Node.State state, byte[] data) { - return nodeFromSlime(state, SlimeUtils.jsonToSlime(data).get()); + var key = Hashing.sipHash24().newHasher() + .putString(state.name(), StandardCharsets.UTF_8) + .putBytes(data).hash() + .asLong(); + try { + return cache.get(key, () -> nodeFromSlime(state, SlimeUtils.jsonToSlime(data).get())); + } catch (ExecutionException e) { + throw new UncheckedExecutionException(e); + } } private Node nodeFromSlime(Node.State state, Inspector object) { -- cgit v1.2.3