From 4857969ca4055e292d2f1c956d61143bdf2141a0 Mon Sep 17 00:00:00 2001 From: Luck Date: Sun, 18 Dec 2016 09:57:39 +0000 Subject: [PATCH] Cache calls querying parent groups in bridge subjects - closes #69 --- .../common/core/model/PermissionHolder.java | 12 ++++ .../luckperms/sponge/model/SpongeGroup.java | 61 +++++++++++++------ 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java b/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java index a5bd1444..a6059ab9 100644 --- a/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java +++ b/common/src/main/java/me/lucko/luckperms/common/core/model/PermissionHolder.java @@ -116,6 +116,9 @@ public abstract class PermissionHolder { @Getter private final Lock ioLock = new ReentrantLock(); + @Getter + private final Set stateListeners = ConcurrentHashMap.newKeySet(); + /* * CACHES - cache the result of a number of methods in this class, until they are invalidated. @@ -178,6 +181,15 @@ public abstract class PermissionHolder { getAllNodesFilteredCache.invalidateAll(); exportNodesCache.invalidateAll(); + // Invalidate listeners + for (Runnable r : stateListeners) { + try { + r.run(); + } catch (Exception e) { + e.printStackTrace(); + } + } + // Get previous references Set refs = plugin.getCachedStateManager().getInheritances(toReference()); diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java index 2e56fc2a..28d84795 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/model/SpongeGroup.java @@ -24,6 +24,9 @@ package me.lucko.luckperms.sponge.model; import lombok.Getter; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import me.lucko.luckperms.api.LocalizedNode; @@ -73,11 +76,48 @@ public class SpongeGroup extends Group { @Getter private final LuckPermsSubjectData transientSubjectData; + private final LoadingCache permissionCache = CacheBuilder.newBuilder() + .build(new CacheLoader() { + @Override + public NodeTree load(ContextSet contexts) { + // TODO move this away from NodeTree + Map permissions = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() + .map(LocalizedNode::getNode) + .collect(Collectors.toMap(Node::getPermission, Node::getValue)); + + return NodeTree.of(permissions); + } + }); + + private final LoadingCache> parentCache = CacheBuilder.newBuilder() + .build(new CacheLoader>() { + @Override + public Set load(ContextSet contexts) { + Set subjects = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() + .map(LocalizedNode::getNode) + .filter(Node::isGroupNode) + .map(Node::getGroupName) + .map(s -> plugin.getService().getGroupSubjects().get(s)) + .map(LPSubject::toReference) + .collect(Collectors.toSet()); + + subjects.addAll(plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getParents(contexts)); + subjects.addAll(plugin.getService().getDefaults().getParents(contexts)); + + return ImmutableSet.copyOf(subjects); + } + }); + private GroupSubject(LPSpongePlugin plugin, SpongeGroup parent) { this.parent = parent; this.plugin = plugin; this.subjectData = new LuckPermsSubjectData(true, plugin.getService(), parent, this); this.transientSubjectData = new LuckPermsSubjectData(false, plugin.getService(), parent, this); + + parent.getStateListeners().add(() -> { + permissionCache.invalidateAll(); + parentCache.invalidateAll(); + }); } @Override @@ -108,12 +148,8 @@ public class SpongeGroup extends Group { @Override public Tristate getPermissionValue(ContextSet contexts, String permission) { try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PERMISSION_VALUE)) { - // TODO move this away from NodeTree - Map permissions = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() - .map(LocalizedNode::getNode) - .collect(Collectors.toMap(Node::getPermission, Node::getValue)); - - Tristate t = Util.convertTristate(NodeTree.of(permissions).get(permission)); + NodeTree nt = permissionCache.getUnchecked(contexts); + Tristate t = Util.convertTristate(nt.get(permission)); if (t != Tristate.UNDEFINED) { return t; } @@ -138,18 +174,7 @@ public class SpongeGroup extends Group { @Override public Set getParents(ContextSet contexts) { try (Timing ignored = plugin.getTimings().time(LPTiming.GROUP_GET_PARENTS)) { - Set subjects = parent.getAllNodesFiltered(ExtractedContexts.generate(plugin.getService().calculateContexts(contexts))).stream() - .map(LocalizedNode::getNode) - .filter(Node::isGroupNode) - .map(Node::getGroupName) - .map(s -> plugin.getService().getGroupSubjects().get(s)) - .map(LPSubject::toReference) - .collect(Collectors.toSet()); - - subjects.addAll(plugin.getService().getGroupSubjects().getDefaultSubject().resolve(getService()).getParents(contexts)); - subjects.addAll(plugin.getService().getDefaults().getParents(contexts)); - - return ImmutableSet.copyOf(subjects); + return parentCache.getUnchecked(contexts); } }