diff --git a/src/main/java/net/minecraft/server/Vec3D.java b/src/main/java/net/minecraft/server/Vec3D.java index c1c9c49428..2122b93f33 100644 --- a/src/main/java/net/minecraft/server/Vec3D.java +++ b/src/main/java/net/minecraft/server/Vec3D.java @@ -6,6 +6,7 @@ public class Vec3D { public double a; public double b; public double c; + public Vec3D next; // CraftBukkit public static Vec3D a(double d0, double d1, double d2) { return new Vec3D(d0, d1, d2); diff --git a/src/main/java/net/minecraft/server/Vec3DPool.java b/src/main/java/net/minecraft/server/Vec3DPool.java index 33e21ef276..897fef938f 100644 --- a/src/main/java/net/minecraft/server/Vec3DPool.java +++ b/src/main/java/net/minecraft/server/Vec3DPool.java @@ -7,7 +7,16 @@ public class Vec3DPool { private final int a; private final int b; - private final List c = new ArrayList(); + // CraftBukkit start + // private final List c = new ArrayList(); + private Vec3D freelist = null; + private Vec3D alloclist = null; + private Vec3D freelisthead = null; + private Vec3D alloclisthead = null; + private int total_size = 0; + private int hit; + private int miss; + // CraftBukkit end private int d = 0; private int e = 0; private int f = 0; @@ -17,21 +26,44 @@ public class Vec3DPool { this.b = j; } - public Vec3D create(double d0, double d1, double d2) { + public final Vec3D create(double d0, double d1, double d2) { // CraftBukkit - add final if (this.f == 0) return new Vec3D(d0, d1, d2); // CraftBukkit - don't pool objects indefinitely if thread doesn't adhere to contract Vec3D vec3d; - if (this.d >= this.c.size()) { + if (this.freelist == null) { // CraftBukkit vec3d = new Vec3D(d0, d1, d2); - this.c.add(vec3d); + this.total_size++; // CraftBukkit } else { - vec3d = (Vec3D) this.c.get(this.d); + // CraftBukkit start + vec3d = this.freelist; + this.freelist = vec3d.next; + // CraftBukkit end vec3d.b(d0, d1, d2); } + // CraftBukkit start + if (this.alloclist == null) { + this.alloclisthead = vec3d; + } + vec3d.next = this.alloclist; // add to allocated list + this.alloclist = vec3d; + // CraftBukkit end ++this.d; return vec3d; } + + // CraftBukkit start - offer back vector (can save LOTS of unneeded bloat) - works about 90% of the time + public void release(Vec3D v) { + if (this.alloclist == v) { + this.alloclist = v.next; // Pop off alloc list + // Push on to free list + if (this.freelist == null) this.freelisthead = v; + v.next = this.freelist; + this.freelist = v; + this.d--; + } + } + // CraftBukkit end public void a() { if (this.d > this.e) { @@ -39,14 +71,27 @@ public class Vec3DPool { } // CraftBukkit start - intelligent cache - if ((this.f++ & 0xff) == 0) { - int newSize = this.c.size() - (this.c.size() >> 3); - if (newSize > this.e) { // newSize will be 87.5%, but if we were not in that range, we clear some of the cache - for (int i = this.c.size() - 1; i > newSize; i--) { // Work down from size() to prevent insane array copies - this.c.remove(i); - } + // Take any allocated blocks and put them on free list + if (this.alloclist != null) { + if (this.freelist == null) { + this.freelist = this.alloclist; + this.freelisthead = this.alloclisthead; + } + else { + this.alloclisthead.next = this.freelist; + this.freelist = this.alloclist; + this.freelisthead = this.alloclisthead; + } + this.alloclist = null; + } + if ((this.f++ & 0xff) == 0) { + int newSize = total_size - (total_size >> 3); + if (newSize > this.e) { // newSize will be 87.5%, but if we were not in that range, we clear some of the cache + for (int i = total_size; i > newSize; i--) { + freelist = freelist.next; + } + total_size = newSize; } - this.e = 0; // this.f = 0; // We do not reset to zero; it doubles for a flag } diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index 56c5df059e..ae3dda7367 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -742,9 +742,11 @@ public abstract class World implements IBlockAccess { MovingObjectPosition movingobjectposition1 = block1.a(this, l, i1, j1, vec3d, vec3d1); if (movingobjectposition1 != null) { + Vec3D.a().release(vec3d2); // CraftBukkit return movingobjectposition1; } } + Vec3D.a().release(vec3d2); // CraftBukkit } return null; @@ -1446,6 +1448,7 @@ public abstract class World implements IBlockAccess { entity.motY += vec3d.b * d1; entity.motZ += vec3d.c * d1; } + Vec3D.a().release(vec3d); // CraftBukkit - pop it - we're done return flag; } @@ -1526,6 +1529,7 @@ public abstract class World implements IBlockAccess { int i = 0; int j = 0; + Vec3D vec3d2 = Vec3D.a().create(0, 0, 0); // CraftBukkit for (float f = 0.0F; f <= 1.0F; f = (float) ((double) f + d0)) { for (float f1 = 0.0F; f1 <= 1.0F; f1 = (float) ((double) f1 + d1)) { for (float f2 = 0.0F; f2 <= 1.0F; f2 = (float) ((double) f2 + d2)) { @@ -1533,7 +1537,7 @@ public abstract class World implements IBlockAccess { double d4 = axisalignedbb.b + (axisalignedbb.e - axisalignedbb.b) * (double) f1; double d5 = axisalignedbb.c + (axisalignedbb.f - axisalignedbb.c) * (double) f2; - if (this.a(Vec3D.a().create(d3, d4, d5), vec3d) == null) { + if (this.a(vec3d2.b(d3, d4, d5), vec3d) == null) { // CraftBukkit ++i; } @@ -1541,6 +1545,7 @@ public abstract class World implements IBlockAccess { } } } + Vec3D.a().release(vec3d2); // CraftBukkit return (float) i / (float) j; }