Use a boolean lookup table instead of a ConcurrentHashMap.

This commit is contained in:
Kristian S. Stangeland 2012-10-17 04:13:25 +02:00
parent fee9a32e4b
commit dd5303ea88
5 changed files with 90 additions and 13 deletions

View File

@ -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.
* <p>
* 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.
* <p>
* This creates a set for elements in the range [0, count).
* <p>
* 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<Integer> toSet() {
Set<Integer> elements = new HashSet<Integer>();
for (int i = 0; i < array.length; i++) {
if (array[i])
elements.add(i);
}
return elements;
}
}

View File

@ -68,13 +68,13 @@ class NetworkFieldInjector extends PlayerInjector {
private Object syncObject;
// Determine if we're listening
private Set<Integer> sendingFilters;
private IntegerSet sendingFilters;
// Used to construct proxy objects
private ClassLoader classLoader;
public NetworkFieldInjector(ClassLoader classLoader, Logger logger, Player player,
ListenerInvoker manager, Set<Integer> sendingFilters) throws IllegalAccessException {
ListenerInvoker manager, IntegerSet sendingFilters) throws IllegalAccessException {
super(logger, player, manager);
this.classLoader = classLoader;

View File

@ -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<Integer> sendingFilters;
private IntegerSet sendingFilters;
// Used to construct proxy objects
private ClassLoader classLoader;
public NetworkObjectInjector(ClassLoader classLoader, Logger logger, Player player,
ListenerInvoker invoker, Set<Integer> sendingFilters) throws IllegalAccessException {
ListenerInvoker invoker, IntegerSet sendingFilters) throws IllegalAccessException {
super(logger, player, invoker);
this.sendingFilters = sendingFilters;
this.classLoader = classLoader;

View File

@ -55,14 +55,14 @@ public class NetworkServerInjector extends PlayerInjector {
private InjectedServerConnection serverInjection;
// Determine if we're listening
private Set<Integer> sendingFilters;
private IntegerSet sendingFilters;
// Used to create proxy objects
private ClassLoader classLoader;
public NetworkServerInjector(
ClassLoader classLoader, Logger logger, Player player,
ListenerInvoker invoker, Set<Integer> sendingFilters,
ListenerInvoker invoker, IntegerSet sendingFilters,
InjectedServerConnection serverInjection) throws IllegalAccessException {
super(logger, player, invoker);

View File

@ -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;
/**
@ -52,6 +49,11 @@ import com.google.common.collect.Maps;
*/
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<Integer> sendingFilters = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
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<Integer> getSendingFilters() {
return ImmutableSet.copyOf(sendingFilters);
return sendingFilters.toSet();
}
/**