diff --git a/Spigot-API-Patches/Timings-v2.patch b/Spigot-API-Patches/Timings-v2.patch
index 30e889a237..4aa6085169 100644
--- a/Spigot-API-Patches/Timings-v2.patch
+++ b/Spigot-API-Patches/Timings-v2.patch
@@ -6,7 +6,7 @@ Subject: [PATCH] Timings v2
 
 diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java
 new file mode 100644
-index 000000000..4d8b633ed
+index 000000000..98079dc0c
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java
 @@ -0,0 +0,0 @@
@@ -15,7 +15,7 @@ index 000000000..4d8b633ed
 +import static co.aikar.timings.TimingsManager.*;
 +
 +public class FullServerTickHandler extends TimingHandler {
-+    private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null, false);
++    private static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null);
 +    final TimingData minuteData;
 +    double avgFreeMemory = -1D;
 +    double avgUsedMemory = -1D;
@@ -456,7 +456,7 @@ index 000000000..f222d6b7d
 +}
 diff --git a/src/main/java/co/aikar/timings/TimingHandler.java b/src/main/java/co/aikar/timings/TimingHandler.java
 new file mode 100644
-index 000000000..916b6f9d6
+index 000000000..521c985e6
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingHandler.java
 @@ -0,0 +0,0 @@
@@ -489,12 +489,13 @@ index 000000000..916b6f9d6
 +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 +import org.bukkit.Bukkit;
 +
