mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-30 04:02:50 +01:00
[Bleeding] Change Vec3DPool to a stack based pool
Avoid overhead of using an ArrayList and resizing it. Also allows for reuse of objects in the pool during the same tick by explicitly releasing them back to the pool. This allows for much better cache performance as well as reduced cache footprint.
This commit is contained in:
parent
d628c886d2
commit
8219081385
3 changed files with 64 additions and 13 deletions
|
@ -6,6 +6,7 @@ public class Vec3D {
|
||||||
public double a;
|
public double a;
|
||||||
public double b;
|
public double b;
|
||||||
public double c;
|
public double c;
|
||||||
|
public Vec3D next; // CraftBukkit
|
||||||
|
|
||||||
public static Vec3D a(double d0, double d1, double d2) {
|
public static Vec3D a(double d0, double d1, double d2) {
|
||||||
return new Vec3D(d0, d1, d2);
|
return new Vec3D(d0, d1, d2);
|
||||||
|
|
|
@ -7,7 +7,16 @@ public class Vec3DPool {
|
||||||
|
|
||||||
private final int a;
|
private final int a;
|
||||||
private final int b;
|
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 d = 0;
|
||||||
private int e = 0;
|
private int e = 0;
|
||||||
private int f = 0;
|
private int f = 0;
|
||||||
|
@ -17,21 +26,44 @@ public class Vec3DPool {
|
||||||
this.b = j;
|
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
|
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;
|
Vec3D vec3d;
|
||||||
|
|
||||||
if (this.d >= this.c.size()) {
|
if (this.freelist == null) { // CraftBukkit
|
||||||
vec3d = new Vec3D(d0, d1, d2);
|
vec3d = new Vec3D(d0, d1, d2);
|
||||||
this.c.add(vec3d);
|
this.total_size++; // CraftBukkit
|
||||||
} else {
|
} else {
|
||||||
vec3d = (Vec3D) this.c.get(this.d);
|
// CraftBukkit start
|
||||||
|
vec3d = this.freelist;
|
||||||
|
this.freelist = vec3d.next;
|
||||||
|
// CraftBukkit end
|
||||||
vec3d.b(d0, d1, d2);
|
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;
|
++this.d;
|
||||||
return vec3d;
|
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() {
|
public void a() {
|
||||||
if (this.d > this.e) {
|
if (this.d > this.e) {
|
||||||
|
@ -39,14 +71,27 @@ public class Vec3DPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CraftBukkit start - intelligent cache
|
// CraftBukkit start - intelligent cache
|
||||||
if ((this.f++ & 0xff) == 0) {
|
// Take any allocated blocks and put them on free list
|
||||||
int newSize = this.c.size() - (this.c.size() >> 3);
|
if (this.alloclist != null) {
|
||||||
if (newSize > this.e) { // newSize will be 87.5%, but if we were not in that range, we clear some of the cache
|
if (this.freelist == null) {
|
||||||
for (int i = this.c.size() - 1; i > newSize; i--) { // Work down from size() to prevent insane array copies
|
this.freelist = this.alloclist;
|
||||||
this.c.remove(i);
|
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.e = 0;
|
||||||
// this.f = 0; // We do not reset to zero; it doubles for a flag
|
// this.f = 0; // We do not reset to zero; it doubles for a flag
|
||||||
}
|
}
|
||||||
|
|
|
@ -742,9 +742,11 @@ public abstract class World implements IBlockAccess {
|
||||||
MovingObjectPosition movingobjectposition1 = block1.a(this, l, i1, j1, vec3d, vec3d1);
|
MovingObjectPosition movingobjectposition1 = block1.a(this, l, i1, j1, vec3d, vec3d1);
|
||||||
|
|
||||||
if (movingobjectposition1 != null) {
|
if (movingobjectposition1 != null) {
|
||||||
|
Vec3D.a().release(vec3d2); // CraftBukkit
|
||||||
return movingobjectposition1;
|
return movingobjectposition1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Vec3D.a().release(vec3d2); // CraftBukkit
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1446,6 +1448,7 @@ public abstract class World implements IBlockAccess {
|
||||||
entity.motY += vec3d.b * d1;
|
entity.motY += vec3d.b * d1;
|
||||||
entity.motZ += vec3d.c * d1;
|
entity.motZ += vec3d.c * d1;
|
||||||
}
|
}
|
||||||
|
Vec3D.a().release(vec3d); // CraftBukkit - pop it - we're done
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
@ -1526,6 +1529,7 @@ public abstract class World implements IBlockAccess {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 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 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 f1 = 0.0F; f1 <= 1.0F; f1 = (float) ((double) f1 + d1)) {
|
||||||
for (float f2 = 0.0F; f2 <= 1.0F; f2 = (float) ((double) f2 + d2)) {
|
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 d4 = axisalignedbb.b + (axisalignedbb.e - axisalignedbb.b) * (double) f1;
|
||||||
double d5 = axisalignedbb.c + (axisalignedbb.f - axisalignedbb.c) * (double) f2;
|
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;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1541,6 +1545,7 @@ public abstract class World implements IBlockAccess {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Vec3D.a().release(vec3d2); // CraftBukkit
|
||||||
|
|
||||||
return (float) i / (float) j;
|
return (float) i / (float) j;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue