From 84f611144ba7825f86de7d884674541c65bfb444 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 19 Jan 2013 19:28:14 +1100 Subject: [PATCH] Add Aikar's timings patches. --- ...e-duration-of-the-entire-timings-run.patch | 65 ++++ ...sHandler-for-adding-new-CraftBukkit-.patch | 133 +++++++ ...Add-Custom-Timings-to-various-points.patch | 329 ++++++++++++++++++ 3 files changed, 527 insertions(+) create mode 100644 Bukkit-Patches/0002-Measure-the-duration-of-the-entire-timings-run.patch create mode 100644 Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch create mode 100644 CraftBukkit-Patches/0019-Add-Custom-Timings-to-various-points.patch diff --git a/Bukkit-Patches/0002-Measure-the-duration-of-the-entire-timings-run.patch b/Bukkit-Patches/0002-Measure-the-duration-of-the-entire-timings-run.patch new file mode 100644 index 000000000..f595241c9 --- /dev/null +++ b/Bukkit-Patches/0002-Measure-the-duration-of-the-entire-timings-run.patch @@ -0,0 +1,65 @@ +From a1e1f7ed9dab3b4b7889ae54120fc1e24ccb0c12 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 9 Jan 2013 16:53:45 -0500 +Subject: [PATCH] Measure the duration of the entire timings run. + +--- + src/main/java/org/bukkit/command/defaults/TimingsCommand.java | 4 ++++ + src/main/java/org/bukkit/plugin/SimplePluginManager.java | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +index 29ebbe0..94cd62c 100644 +--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList; + public class TimingsCommand extends BukkitCommand { + private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate"); + ++ public static long timingStart = 0; // Spigot + public TimingsCommand(String name) { + super(name); + this.description = "Records timings for all plugin events"; +@@ -50,9 +51,11 @@ public class TimingsCommand extends BukkitCommand { + } + } + } ++ timingStart = System.nanoTime(); // Spigot + sender.sendMessage("Timings reset"); + } else if ("merged".equals(args[0]) || separate) { + ++ long sampleTime = System.nanoTime() - timingStart; // Spigot + int index = 0; + int pluginIdx = 0; + File timingFolder = new File("timings"); +@@ -92,6 +95,7 @@ public class TimingsCommand extends BukkitCommand { + } + fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); + } ++ fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1000000000 + "s)"); // Spigot + sender.sendMessage("Timings written to " + timings.getPath()); + if (separate) sender.sendMessage("Names written to " + names.getPath()); + } catch (IOException e) { +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index d4f6bf3..4049d3a 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -23,6 +23,7 @@ import org.bukkit.Server; + import org.bukkit.command.Command; + import org.bukkit.command.PluginCommandYamlParser; + import org.bukkit.command.SimpleCommandMap; ++import org.bukkit.command.defaults.TimingsCommand; + import org.bukkit.event.Event; + import org.bukkit.event.EventPriority; + import org.bukkit.event.HandlerList; +@@ -274,6 +275,7 @@ public final class SimplePluginManager implements PluginManager { + } + } + ++ TimingsCommand.timingStart = System.nanoTime(); // Spigot + return result.toArray(new Plugin[result.size()]); + } + +-- +1.8.1-rc2 + diff --git a/Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch b/Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch new file mode 100644 index 000000000..3c2e72cdb --- /dev/null +++ b/Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch @@ -0,0 +1,133 @@ +From 1b7af1803b6c1fdcc7f0d8574f37000bbe10923f Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 9 Jan 2013 22:18:26 -0500 +Subject: [PATCH] Add CustomTimingsHandler for adding new CraftBukkit custom + timings + +--- + .../org/bukkit/command/defaults/ReloadCommand.java | 2 + + .../bukkit/command/defaults/TimingsCommand.java | 4 ++ + .../org/bukkit/event/CustomTimingsHandler.java | 60 ++++++++++++++++++++++ + 3 files changed, 66 insertions(+) + create mode 100644 src/main/java/org/bukkit/event/CustomTimingsHandler.java + +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index fb3c90f..fffafa5 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -6,6 +6,7 @@ import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.Command; + import org.bukkit.command.CommandSender; ++import org.bukkit.event.CustomTimingsHandler; + + public class ReloadCommand extends BukkitCommand { + public ReloadCommand(String name) { +@@ -20,6 +21,7 @@ public class ReloadCommand extends BukkitCommand { + public boolean execute(CommandSender sender, String currentAlias, String[] args) { + if (!testPermission(sender)) return true; + ++ CustomTimingsHandler.reload(); // Spigot + Bukkit.reload(); + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Reload complete."); + +diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +index 94cd62c..e0628d0 100644 +--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +@@ -10,6 +10,7 @@ import org.apache.commons.lang.Validate; + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.CommandSender; ++import org.bukkit.event.CustomTimingsHandler; + import org.bukkit.event.Event; + import org.bukkit.event.HandlerList; + import org.bukkit.plugin.Plugin; +@@ -51,6 +52,7 @@ public class TimingsCommand extends BukkitCommand { + } + } + } ++ CustomTimingsHandler.reload(); // Spigot + timingStart = System.nanoTime(); // Spigot + sender.sendMessage("Timings reset"); + } else if ("merged".equals(args[0]) || separate) { +@@ -95,8 +97,10 @@ public class TimingsCommand extends BukkitCommand { + } + fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); + } ++ CustomTimingsHandler.printTimings(fileTimings); // Spigot + fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1000000000 + "s)"); // Spigot + sender.sendMessage("Timings written to " + timings.getPath()); ++ sender.sendMessage("Paste contents of file into form at http://aikar.co/timings.php to read results."); // Spigot + if (separate) sender.sendMessage("Names written to " + names.getPath()); + } catch (IOException e) { + } finally { +diff --git a/src/main/java/org/bukkit/event/CustomTimingsHandler.java b/src/main/java/org/bukkit/event/CustomTimingsHandler.java +new file mode 100644 +index 0000000..83294e3 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/CustomTimingsHandler.java +@@ -0,0 +1,60 @@ ++package org.bukkit.event; ++ ++ ++import org.bukkit.Bukkit; ++ ++import java.io.PrintStream; ++import java.util.ArrayList; ++ ++/** ++ * Extends RegisteredListener to include timing information ++ */ ++public class CustomTimingsHandler { ++ ++ private final String name; ++ public int count = 0; ++ public long totalTime = 0; ++ long start = 0; ++ ++ static public ArrayList allList = new ArrayList<>(); ++ public CustomTimingsHandler(String name) { ++ this.name = name; ++ allList.add(this); ++ } ++ ++ static public void printTimings(PrintStream printStream) { ++ printStream.println("Minecraft - ** indicates it's already counted by another timing"); ++ for (CustomTimingsHandler t : allList) { ++ long time = t.totalTime; ++ int count = t.count; ++ if (count == 0) continue; ++ long avg = time / count; ++ ++ printStream.println(" " + t.name + " Time: " + time + " Count: " + count + " Avg: " + avg); ++ } ++ } ++ ++ static public void reload() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ for (CustomTimingsHandler t : allList) { ++ t.reset(); ++ } ++ } ++ ++ public void startTiming() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ start = System.nanoTime(); ++ } ++ ++ public void stopTiming() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ totalTime += System.nanoTime() - start; ++ count++; ++ } ++ ++ public void reset() { ++ count = 0; ++ totalTime = 0; ++ } ++} ++ +-- +1.8.1-rc2 + diff --git a/CraftBukkit-Patches/0019-Add-Custom-Timings-to-various-points.patch b/CraftBukkit-Patches/0019-Add-Custom-Timings-to-various-points.patch new file mode 100644 index 000000000..2de98dd0a --- /dev/null +++ b/CraftBukkit-Patches/0019-Add-Custom-Timings-to-various-points.patch @@ -0,0 +1,329 @@ +From ef52fe6ba0830854af641e8e9355fc0a16f94c73 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 10 Jan 2013 00:18:11 -0500 +Subject: [PATCH] Add Custom Timings to various points + +--- + .../net/minecraft/server/ChunkProviderServer.java | 4 ++++ + .../java/net/minecraft/server/EntityLiving.java | 21 +++++++++++++++++++++ + .../java/net/minecraft/server/PlayerConnection.java | 7 +++++++ + src/main/java/net/minecraft/server/World.java | 9 +++++++++ + src/main/java/net/minecraft/server/WorldServer.java | 4 ++++ + .../java/org/bukkit/event/WorldTimingsHandler.java | 20 ++++++++++++++++++++ + 6 files changed, 65 insertions(+) + create mode 100644 src/main/java/org/bukkit/event/WorldTimingsHandler.java + +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index c0bab0f..279ba9e 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -15,6 +15,7 @@ import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor; + import org.bukkit.craftbukkit.util.LongHash; + import org.bukkit.craftbukkit.util.LongHashSet; + import org.bukkit.craftbukkit.util.LongObjectHashMap; ++import org.bukkit.event.CustomTimingsHandler; + import org.bukkit.event.world.ChunkUnloadEvent; + // CraftBukkit end + +@@ -28,6 +29,7 @@ public class ChunkProviderServer implements IChunkProvider { + public boolean forceChunkLoad = false; // true -> false + public LongObjectHashMap chunks = new LongObjectHashMap(); + public WorldServer world; ++ static private CustomTimingsHandler syncChunkLoadTimer = new CustomTimingsHandler("syncChunkLoad"); // Spigot + // CraftBukkit end + + public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, IChunkProvider ichunkprovider) { +@@ -103,6 +105,7 @@ public class ChunkProviderServer implements IChunkProvider { + // CraftBukkit end + + if (chunk == null) { ++ syncChunkLoadTimer.startTiming(); // Spigot + chunk = this.loadChunk(i, j); + if (chunk == null) { + if (this.chunkProvider == null) { +@@ -141,6 +144,7 @@ public class ChunkProviderServer implements IChunkProvider { + // CraftBukkit end + + chunk.a(this, this, i, j); ++ syncChunkLoadTimer.stopTiming(); // Spigot + } + + // CraftBukkit start - If we didn't need to load the chunk run the callback now +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 7d2e633..b2481aa 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -8,6 +8,7 @@ import java.util.Random; + + // CraftBukkit start + import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.CustomTimingsHandler; + import org.bukkit.event.entity.EntityDamageByBlockEvent; + import org.bukkit.event.entity.EntityDamageEvent; + import org.bukkit.event.entity.EntityRegainHealthEvent; +@@ -110,6 +111,14 @@ public abstract class EntityLiving extends Entity { + public int expToDrop = 0; + public int maxAirTicks = 300; + public int maxHealth = this.getMaxHealth(); ++ // Spigot Start ++ public static CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** entityBaseTick"); ++ public static CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** entityAI"); ++ public static CustomTimingsHandler timerEntityAIJump = new CustomTimingsHandler("** entityAIJump"); ++ public static CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** entityAIMove"); ++ public static CustomTimingsHandler timerEntityAILoot = new CustomTimingsHandler("** entityAILoot"); ++ public static CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** entityTickRest"); ++ // Spigot End + // CraftBukkit end + + public EntityLiving(World world) { +@@ -505,6 +514,7 @@ public abstract class EntityLiving extends Entity { + } + + public void j_() { ++ timerEntityBaseTick.startTiming(); // Spigot + super.j_(); + if (!this.world.isStatic) { + int i; +@@ -531,7 +541,9 @@ public abstract class EntityLiving extends Entity { + } + } + ++ timerEntityBaseTick.stopTiming(); // Spigot + this.c(); ++ timerEntityTickRest.startTiming(); // Spigot + double d0 = this.locX - this.lastX; + double d1 = this.locZ - this.lastZ; + float f = (float) (d0 * d0 + d1 * d1); +@@ -622,6 +634,7 @@ public abstract class EntityLiving extends Entity { + + this.world.methodProfiler.b(); + this.aD += f2; ++ timerEntityTickRest.stopTiming(); // Spigot + } + + // CraftBukkit start - delegate so we can handle providing a reason for health being regained +@@ -1228,6 +1241,7 @@ public abstract class EntityLiving extends Entity { + } + + public void c() { ++ timerEntityAI.startTiming(); // Spigot + if (this.bV > 0) { + --this.bV; + } +@@ -1279,9 +1293,11 @@ public abstract class EntityLiving extends Entity { + this.az = this.yaw; + } + } ++ timerEntityAI.stopTiming(); // Spigot + + this.world.methodProfiler.b(); + this.world.methodProfiler.a("jump"); ++ timerEntityAIJump.startTiming(); // Spigot + if (this.bF) { + if (!this.H() && !this.J()) { + if (this.onGround && this.bV == 0) { +@@ -1295,8 +1311,10 @@ public abstract class EntityLiving extends Entity { + this.bV = 0; + } + ++ timerEntityAIJump.stopTiming(); // Spigot + this.world.methodProfiler.b(); + this.world.methodProfiler.a("travel"); ++ timerEntityAIMove.startTiming(); // Spigot + this.bC *= 0.98F; + this.bD *= 0.98F; + this.bE *= 0.9F; +@@ -1305,6 +1323,7 @@ public abstract class EntityLiving extends Entity { + this.aN *= this.bB(); + this.e(this.bC, this.bD); + this.aN = f; ++ timerEntityAIMove.stopTiming(); // Spigot + this.world.methodProfiler.b(); + this.world.methodProfiler.a("push"); + if (!this.world.isStatic) { +@@ -1313,6 +1332,7 @@ public abstract class EntityLiving extends Entity { + + this.world.methodProfiler.b(); + this.world.methodProfiler.a("looting"); ++ timerEntityAILoot.startTiming(); // Spigot + // CraftBukkit - Don't run mob pickup code on players + if (!this.world.isStatic && !(this instanceof EntityPlayer) && this.canPickUpLoot && !this.bc && this.world.getGameRules().getBoolean("mobGriefing")) { + List list = this.world.a(EntityItem.class, this.boundingBox.grow(1.0D, 0.0D, 1.0D)); +@@ -1377,6 +1397,7 @@ public abstract class EntityLiving extends Entity { + } + } + ++ timerEntityAILoot.stopTiming(); // Spigot + this.world.methodProfiler.b(); + } + +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 80656b2..9cdadf1 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -25,6 +25,7 @@ import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.craftbukkit.entity.CraftPlayer; + import org.bukkit.craftbukkit.event.CraftEventFactory; + import org.bukkit.entity.Player; ++import org.bukkit.event.CustomTimingsHandler; + import org.bukkit.event.Event; + import org.bukkit.event.block.Action; + import org.bukkit.event.block.SignChangeEvent; +@@ -67,6 +68,7 @@ public class PlayerConnection extends Connection { + private double q; + public boolean checkMovement = true; // CraftBukkit - private -> public + private IntHashMap s = new IntHashMap(); ++ static private CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("playerCommand"); // Spigot + + public PlayerConnection(MinecraftServer minecraftserver, INetworkManager inetworkmanager, EntityPlayer entityplayer) { + this.minecraftServer = minecraftserver; +@@ -975,6 +977,7 @@ public class PlayerConnection extends Connection { + // CraftBukkit end + + private void handleCommand(String s) { ++ playerCommandTimer.startTiming(); // Spigot + // CraftBukkit start + CraftPlayer player = this.getPlayer(); + +@@ -982,19 +985,23 @@ public class PlayerConnection extends Connection { + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { ++ playerCommandTimer.stopTiming(); // Spigot + return; + } + + try { + if (server.logCommands) logger.info(event.getPlayer().getName() + " issued server command: " + event.getMessage()); // Spigot + if (this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ playerCommandTimer.stopTiming(); // Spigot + return; + } + } catch (org.bukkit.command.CommandException ex) { + player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); + Logger.getLogger(PlayerConnection.class.getName()).log(Level.SEVERE, null, ex); ++ playerCommandTimer.stopTiming(); // Spigot + return; + } ++ playerCommandTimer.stopTiming(); // Spigot + // CraftBukkit end + + /* CraftBukkit start - No longer needed as we have already handled it in server.dispatchServerCommand above. +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index e28aa00..3c6adb6 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -14,6 +14,7 @@ import java.util.concurrent.Callable; + import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.util.LongHashSet; + import org.bukkit.craftbukkit.util.UnsafeList; ++import org.bukkit.event.WorldTimingsHandler; + import org.bukkit.generator.ChunkGenerator; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; +@@ -114,6 +115,7 @@ public abstract class World implements IBlockAccess { + final Object chunkLock = new Object(); + private byte chunkTickRadius; + ++ public WorldTimingsHandler timings; // Spigot + public CraftWorld getWorld() { + return this.world; + } +@@ -193,6 +195,7 @@ public abstract class World implements IBlockAccess { + this.a(); + + this.getServer().addWorld(this.world); // CraftBukkit ++ timings = new WorldTimingsHandler(this); // Spigot + } + + protected abstract IChunkProvider j(); +@@ -1207,6 +1210,7 @@ public abstract class World implements IBlockAccess { + CrashReport crashreport; + CrashReportSystemDetails crashreportsystemdetails; + ++ timings.entityBaseTick.startTiming(); // Spigot + for (i = 0; i < this.i.size(); ++i) { + entity = (Entity) this.i.get(i); + // CraftBukkit start - fixed an NPE, don't process entities in chunks queued for unload +@@ -1261,7 +1265,9 @@ public abstract class World implements IBlockAccess { + + this.f.clear(); + this.methodProfiler.c("regular"); ++ timings.entityBaseTick.stopTiming(); // Spigot + ++ timings.entityTick.startTiming(); // Spigot + for (i = 0; i < this.entityList.size(); ++i) { + entity = (Entity) this.entityList.get(i); + +@@ -1314,7 +1320,9 @@ public abstract class World implements IBlockAccess { + this.methodProfiler.b(); + } + ++ timings.entityTick.stopTiming(); // Spigot + this.methodProfiler.c("tileEntities"); ++ timings.tileEntityTick.startTiming(); // Spigot + this.M = true; + Iterator iterator = this.tileEntityList.iterator(); + +@@ -1393,6 +1401,7 @@ public abstract class World implements IBlockAccess { + this.a.clear(); + } + ++ timings.tileEntityTick.stopTiming(); // Spigot + this.methodProfiler.b(); + this.methodProfiler.b(); + } +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 6e5434b..fdb3fc7 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -157,9 +157,12 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate + // CraftBukkit start - Only call spawner if we have players online and the world allows for mobs or animals + long time = this.worldData.getTime(); + if (this.getGameRules().getBoolean("doMobSpawning") && (this.allowMonsters || this.allowAnimals) && (this instanceof WorldServer && this.players.size() > 0)) { ++ timings.mobSpawn.startTiming(); // Spigot + SpawnerCreature.spawnEntities(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L), this.worldData.getTime() % 400L == 0L); ++ timings.mobSpawn.stopTiming(); // Spigot + } + // CraftBukkit end ++ timings.doTickRest.startTiming(); // Spigot + this.getWorld().processChunkGC(); // Spigot + this.methodProfiler.c("chunkSource"); + this.chunkProvider.unloadChunks(); +@@ -187,6 +190,7 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate + this.V(); + + this.getWorld().processChunkGC(); // CraftBukkit ++ timings.doTickRest.stopTiming(); // Spigot + } + + public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) { +diff --git a/src/main/java/org/bukkit/event/WorldTimingsHandler.java b/src/main/java/org/bukkit/event/WorldTimingsHandler.java +new file mode 100644 +index 0000000..bb0c191 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/WorldTimingsHandler.java +@@ -0,0 +1,20 @@ ++package org.bukkit.event; ++ ++import net.minecraft.server.World; ++ ++public class WorldTimingsHandler { ++ public CustomTimingsHandler mobSpawn; ++ public CustomTimingsHandler doTickRest; ++ public CustomTimingsHandler entityBaseTick; ++ public CustomTimingsHandler entityTick; ++ public CustomTimingsHandler tileEntityTick; ++ public WorldTimingsHandler(World server) { ++ String name = server.worldData.getName() +" - "; ++ ++ mobSpawn = new CustomTimingsHandler(name + "mobSpawn"); ++ doTickRest = new CustomTimingsHandler(name + "doTickRest"); ++ entityBaseTick = new CustomTimingsHandler(name + "entityBaseTick"); ++ entityTick = new CustomTimingsHandler(name + "entityTick"); ++ tileEntityTick = new CustomTimingsHandler(name + "tileEntityTick"); ++ } ++} +-- +1.8.1-rc2 +