mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Optimize LookupSetting storage/manipulation within Contexts
Fixes some performance issues resulting from bad use / implementation of ImmutableEnumSets
This commit is contained in:
parent
2da6298c53
commit
fe77834cef
@ -25,14 +25,11 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.api;
|
package me.lucko.luckperms.api;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.api.context.ContextSet;
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -57,9 +54,9 @@ public class Contexts {
|
|||||||
public static final String WORLD_KEY = "world";
|
public static final String WORLD_KEY = "world";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default {@link LookupSetting}s.
|
* The default {@link LookupSetting}s as a flag.
|
||||||
*/
|
*/
|
||||||
private static final EnumSet<LookupSetting> DEFAULT_SETTINGS = EnumSet.of(
|
private static final byte DEFAULT_SETTINGS_FLAG = LookupSetting.createFlag(
|
||||||
LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER,
|
LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER,
|
||||||
LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD,
|
LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD,
|
||||||
LookupSetting.RESOLVE_INHERITANCE,
|
LookupSetting.RESOLVE_INHERITANCE,
|
||||||
@ -73,7 +70,7 @@ public class Contexts {
|
|||||||
* <p>Formed of an empty {@link ContextSet} and all inclusion and
|
* <p>Formed of an empty {@link ContextSet} and all inclusion and
|
||||||
* inheritance {@link LookupSetting}s applied.</p>
|
* inheritance {@link LookupSetting}s applied.</p>
|
||||||
*/
|
*/
|
||||||
private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), ImmutableSet.copyOf(DEFAULT_SETTINGS));
|
private static final Contexts GLOBAL = new Contexts(ImmutableContextSet.empty(), DEFAULT_SETTINGS_FLAG);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link FullySatisfiedContexts} instance.
|
* Gets the {@link FullySatisfiedContexts} instance.
|
||||||
@ -111,7 +108,7 @@ public class Contexts {
|
|||||||
*/
|
*/
|
||||||
public static @NonNull Contexts of(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
public static @NonNull Contexts of(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
||||||
Objects.requireNonNull(contextSet, "contextSet");
|
Objects.requireNonNull(contextSet, "contextSet");
|
||||||
EnumSet<LookupSetting> settings = formSettings(
|
byte settingsFlag = LookupSetting.createFlag(
|
||||||
includeNodesSetWithoutServer,
|
includeNodesSetWithoutServer,
|
||||||
includeNodesSetWithoutWorld,
|
includeNodesSetWithoutWorld,
|
||||||
resolveInheritance,
|
resolveInheritance,
|
||||||
@ -119,18 +116,10 @@ public class Contexts {
|
|||||||
applyParentsWithoutWorld,
|
applyParentsWithoutWorld,
|
||||||
isOp
|
isOp
|
||||||
);
|
);
|
||||||
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settings)) {
|
if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) {
|
||||||
return GLOBAL;
|
return GLOBAL;
|
||||||
}
|
}
|
||||||
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settings));
|
return new Contexts(contextSet.makeImmutable(), settingsFlag);
|
||||||
}
|
|
||||||
|
|
||||||
private static EnumSet<LookupSetting> asEnumSet(Set<LookupSetting> settings) {
|
|
||||||
if (settings instanceof EnumSet<?>) {
|
|
||||||
return ((EnumSet<LookupSetting>) settings);
|
|
||||||
} else {
|
|
||||||
return EnumSet.copyOf(settings);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -144,12 +133,12 @@ public class Contexts {
|
|||||||
Objects.requireNonNull(contextSet, "contextSet");
|
Objects.requireNonNull(contextSet, "contextSet");
|
||||||
Objects.requireNonNull(settings, "settings");
|
Objects.requireNonNull(settings, "settings");
|
||||||
|
|
||||||
EnumSet<LookupSetting> settingsCopy = asEnumSet(settings);
|
byte settingsFlag = LookupSetting.createFlag(settings);
|
||||||
if (contextSet.isEmpty() && DEFAULT_SETTINGS.equals(settingsCopy)) {
|
if (contextSet.isEmpty() && DEFAULT_SETTINGS_FLAG == settingsFlag) {
|
||||||
return GLOBAL;
|
return GLOBAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Contexts(contextSet.makeImmutable(), ImmutableSet.copyOf(settingsCopy));
|
return new Contexts(contextSet.makeImmutable(), settingsFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,7 +149,7 @@ public class Contexts {
|
|||||||
/**
|
/**
|
||||||
* The settings for this lookup
|
* The settings for this lookup
|
||||||
*/
|
*/
|
||||||
private final ImmutableSet<LookupSetting> settings;
|
private final byte settingsFlag;
|
||||||
|
|
||||||
// cache hashcode - this class is immutable, and is used as an index in the permission cache.
|
// cache hashcode - this class is immutable, and is used as an index in the permission cache.
|
||||||
private final int hashCode;
|
private final int hashCode;
|
||||||
@ -180,20 +169,20 @@ public class Contexts {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
public Contexts(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
public Contexts(@NonNull ContextSet contextSet, boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
||||||
this.contextSet = Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
|
this.contextSet = Objects.requireNonNull(contextSet, "contextSet").makeImmutable();
|
||||||
this.settings = ImmutableSet.copyOf(formSettings(
|
this.settingsFlag = LookupSetting.createFlag(
|
||||||
includeNodesSetWithoutServer,
|
includeNodesSetWithoutServer,
|
||||||
includeNodesSetWithoutWorld,
|
includeNodesSetWithoutWorld,
|
||||||
resolveInheritance,
|
resolveInheritance,
|
||||||
applyParentsWithoutServer,
|
applyParentsWithoutServer,
|
||||||
applyParentsWithoutWorld,
|
applyParentsWithoutWorld,
|
||||||
isOp
|
isOp
|
||||||
));
|
);
|
||||||
this.hashCode = calculateHashCode();
|
this.hashCode = calculateHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Contexts(@NonNull ImmutableContextSet contextSet, @NonNull ImmutableSet<LookupSetting> settings) {
|
protected Contexts(@NonNull ImmutableContextSet contextSet, byte settingsFlag) {
|
||||||
this.contextSet = contextSet;
|
this.contextSet = contextSet;
|
||||||
this.settings = settings;
|
this.settingsFlag = settingsFlag;
|
||||||
this.hashCode = calculateHashCode();
|
this.hashCode = calculateHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +203,7 @@ public class Contexts {
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public @NonNull Set<LookupSetting> getSettings() {
|
public @NonNull Set<LookupSetting> getSettings() {
|
||||||
return this.settings;
|
return LookupSetting.createSetFromFlag(this.settingsFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -225,7 +214,7 @@ public class Contexts {
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public boolean hasSetting(@NonNull LookupSetting setting) {
|
public boolean hasSetting(@NonNull LookupSetting setting) {
|
||||||
return this.settings.contains(setting);
|
return LookupSetting.isSet(this.settingsFlag, setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,7 +291,7 @@ public class Contexts {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull String toString() {
|
public @NonNull String toString() {
|
||||||
return "Contexts(contextSet=" + this.contextSet + ", settings=" + this.settings + ")";
|
return "Contexts(contextSet=" + this.contextSet + ", settings=" + LookupSetting.createSetFromFlag(this.settingsFlag) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -311,14 +300,14 @@ public class Contexts {
|
|||||||
if (o == allowAll()) return false;
|
if (o == allowAll()) return false;
|
||||||
if (!(o instanceof Contexts)) return false;
|
if (!(o instanceof Contexts)) return false;
|
||||||
final Contexts that = (Contexts) o;
|
final Contexts that = (Contexts) o;
|
||||||
return this.contextSet.equals(that.contextSet) && this.settings.equals(that.settings);
|
return this.contextSet.equals(that.contextSet) && this.settingsFlag == that.settingsFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateHashCode() {
|
private int calculateHashCode() {
|
||||||
final int PRIME = 59;
|
final int PRIME = 59;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = result * PRIME + this.contextSet.hashCode();
|
result = result * PRIME + this.contextSet.hashCode();
|
||||||
result = result * PRIME + this.settings.hashCode();
|
result = result * PRIME + this.settingsFlag;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,27 +316,4 @@ public class Contexts {
|
|||||||
return this.hashCode;
|
return this.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EnumSet<LookupSetting> formSettings(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
|
||||||
EnumSet<LookupSetting> settings = EnumSet.noneOf(LookupSetting.class);
|
|
||||||
if (includeNodesSetWithoutServer) {
|
|
||||||
settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER);
|
|
||||||
}
|
|
||||||
if (includeNodesSetWithoutWorld) {
|
|
||||||
settings.add(LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD);
|
|
||||||
}
|
|
||||||
if (resolveInheritance) {
|
|
||||||
settings.add(LookupSetting.RESOLVE_INHERITANCE);
|
|
||||||
}
|
|
||||||
if (applyParentsWithoutServer) {
|
|
||||||
settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER);
|
|
||||||
}
|
|
||||||
if (applyParentsWithoutWorld) {
|
|
||||||
settings.add(LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD);
|
|
||||||
}
|
|
||||||
if (isOp) {
|
|
||||||
settings.add(LookupSetting.IS_OP);
|
|
||||||
}
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.api;
|
package me.lucko.luckperms.api;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.api.caching.CachedData;
|
import me.lucko.luckperms.api.caching.CachedData;
|
||||||
import me.lucko.luckperms.api.caching.MetaContexts;
|
import me.lucko.luckperms.api.caching.MetaContexts;
|
||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
@ -59,7 +57,7 @@ public final class FullySatisfiedContexts extends Contexts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private FullySatisfiedContexts() {
|
private FullySatisfiedContexts() {
|
||||||
super(ImmutableContextSet.empty(), ImmutableSet.copyOf(Contexts.global().getSettings()));
|
super(ImmutableContextSet.empty(), LookupSetting.createFlag(Contexts.global().getSettings()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
package me.lucko.luckperms.api;
|
package me.lucko.luckperms.api;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The various lookup setting flags for {@link Contexts}.
|
* The various lookup setting flags for {@link Contexts}.
|
||||||
*
|
*
|
||||||
@ -60,5 +63,62 @@ public enum LookupSetting {
|
|||||||
/**
|
/**
|
||||||
* If global or non-world-specific group memberships should be applied
|
* If global or non-world-specific group memberships should be applied
|
||||||
*/
|
*/
|
||||||
APPLY_PARENTS_SET_WITHOUT_WORLD
|
APPLY_PARENTS_SET_WITHOUT_WORLD;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* bitwise utility methods */
|
||||||
|
|
||||||
|
static boolean isSet(byte b, LookupSetting setting) {
|
||||||
|
return ((b >> setting.ordinal()) & 1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte createFlag(LookupSetting... settings) {
|
||||||
|
byte b = 0;
|
||||||
|
for (LookupSetting setting : settings) {
|
||||||
|
b |= (1 << setting.ordinal());
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte createFlag(Set<LookupSetting> settings) {
|
||||||
|
byte b = 0;
|
||||||
|
for (LookupSetting setting : settings) {
|
||||||
|
b |= (1 << setting.ordinal());
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Set<LookupSetting> createSetFromFlag(byte b) {
|
||||||
|
EnumSet<LookupSetting> settings = EnumSet.noneOf(LookupSetting.class);
|
||||||
|
for (LookupSetting setting : LookupSetting.values()) {
|
||||||
|
if (((b >> setting.ordinal()) & 1) == 1) {
|
||||||
|
settings.add(setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte createFlag(boolean includeNodesSetWithoutServer, boolean includeNodesSetWithoutWorld, boolean resolveInheritance, boolean applyParentsWithoutServer, boolean applyParentsWithoutWorld, boolean isOp) {
|
||||||
|
byte b = 0;
|
||||||
|
if (includeNodesSetWithoutServer) {
|
||||||
|
b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_SERVER.ordinal());
|
||||||
|
}
|
||||||
|
if (includeNodesSetWithoutWorld) {
|
||||||
|
b |= (1 << LookupSetting.INCLUDE_NODES_SET_WITHOUT_WORLD.ordinal());
|
||||||
|
}
|
||||||
|
if (resolveInheritance) {
|
||||||
|
b |= (1 << LookupSetting.RESOLVE_INHERITANCE.ordinal());
|
||||||
|
}
|
||||||
|
if (applyParentsWithoutServer) {
|
||||||
|
b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_SERVER.ordinal());
|
||||||
|
}
|
||||||
|
if (applyParentsWithoutWorld) {
|
||||||
|
b |= (1 << LookupSetting.APPLY_PARENTS_SET_WITHOUT_WORLD.ordinal());
|
||||||
|
}
|
||||||
|
if (isOp) {
|
||||||
|
b |= (1 << LookupSetting.IS_OP.ordinal());
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user