Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: FastUtil #168

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions patches/server/0003-Setup-Gradle-project.patch
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ Subject: [PATCH] Setup Gradle project

diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000000000000000000000000000000000000..3938905ca58c3d1cd1db4fa9632637b7a43ff8c5
index 0000000000000000000000000000000000000000..7a4dbe3923dc2a001f57e35fe6a6e94083769c65
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,114 @@
@@ -0,0 +1,116 @@
+plugins {
+ id("pandaspigot.conventions")
+ id("com.github.johnrengelman.shadow") version "7.1.2"
Expand Down Expand Up @@ -112,15 +112,17 @@ index 0000000000000000000000000000000000000000..3938905ca58c3d1cd1db4fa9632637b7
+ )
+ }
+ }
+
+ var jvmargs = listOf("-Xms1G", "-Xmx1G", "-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", "-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4", "-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90", "-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem", "-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs", "-Daikars.new.flags=true")
+ registerRunTask("runShadow") {
+ description = "Spin up a test server from the shadowJar archiveFile"
+ jvmArgs = jvmargs
+ classpath(shadowJar.flatMap { it.archiveFile })
+ }
+
+ registerRunTask("runDev") {
+ description = "Spin up a non-shaded non-relocated test server"
+ classpath = java.sourceSets.main.get().runtimeClasspath
+ jvmArgs = jvmargs
+ mainClass.set("org.bukkit.craftbukkit.Main")
+ }
+}
Expand Down
18 changes: 18 additions & 0 deletions patches/server/0100-add-fastutil.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mechoriet <[email protected]>
Date: Sat, 7 Oct 2023 17:27:39 +0200
Subject: [PATCH] add fastutil


