From 3656d1faf6a82a57643c4e9b4a69ce221bede795 Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au>
Date: Sat, 23 Mar 2013 09:29:43 +1100
Subject: [PATCH] LongHash Tweaks.

This commit adds a flat array based cache to the LongHash(Set/Map) classes leading to excellent efficiency for servers where most activity is centered around the origin (0,0)

diff --git a/src/main/java/org/bukkit/craftbukkit/util/FlatMap.java b/src/main/java/org/bukkit/craftbukkit/util/FlatMap.java
new file mode 100644
index 0000000..e8a7725
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/util/FlatMap.java
@@ -0,0 +1,34 @@
+package org.bukkit.craftbukkit.util;
+
+public class FlatMap<V> {
+
+    private static final int FLAT_LOOKUP_SIZE = 512;
+    private final Object[][] flatLookup = new Object[FLAT_LOOKUP_SIZE * 2][FLAT_LOOKUP_SIZE * 2];
+
+    public void put(long msw, long lsw, V value) {
+        long acx = Math.abs(msw);
+        long acz = Math.abs(lsw);
+        if (acx < FLAT_LOOKUP_SIZE && acz < FLAT_LOOKUP_SIZE) {
+            flatLookup[(int) (msw + FLAT_LOOKUP_SIZE)][(int) (lsw + FLAT_LOOKUP_SIZE)] = value;
+        }
+    }
+
+    public void put(long key, V value) {
+        put(LongHash.msw(key), LongHash.lsw(key), value);
+
+    }
+
+    public V get(long msw, long lsw) {
+        long acx = Math.abs(msw);
+        long acz = Math.abs(lsw);
+        if (acx < FLAT_LOOKUP_SIZE && acz < FLAT_LOOKUP_SIZE) {
+            return (V) flatLookup[(int) (msw + FLAT_LOOKUP_SIZE)][(int) (lsw + FLAT_LOOKUP_SIZE)];
+        } else {
+            return null;
+        }
+    }
+
+    public V get(long key) {
+        return get(LongHash.msw(key), LongHash.lsw(key));
+    }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java
index 22c96c5..331d570 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LongHashSet.java
@@ -31,6 +31,8 @@ public class LongHashSet {
     private int elements;
     private long[] values;
     private int modCount;
+    private static final Object PRESENT = new Object();
+    private final FlatMap<Object> flat = new FlatMap<Object>();
 
     public LongHashSet() {
         this(INITIAL_SIZE);
@@ -56,10 +58,12 @@ public class LongHashSet {
     }
 
     public boolean contains(int msw, int lsw) {
+        if (flat.get(msw, lsw) != null) return true; // Spigot
         return contains(LongHash.toLong(msw, lsw));
     }
 
     public boolean contains(long value) {
+        if (flat.get(value) != null) return true; // Spigot
         int hash = hash(value);
         int index = (hash & 0x7FFFFFFF) % values.length;
         int offset = 1;
@@ -82,6 +86,7 @@ public class LongHashSet {
     }
 
     public boolean add(long value) {
+        flat.put(value, PRESENT); // Spigot
         int hash = hash(value);
         int index = (hash & 0x7FFFFFFF) % values.length;
         int offset = 1;
@@ -125,10 +130,11 @@ public class LongHashSet {
     }
 
     public void remove(int msw, int lsw) {
+        flat.put(msw, lsw, null); // Spigot
         remove(LongHash.toLong(msw, lsw));
     }
 
-    public boolean remove(long value) {
+    private boolean remove(long value) { // Spigot
         int hash = hash(value);
         int index = (hash & 0x7FFFFFFF) % values.length;
         int offset = 1;
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java b/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java
index 01861cc..dbd33fa 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LongObjectHashMap.java
@@ -28,6 +28,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     private transient V[][]    values;
     private transient int      modCount;
     private transient int      size;
+    private final FlatMap<V> flat = new FlatMap<V>(); // Spigot
 
     public LongObjectHashMap() {
         initialize();
@@ -61,6 +62,8 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     }
 
     public V get(long key) {
+        V val = flat.get(key); // Spigot
+        if (val != null) return val; // Spigot
         int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
         long[] inner = keys[index];
         if (inner == null) return null;
@@ -78,6 +81,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     }
 
     public V put(long key, V value) {
+        flat.put(key, value); // Spigot
         int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
         long[] innerKeys = keys[index];
         V[] innerValues = values[index];
@@ -124,6 +128,7 @@ public class LongObjectHashMap<V> implements Cloneable, Serializable {
     }
 
     public V remove(long key) {
+        flat.put(key, null); // Spigot
         int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
         long[] inner = keys[index];
         if (inner == null) {
-- 
1.8.1.2