From dd5303ea883a9a5af974318fc65154de4e017c04 Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Wed, 17 Oct 2012 04:13:25 +0200 Subject: [PATCH] Use a boolean lookup table instead of a ConcurrentHashMap. --- .../protocol/injector/player/IntegerSet.java | 76 +++++++++++++++++++ .../injector/player/NetworkFieldInjector.java | 4 +- .../player/NetworkObjectInjector.java | 5 +- .../player/NetworkServerInjector.java | 4 +- .../player/PlayerInjectionHandler.java | 14 ++-- 5 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/IntegerSet.java diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/IntegerSet.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/IntegerSet.java new file mode 100644 index 00000000..b877bc2a --- /dev/null +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/IntegerSet.java @@ -0,0 +1,76 @@ +package com.comphenix.protocol.injector.player; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Represents a very quick integer set that uses a lookup table to store membership. + *

+ * This class is intentionally missing a size method. + * @author Kristian + */ +class IntegerSet { + private final boolean[] array; + + /** + * Initialize a lookup table with the given maximum number of elements. + *

+ * This creates a set for elements in the range [0, count). + *

+ * Formally, the current set must be a subset of [0, 1, 2, ..., count - 1]. + * @param maximumCount - maximum element value and count. + */ + public IntegerSet(int maximumCount) { + this.array = new boolean[maximumCount]; + } + + /** + * Determine whether or not the given element exists in the set. + * @param value - the element to check. Must be in the range [0, count). + * @return TRUE if the given element exists, FALSE otherwise. + */ + public boolean contains(int element) { + return array[element]; + } + + /** + * Add the given element to the set, or do nothing if it already exists. + * @param element - element to add. + * @throws OutOfBoundsException If the given element is not in the range [0, count). + */ + public void add(int element) { + array[element] = true; + } + + /** + * Remove the given element from the set, or do nothing if it's already removed. + * @param element - element to remove. + */ + public void remove(int element) { + // We don't actually care if the caller tries to remove an element outside the valid set + if (element >= 0 && element < array.length) + array[element] = false; + } + + /** + * Remove every element from the set. + */ + public void clear() { + Arrays.fill(array, false); + } + + /** + * Convert the current IntegerSet to an equivalent HashSet. + * @return The resulting HashSet. + */ + public Set toSet() { + Set elements = new HashSet(); + + for (int i = 0; i < array.length; i++) { + if (array[i]) + elements.add(i); + } + return elements; + } +} diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkFieldInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkFieldInjector.java index c3c4f26d..d6c21dbb 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkFieldInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkFieldInjector.java @@ -68,13 +68,13 @@ class NetworkFieldInjector extends PlayerInjector { private Object syncObject; // Determine if we're listening - private Set sendingFilters; + private IntegerSet sendingFilters; // Used to construct proxy objects private ClassLoader classLoader; public NetworkFieldInjector(ClassLoader classLoader, Logger logger, Player player, - ListenerInvoker manager, Set sendingFilters) throws IllegalAccessException { + ListenerInvoker manager, IntegerSet sendingFilters) throws IllegalAccessException { super(logger, player, manager); this.classLoader = classLoader; diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkObjectInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkObjectInjector.java index d9af4827..e8d07dd8 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkObjectInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkObjectInjector.java @@ -28,7 +28,6 @@ import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; -import java.util.Set; import java.util.logging.Logger; import org.bukkit.entity.Player; @@ -47,13 +46,13 @@ import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks; */ class NetworkObjectInjector extends PlayerInjector { // Determine if we're listening - private Set sendingFilters; + private IntegerSet sendingFilters; // Used to construct proxy objects private ClassLoader classLoader; public NetworkObjectInjector(ClassLoader classLoader, Logger logger, Player player, - ListenerInvoker invoker, Set sendingFilters) throws IllegalAccessException { + ListenerInvoker invoker, IntegerSet sendingFilters) throws IllegalAccessException { super(logger, player, invoker); this.sendingFilters = sendingFilters; this.classLoader = classLoader; diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java index 01ea2fc9..993deb02 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/NetworkServerInjector.java @@ -55,14 +55,14 @@ public class NetworkServerInjector extends PlayerInjector { private InjectedServerConnection serverInjection; // Determine if we're listening - private Set sendingFilters; + private IntegerSet sendingFilters; // Used to create proxy objects private ClassLoader classLoader; public NetworkServerInjector( ClassLoader classLoader, Logger logger, Player player, - ListenerInvoker invoker, Set sendingFilters, + ListenerInvoker invoker, IntegerSet sendingFilters, InjectedServerConnection serverInjection) throws IllegalAccessException { super(logger, player, invoker); diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java index 23b82e2b..d6a69316 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/player/PlayerInjectionHandler.java @@ -22,10 +22,8 @@ import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; -import java.util.Collections; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -42,7 +40,6 @@ import com.comphenix.protocol.injector.ListenerInvoker; import com.comphenix.protocol.injector.PlayerLoggedOutException; import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks; import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; /** @@ -51,7 +48,12 @@ import com.google.common.collect.Maps; * @author Kristian */ public class PlayerInjectionHandler { - + + /** + * The highest possible packet ID. It's unlikely that this value will ever change. + */ + private static final int MAXIMUM_PACKET_ID = 255; + // Server connection injection private InjectedServerConnection serverInjection; @@ -80,7 +82,7 @@ public class PlayerInjectionHandler { private ListenerInvoker invoker; // Enabled packet filters - private Set sendingFilters = Collections.newSetFromMap(new ConcurrentHashMap()); + private IntegerSet sendingFilters = new IntegerSet(MAXIMUM_PACKET_ID + 1); // The class loader we're using private ClassLoader classLoader; @@ -477,7 +479,7 @@ public class PlayerInjectionHandler { * @return List of the sending listeners's packet IDs. */ public Set getSendingFilters() { - return ImmutableSet.copyOf(sendingFilters); + return sendingFilters.toSet(); } /**