diff --git a/build.gradle.kts b/build.gradle.kts
index 32e86e461d803da6493ac42c173317c2c67ca18b..12283bd6386dc459aebb28484cb1221fabb3db88 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -20,6 +20,7 @@ dependencies {

// Minecraft libraries:
implementation("io.netty:netty-all:4.1.91.Final") // PandaSpigot - Update Netty to 4.1.x
+ implementation("it.unimi.dsi:fastutil:8.5.12") // PandaSpigot - add fastutil
implementation("com.mojang:authlib:1.5.21")
// PandaSpigot start - Update log4j
implementation("org.apache.logging.log4j:log4j-api:2.17.1")
210 changes: 210 additions & 0 deletions patches/server/0101-fastutil-add-ObjectMapList.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mechoriet <[email protected]>
Date: Sat, 7 Oct 2023 17:33:06 +0200
Subject: [PATCH] fastutil - add ObjectMapList


diff --git a/src/main/java/io/papermc/paper/util/maplist/ObjectMapList.java b/src/main/java/io/papermc/paper/util/maplist/ObjectMapList.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9eee73e34cc6ad6f872e8f000775c900a7509c1
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/maplist/ObjectMapList.java
@@ -0,0 +1,198 @@
+package io.papermc.paper.util.maplist;
+
+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.AbstractReferenceList;
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
+import it.unimi.dsi.fastutil.objects.ObjectSpliterator;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * list with O(1) remove & contains
+ * @author Spottedleaf
+ */
+public final class ObjectMapList<T> extends AbstractReferenceList<T> implements Set<T> {
+
+ private final Int2IntOpenHashMap objectToIndex;
+
+ private static final Object[] EMPTY_LIST = new Object[0];
+ private T[] elements = (T[]) EMPTY_LIST;
+ private int count;
+
+ public ObjectMapList() {
+ this(2, 0.8f);
+ }
+
+ public ObjectMapList(int expectedSize, float loadFactor) {
+ this.objectToIndex = new Int2IntOpenHashMap(expectedSize, loadFactor);
+ this.objectToIndex.defaultReturnValue(Integer.MIN_VALUE);
+ }
+
+ @Override
+ public int size() {
+ return this.count;
+ }
+
+ @Override
+ public int indexOf(Object object) {
+ return this.objectToIndex.get(object.hashCode());
+ }
+
+ @Override
+ public int lastIndexOf(Object object) {
+ return super.indexOf(object);
+ }
+
+ @Override
+ public boolean remove(final Object object) {
+ final int index = this.objectToIndex.remove(object.hashCode());
+ if (index == Integer.MIN_VALUE) {
+ return false;
+ }
+
+ // move the obj at the end to this index
+ final int endIndex = --this.count;
+ final T end = this.elements[endIndex];
+ if (index != endIndex) {
+ // not empty after this call
+ this.objectToIndex.put(end.hashCode(), index); // update index
+ }
+ this.elements[index] = end;
+ this.elements[endIndex] = null;
+ return true;
+ }
+
+ @Override
+ public boolean add(final T object) {
+ final int count = this.count;
+ final int currIndex = this.objectToIndex.putIfAbsent(object.hashCode(), count);
+
+ if (currIndex != Integer.MIN_VALUE) {
+ return false; // already in this list
+ }
+
+ T[] list = this.elements;
+ if (list.length == count) {
+ // resize required
+ list = this.elements = Arrays.copyOf(list, (int)Math.max(4L, (long) count << 1)); // overflow results in negative
+ }
+
+ list[count] = object;
+ this.count = count + 1;
+ return true;
+ }
+
+ @Override
+ public void add(final int index, final T object) {
+ final int currIndex = this.objectToIndex.putIfAbsent(object.hashCode(), index);
+
+ if (currIndex != Integer.MIN_VALUE) {
+ return; // already in this list
+ }
+
+ int count = this.count;
+ T[] list = this.elements;
+ if (list.length == count) {
+ // resize required
+ list = this.elements = Arrays.copyOf(list, (int) Math.max(4L, (long) count << 1)); // overflow results in negative
+ }
+
+ System.arraycopy(list, index, list, index + 1, count - index);
+ list[index] = object;
+ this.count = count + 1;
+ }
+
+ @Override
+ public T get(int index) {
+ return this.elements[index];
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.count == 0;
+ }
+
+ @Override
+ public void clear() {
+ this.objectToIndex.clear();
+ Arrays.fill(this.elements, 0, this.count, null);
+ this.count = 0;
+ }
+
+ @Override
+ public Object @NotNull [] toArray() {
+ return Arrays.copyOf(this.elements, this.count);
+ }
+
+ @Override
+ public ObjectSpliterator<T> spliterator() {
+ return super.spliterator();
+ }
+
+ @Override
+ public @NotNull ObjectListIterator<T> iterator() {
+ return new Iterator(0);
+ }
+
+ private class Iterator implements ObjectListIterator<T> {
+
+ T lastRet;
+ int current;
+
+ Iterator(int index) {
+ current = index;
+ }
+
+ @Override
+ public int nextIndex() {
+ return this.current + 1;
+ }
+
+ @Override
+ public int previousIndex() {
+ return this.current - 1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return this.current < ObjectMapList.this.count;
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return this.current > 0;
+ }
+
+ @Override
+ public T next() {
+ if (this.current >= ObjectMapList.this.count) {
+ throw new NoSuchElementException();
+ }
+ return this.lastRet = ObjectMapList.this.elements[this.current++];
+ }
+
+ @Override
+ public T previous() {
+ if (this.current < 0) {
+ throw new NoSuchElementException();
+ }
+ return this.lastRet = ObjectMapList.this.elements[--this.current];
+ }
+
+ @Override
+ public void remove() {
+ final T lastRet = this.lastRet;
+
+ if (lastRet == null) {
+ throw new IllegalStateException();
+ }
+ this.lastRet = null;
+
+ ObjectMapList.this.remove(lastRet);
+ --this.current;
+ }
+ }
+}
32 changes: 32 additions & 0 deletions patches/server/0102-fastutil-EntityTracker.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mechoriet <[email protected]>
Date: Sat, 7 Oct 2023 17:33:39 +0200
Subject: [PATCH] fastutil - EntityTracker


diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java
index cb72b36725927272fddfdad929b268a7b06140ac..d3afb43259dc34a63c561266efbf7e5050d9d213 100644
--- a/src/main/java/net/minecraft/server/EntityTracker.java
+++ b/src/main/java/net/minecraft/server/EntityTracker.java
@@ -13,7 +13,7 @@ public class EntityTracker {

private static final Logger a = LogManager.getLogger();
private final WorldServer world;
- private Set<EntityTrackerEntry> c = Sets.newHashSet();
+ private Set<EntityTrackerEntry> c = new io.papermc.paper.util.maplist.ObjectMapList<>(); // PandaSpigot - FastUtil - ObjectMapList
public IntHashMap<EntityTrackerEntry> trackedEntities = new IntHashMap();
private int e;

diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
index 0b90b6f30ea09fb117281d5ddd2fc752d2c139b5..108043d6460374d64a6c1fcfb9e1aab5a4024733 100644
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
@@ -42,7 +42,7 @@ public class EntityTrackerEntry {
// PaperSpigot start
// Replace trackedPlayers Set with a Map. The value is true until the player receives
// their first update (which is forced to have absolute coordinates), false afterward.
- public java.util.Map<EntityPlayer, Boolean> trackedPlayerMap = new java.util.HashMap<EntityPlayer, Boolean>();
+ public java.util.Map<EntityPlayer, Boolean> trackedPlayerMap = new it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap<>(); // PandaSpigot - HashMap -> Reference2BooleanOpenHashMap
public Set<EntityPlayer> trackedPlayers = trackedPlayerMap.keySet();
// PaperSpigot end

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mechoriet <[email protected]>
Date: Sat, 7 Oct 2023 17:34:37 +0200
Subject: [PATCH] fastutil - use ObjectMapList in Chunk EntitySlices


diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 3cb8d99311e2fa9a4a1173f6ef9e8dee957b20fa..4107f2ab945cc1f1ae428493341f5c65f1b56daa 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -146,7 +146,7 @@ public class Chunk {
this.heightMap = new int[256];

for (int k = 0; k < this.entitySlices.length; ++k) {
- this.entitySlices[k] = new org.bukkit.craftbukkit.util.UnsafeList(); // Spigot
+ this.entitySlices[k] = new io.papermc.paper.util.maplist.ObjectMapList<>(); // PandaSpigot - UnsafeList -> ObjectMapList
}

Arrays.fill(this.f, -999);
37 changes: 37 additions & 0 deletions patches/server/0104-fastutil-PlayerChunkMap.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mechoriet <[email protected]>
Date: Sat, 7 Oct 2023 17:51:33 +0200
Subject: [PATCH] fastutil - PlayerChunkMap


diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 696edfe83aa6c75deaaa59cc10818dbf261cc5a9..600c75e86db444b1f31e245a729d22365d5b222b 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -19,7 +19,7 @@ public class PlayerChunkMap {

private static final Logger a = LogManager.getLogger();
private final WorldServer world;
- private final List<EntityPlayer> managedPlayers = Lists.newArrayList();
+ private final List<EntityPlayer> managedPlayers = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); // PandaSpigot - ArrayList -> ObjectArrayList
private final LongHashMap<PlayerChunkMap.PlayerChunk> d = new LongHashMap();
private final Queue<PlayerChunkMap.PlayerChunk> e = new java.util.concurrent.ConcurrentLinkedQueue<PlayerChunkMap.PlayerChunk>(); // CraftBukkit ArrayList -> ConcurrentLinkedQueue
private final Queue<PlayerChunkMap.PlayerChunk> f = new java.util.concurrent.ConcurrentLinkedQueue<PlayerChunkMap.PlayerChunk>(); // CraftBukkit ArrayList -> ConcurrentLinkedQueue
@@ -351,7 +351,7 @@ public class PlayerChunkMap {

class PlayerChunk {

- private final List<EntityPlayer> b = Lists.newArrayList();
+ private final List<EntityPlayer> b = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); // PandaSpigot - ArrayList -> ObjectArrayList
private final ChunkCoordIntPair location;
private short[] dirtyBlocks = new short[64];
private int dirtyCount;
@@ -359,7 +359,7 @@ public class PlayerChunkMap {
private long g;

// CraftBukkit start - add fields
- private final HashMap<EntityPlayer, Runnable> players = new HashMap<EntityPlayer, Runnable>();
+ private final java.util.Map<EntityPlayer, Runnable> players = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // Pandaspigot - HashMap -> Object2ObjectOpenHashMAp
private boolean loaded = false;
private Runnable loadedRunnable = new Runnable() {
public void run() {
30 changes: 30 additions & 0 deletions patches/server/0105-fastutil-World.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mechoriet <[email protected]>
Date: Sat, 7 Oct 2023 20:52:52 +0200
Subject: [PATCH] fastutil - World


diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 38ebe35f6fa434103b52e86262c7f4cc32d486e3..599b496acfd7ba727a4948ff18ada7614bb74e08 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -36,7 +36,7 @@ public abstract class World implements IBlockAccess {
private int a = 63;
protected boolean e;
// Spigot start - guard entity list from removals
- public final List<Entity> entityList = new java.util.ArrayList<Entity>()
+ public final List<Entity> entityList = new it.unimi.dsi.fastutil.objects.ObjectArrayList<Entity>() // PandaSpigot ArrayList -> ObjectArrayList
{
@Override
public Entity remove(int index)
@@ -66,8 +66,8 @@ public abstract class World implements IBlockAccess {
public final List<TileEntity> tileEntityList = Lists.newArrayList();
private final List<TileEntity> b = Lists.newArrayList();
private final Set<TileEntity> c = Sets.newHashSet(); // Paper
- public final List<EntityHuman> players = Lists.newArrayList();
- public final List<Entity> k = Lists.newArrayList();
+ public final List<EntityHuman> players = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); // PandaSpigot - ArrayList -> ObjectArrayList
+ public final List<Entity> k = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); // PandaSpigot - ArrayList -> ObjectArrayList
protected final IntHashMap<Entity> entitiesById = new IntHashMap();
private long d = 16777215L;
private int I;
Loading