++import java.util.concurrent.atomic.AtomicInteger;
 +import java.util.logging.Level;
 +
 +class TimingHandler implements Timing {
 +
-+    private static int idPool = 1;
-+    final int id = idPool++;
++    private static AtomicInteger idPool = new AtomicInteger(1);
++    final int id = idPool.getAndIncrement();
 +
 +    final String name;
 +    private final boolean verbose;
@@ -546,21 +547,17 @@ index 000000000..916b6f9d6
 +
 +    @Override
 +    public Timing startTimingIfSync() {
-+        if (Bukkit.isPrimaryThread()) {
-+            startTiming();
-+        }
++        startTiming();
 +        return this;
 +    }
 +
 +    @Override
 +    public void stopTimingIfSync() {
-+        if (Bukkit.isPrimaryThread()) {
-+            stopTiming();
-+        }
++        stopTiming();
 +    }
 +
 +    public Timing startTiming() {
-+        if (enabled && ++timingDepth == 1) {
++        if (enabled && Bukkit.isPrimaryThread() && ++timingDepth == 1) {
 +            start = System.nanoTime();
 +            parent = TimingsManager.CURRENT;
 +            TimingsManager.CURRENT = this;
@@ -569,13 +566,7 @@ index 000000000..916b6f9d6
 +    }
 +
 +    public void stopTiming() {
-+        if (enabled && --timingDepth == 0 && start != 0) {
-+            if (!Bukkit.isPrimaryThread()) {
-+                Bukkit.getLogger().log(Level.SEVERE, "stopTiming called async for " + name);
-+                new Throwable().printStackTrace();
-+                start = 0;
-+                return;
-+            }
++        if (enabled && timingDepth > 0 && Bukkit.isPrimaryThread() && --timingDepth == 0 && start != 0) {
 +            addDiff(System.nanoTime() - start);
 +            start = 0;
 +        }
@@ -1090,7 +1081,7 @@ index 000000000..0e114eb32
 +}
 diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java
 new file mode 100644
-index 000000000..623dda49c
+index 000000000..63b4f318a
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingIdentifier.java
 @@ -0,0 +0,0 @@
@@ -1119,12 +1110,12 @@ index 000000000..623dda49c
 + */
 +package co.aikar.timings;
 +
-+import com.google.common.base.Function;
 +import co.aikar.util.LoadingMap;
 +import co.aikar.util.MRUMapCache;
 +
 +import java.util.ArrayDeque;
 +import java.util.Map;
++import java.util.concurrent.atomic.AtomicInteger;
 +
 +/**
 + * <p>Used as a basis for fast HashMap key comparisons for the Timing Map.</p>
@@ -1136,25 +1127,18 @@ index 000000000..623dda49c
 +     * Holds all groups. Autoloads on request for a group by name.
 +     */
 +    static final Map<String, TimingGroup> GROUP_MAP = MRUMapCache.of(
-+        LoadingMap.newIdentityHashMap(new Function<String, TimingGroup>() {
-+            @Override
-+            public TimingGroup apply(String group) {
-+                return new TimingGroup(group);
-+            }
-+        }, 64)
++        LoadingMap.newIdentityHashMap(TimingGroup::new, 64)
 +    );
-+    static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft");
++    private static final TimingGroup DEFAULT_GROUP = getGroup("Minecraft");
 +    final String group;
 +    final String name;
 +    final TimingHandler groupHandler;
-+    final boolean protect;
 +    private final int hashCode;
 +
-+    TimingIdentifier(String group, String name, Timing groupHandler, boolean protect) {
++    TimingIdentifier(String group, String name, Timing groupHandler) {
 +        this.group = group != null ? group.intern() : DEFAULT_GROUP.name;
 +        this.name = name.intern();
 +        this.groupHandler = groupHandler != null ? groupHandler.getTimingHandler() : null;
-+        this.protect = protect;
 +        this.hashCode = (31 * this.group.hashCode()) + this.name.hashCode();
 +    }
 +
@@ -1185,8 +1169,8 @@ index 000000000..623dda49c
 +
 +    static class TimingGroup {
 +
-+        private static int idPool = 1;
-+        final int id = idPool++;
++        private static AtomicInteger idPool = new AtomicInteger(1);
++        final int id = idPool.getAndIncrement();
 +
 +        final String name;
 +        ArrayDeque<TimingHandler> handlers = new ArrayDeque<TimingHandler>(64);
@@ -1194,11 +1178,24 @@ index 000000000..623dda49c
 +        private TimingGroup(String name) {
 +            this.name = name;
 +        }
++
++        @Override
++        public boolean equals(Object o) {
++            if (this == o) return true;
++            if (o == null || getClass() != o.getClass()) return false;
++            TimingGroup that = (TimingGroup) o;
++            return id == that.id;
++        }
++
++        @Override
++        public int hashCode() {
++            return id;
++        }
 +    }
 +}
 diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java
 new file mode 100644
-index 000000000..32e4bb1e2
+index 000000000..f907649ba
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/Timings.java
 @@ -0,0 +0,0 @@
@@ -1278,7 +1275,7 @@ index 000000000..32e4bb1e2
 +     */
 +    public static Timing of(Plugin plugin, String name, Timing groupHandler) {
 +        Preconditions.checkNotNull(plugin, "Plugin can not be null");
-+        return TimingsManager.getHandler(plugin.getName(), name, groupHandler, true);
++        return TimingsManager.getHandler(plugin.getName(), name, groupHandler);
 +    }
 +
 +    /**
@@ -1310,7 +1307,7 @@ index 000000000..32e4bb1e2
 +     */
 +    public static Timing ofStart(Plugin plugin, String name, Timing groupHandler) {
 +        Timing timing = of(plugin, name, groupHandler);
-+        timing.startTimingIfSync();
++        timing.startTiming();
 +        return timing;
 +    }
 +
@@ -1483,7 +1480,7 @@ index 000000000..32e4bb1e2
 +    }
 +
 +    static TimingHandler ofSafe(String groupName, String name, Timing groupHandler) {
-+        return TimingsManager.getHandler(groupName, name, groupHandler, false);
++        return TimingsManager.getHandler(groupName, name, groupHandler);
 +    }
 +}
 diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java
@@ -1961,7 +1958,7 @@ index 000000000..df7f42595
 +}
 diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java
 new file mode 100644
-index 000000000..58ed35e00
+index 000000000..e0f3e07fe
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingsManager.java
 @@ -0,0 +0,0 @@
@@ -1990,7 +1987,6 @@ index 000000000..58ed35e00
 + */
 +package co.aikar.timings;
 +
-+import com.google.common.base.Function;
 +import com.google.common.collect.EvictingQueue;
 +import org.bukkit.Bukkit;
 +import org.bukkit.Server;
@@ -2010,16 +2006,8 @@ index 000000000..58ed35e00
 +public final class TimingsManager {
 +    static final Map<TimingIdentifier, TimingHandler> TIMING_MAP =
 +        Collections.synchronizedMap(LoadingMap.newHashMap(
-+            new Function<TimingIdentifier, TimingHandler>() {
-+                @Override
-+                public TimingHandler apply(TimingIdentifier id) {
-+                    return (id.protect ?
-+                        new UnsafeTimingHandler(id) :
-+                        new TimingHandler(id)
-+                    );
-+                }
-+            },
-+            256, .5F
++            TimingHandler::new,
++            4096, .5F
 +        ));
 +    public static final FullServerTickHandler FULL_SERVER_TICK = new FullServerTickHandler();
 +    public static final TimingHandler TIMINGS_TICK = Timings.ofSafe("Timings Tick", FULL_SERVER_TICK);
@@ -2108,8 +2096,8 @@ index 000000000..58ed35e00
 +        historyStart = System.currentTimeMillis();
 +    }
 +
-+    static TimingHandler getHandler(String group, String name, Timing parent, boolean protect) {
-+        return TIMING_MAP.get(new TimingIdentifier(group, name, parent, protect));
++    static TimingHandler getHandler(String group, String name, Timing parent) {
++        return TIMING_MAP.get(new TimingIdentifier(group, name, parent));
 +    }
 +
 +