From f57afb294401c51090e2f9e8326f242f1eeff3db Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 21 Aug 2014 22:39:32 -0700 Subject: [PATCH] Don't use the region chunk has table until a threshold. --- .../managers/index/ChunkHashTable.java | 108 ++++++++++-------- 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/sk89q/worldguard/protection/managers/index/ChunkHashTable.java b/src/main/java/com/sk89q/worldguard/protection/managers/index/ChunkHashTable.java index b3730ca1..6b169ed6 100644 --- a/src/main/java/com/sk89q/worldguard/protection/managers/index/ChunkHashTable.java +++ b/src/main/java/com/sk89q/worldguard/protection/managers/index/ChunkHashTable.java @@ -51,8 +51,14 @@ */ public class ChunkHashTable implements ConcurrentRegionIndex { + /** + * The number of regions required before this hash table kicks in. + */ + private static final int CACHE_THRESHOLD = 5; + private ListeningExecutorService executor = createExecutor(); - private LongHashTable states = new LongHashTable(); + @Nullable + private LongHashTable states; private final RegionIndex index; private final Object lock = new Object(); @Nullable @@ -79,35 +85,23 @@ private ListeningExecutorService createExecutor() { } /** - * Get a state object at the given position. + * Get a state object at the given position, returning an entry only + * if one exists. * * @param position the position - * @param create true to create an entry if one does not exist - * @return a chunk state object, or {@code null} (only if {@code create} is false) + * @return a chunk state object, or {@code null} */ @Nullable - private ChunkState get(Vector2D position, boolean create) { - ChunkState state; - synchronized (lock) { - state = states.get(position.getBlockX(), position.getBlockZ()); - if (state == null && create) { - state = new ChunkState(position); - states.put(position.getBlockX(), position.getBlockZ(), state); - executor.submit(new EnumerateRegions(position)); - } - } - return state; - } + private ChunkState get(Vector2D position) { + LongHashTable states = this.states; - /** - * Get a state at the given position or create a new entry if one does - * not exist. - * - * @param position the position - * @return a state - */ - private ChunkState getOrCreate(Vector2D position) { - return get(position, true); + if (states != null) { + synchronized (lock) { + return states.get(position.getBlockX(), position.getBlockZ()); + } + } else { + return null; + } } /** @@ -118,22 +112,30 @@ private void rebuild() { ListeningExecutorService previousExecutor = executor; LongHashTable previousStates = states; - previousExecutor.shutdownNow(); - states = new LongHashTable(); - executor = createExecutor(); + if (index.size() > CACHE_THRESHOLD) { + previousExecutor.shutdownNow(); - List positions = new ArrayList(); - for (ChunkState state : previousStates.values()) { - Vector2D position = state.getPosition(); - positions.add(position); - states.put(position.getBlockX(), position.getBlockZ(), new ChunkState(position)); + states = new LongHashTable(); + executor = createExecutor(); + + if (previousStates != null) { + List positions = new ArrayList(); + + for (ChunkState state : previousStates.values()) { + Vector2D position = state.getPosition(); + positions.add(position); + states.put(position.getBlockX(), position.getBlockZ(), new ChunkState(position)); + } + + if (!positions.isEmpty()) { + executor.submit(new EnumerateRegions(positions)); + } + } + + lastState = null; + } else { + states = null; } - - if (!positions.isEmpty()) { - executor.submit(new EnumerateRegions(positions)); - } - - lastState = null; } } @@ -159,7 +161,19 @@ public boolean awaitCompletion(long timeout, TimeUnit unit) throws InterruptedEx @Override public void bias(Vector2D chunkPosition) { checkNotNull(chunkPosition); - getOrCreate(chunkPosition); + + if (states != null) { + synchronized (lock) { + if (states != null) { + ChunkState state = states.get(chunkPosition.getBlockX(), chunkPosition.getBlockZ()); + if (state == null) { + state = new ChunkState(chunkPosition); + states.put(chunkPosition.getBlockX(), chunkPosition.getBlockZ(), state); + executor.submit(new EnumerateRegions(chunkPosition)); + } + } + } + } } @Override @@ -175,10 +189,12 @@ public void biasAll(Collection chunkPositions) { public void forget(Vector2D chunkPosition) { checkNotNull(chunkPosition); synchronized (lock) { - states.remove(chunkPosition.getBlockX(), chunkPosition.getBlockZ()); - ChunkState state = lastState; - if (state != null && state.getPosition().getBlockX() == chunkPosition.getBlockX() && state.getPosition().getBlockZ() == chunkPosition.getBlockZ()) { - lastState = null; + if (states != null) { + states.remove(chunkPosition.getBlockX(), chunkPosition.getBlockZ()); + ChunkState state = lastState; + if (state != null && state.getPosition().getBlockX() == chunkPosition.getBlockX() && state.getPosition().getBlockZ() == chunkPosition.getBlockZ()) { + lastState = null; + } } } } @@ -238,7 +254,7 @@ public void applyContaining(Vector position, Predicate consumer int chunkZ = position.getBlockZ() >> 4; if (state == null || state.getPosition().getBlockX() != chunkX || state.getPosition().getBlockZ() != chunkZ) { - state = get(new Vector2D(chunkX, chunkZ), false); + state = get(new Vector2D(chunkX, chunkZ)); } if (state != null && state.isLoaded()) { @@ -301,7 +317,7 @@ private EnumerateRegions(List positions) { @Override public void run() { for (Vector2D position : positions) { - ChunkState state = get(position, false); + ChunkState state = get(position); if (state != null) { List regions = new ArrayList();