Skip to content

Commit 3641c58

Browse files
committed
A lot of changes!
New load-balancing thread manager! This thread manager, based on a load function decided per-thread, dynamically chooses which threads should get their own thread and which should be left to be remapped to run on the main thread. This is currently used for the dimension threading pool; however, it's toggleable via a config option. Moved around a lot of thread management and IMC stuff to its own classes. A lot of miscellaneous changes to a lot of classes to reduce *auto-boxing/unboxing*! Finally fixed LAN servers not properly deconstructing the distance manager when all players other than the host leave. Fixed an issue with distance manager interfering across worlds. The distance manager should now be completely world-independent. This means that a player with a distance thread in one dimension will not interfere with a player in another dimension with their own distance thread, regardless of relative position to each-other (inside the dim coordinates).
1 parent a2733b9 commit 3641c58

25 files changed

+678
-210
lines changed

src/main/java/com/gamma/spool/api/SpoolAPI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ public void registerStatisticReceiver(String modid, Class<? extends IStatisticRe
5252
"Mod " + modid
5353
+ " attempted to register a Spool statistic receiver without the IStatisticReceiver interface.");
5454

55-
FMLInterModComms.sendMessage(modid, "registerStatisticReceiver", statisticReceiverClass.getName());
55+
FMLInterModComms.sendMessage("spool", "registerStatisticReceiver", statisticReceiverClass.getName());
5656
}
5757
}

src/main/java/com/gamma/spool/api/statistics/ICache.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
package com.gamma.spool.api.statistics;
22

3-
import com.gamma.spool.util.caching.CachedItem;
4-
53
public interface ICache {
64

75
void invalidate();
86

9-
CachedItem<?>[] getCacheItems();
7+
ICachedItem<?>[] getCacheItems();
108

119
@SuppressWarnings("SameReturnValue") // Purely because there's only one cache.
1210
String getNameForDebug();
1311

1412
default long calculateSize() {
1513
long size = 0;
16-
for (CachedItem<?> cache : this.getCacheItems()) {
14+
for (ICachedItem<?> cache : this.getCacheItems()) {
1715
if (cache == null) continue;
1816
size += cache.calculateSize();
1917
}

src/main/java/com/gamma/spool/api/statistics/ICachedItem.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ public interface ICachedItem<T> {
55
T getItem();
66

77
void setItem(T item);
8+
9+
long calculateSize();
810
}

src/main/java/com/gamma/spool/commands/CommandSpool.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import com.gamma.spool.config.DistanceThreadingConfig;
1919
import com.gamma.spool.config.ThreadManagerConfig;
2020
import com.gamma.spool.config.ThreadsConfig;
21-
import com.gamma.spool.core.Spool;
21+
import com.gamma.spool.core.SpoolManagerOrchestrator;
2222
import com.gamma.spool.thread.KeyedPoolThreadManager;
2323
import com.gamma.spool.thread.ManagerNames;
2424
import com.gamma.spool.thread.ThreadManager;
@@ -61,7 +61,7 @@ public void processCommand(ICommandSender sender, String[] args) {
6161
if (!ThreadsConfig.isDimensionThreadingEnabled())
6262
throw new CommandException("Dimension threading disabled.");
6363

64-
KeyedPoolThreadManager dimensionManager = (KeyedPoolThreadManager) Spool.REGISTERED_THREAD_MANAGERS
64+
KeyedPoolThreadManager dimensionManager = (KeyedPoolThreadManager) SpoolManagerOrchestrator.REGISTERED_THREAD_MANAGERS
6565
.get(ManagerNames.DIMENSION);
6666

6767
sender.addChatMessage(new ChatComponentText("Thread stats:"));
@@ -94,7 +94,7 @@ public void processCommand(ICommandSender sender, String[] args) {
9494
if (!ThreadsConfig.isDistanceThreadingEnabled())
9595
throw new CommandException("Distance threading disabled.");
9696

97-
KeyedPoolThreadManager distanceManager = (KeyedPoolThreadManager) Spool.REGISTERED_THREAD_MANAGERS
97+
KeyedPoolThreadManager distanceManager = (KeyedPoolThreadManager) SpoolManagerOrchestrator.REGISTERED_THREAD_MANAGERS
9898
.get(ManagerNames.DISTANCE);
9999

100100
sender.addChatMessage(new ChatComponentText("Thread stats:"));
@@ -130,7 +130,7 @@ public void processCommand(ICommandSender sender, String[] args) {
130130
if (!ThreadsConfig.isThreadedChunkLoadingEnabled())
131131
throw new CommandException("Chunk threading disabled.");
132132

133-
ThreadManager chunkLoadingManager = (ThreadManager) Spool.REGISTERED_THREAD_MANAGERS
133+
ThreadManager chunkLoadingManager = (ThreadManager) SpoolManagerOrchestrator.REGISTERED_THREAD_MANAGERS
134134
.get(ManagerNames.CHUNK_LOAD);
135135

136136
sender.addChatMessage(new ChatComponentText("Thread stats:"));
@@ -232,6 +232,16 @@ public void processCommand(ICommandSender sender, String[] args) {
232232
EnumChatFormatting.ITALIC + " allowProcessingDuringSleep: "
233233
+ ThreadManagerConfig.allowProcessingDuringSleep
234234
+ EnumChatFormatting.RESET));
235+
sender.addChatMessage(
236+
new ChatComponentText(
237+
EnumChatFormatting.ITALIC + " useLoadBalancingDimensionThreadManager: "
238+
+ ThreadManagerConfig.useLoadBalancingDimensionThreadManager
239+
+ EnumChatFormatting.RESET));
240+
sender.addChatMessage(
241+
new ChatComponentText(
242+
EnumChatFormatting.ITALIC + " loadBalancerFrequency: "
243+
+ ThreadManagerConfig.loadBalancerFrequency
244+
+ EnumChatFormatting.RESET));
235245
sender.addChatMessage(
236246
new ChatComponentText(
237247
EnumChatFormatting.ITALIC + " enableSpoolWatchdog: "

src/main/java/com/gamma/spool/concurrent/ConcurrentChunk.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.gamma.spool.concurrent;
22

33
import java.util.ArrayList;
4+
import java.util.Arrays;
45
import java.util.Iterator;
56
import java.util.List;
67
import java.util.Random;
@@ -76,7 +77,7 @@ public class ConcurrentChunk extends Chunk implements IAtomic {
7677
public AtomicIntegerArray heightMap = new AtomicIntegerArray(256);
7778
public final AtomicInteger heightMapMinimum = new AtomicInteger(0);
7879

79-
public final AtomicReferenceArray<Boolean> updateSkylightColumns;
80+
public final AtomicReference<boolean[]> updateSkylightColumns;
8081

8182
public final AtomicReferenceArray<ConcurrentExtendedBlockStorage> storageArrays;
8283

@@ -86,10 +87,9 @@ public class ConcurrentChunk extends Chunk implements IAtomic {
8687
public ConcurrentChunk(World p_i1995_1_, int p_i1995_2_, int p_i1995_3_) {
8788
super(p_i1995_1_, p_i1995_2_, p_i1995_3_);
8889
this.queuedLightChecks.set(4096);
89-
this.updateSkylightColumns = new AtomicReferenceArray<>(new Boolean[256]);
90-
for (int i = 0; i < updateSkylightColumns.length(); i++) {
91-
updateSkylightColumns.set(i, false); // Fill the array.
92-
}
90+
this.updateSkylightColumns = new AtomicReference<>(new boolean[256]);
91+
// Fill the array.
92+
Arrays.fill(updateSkylightColumns.get(), false);
9393

9494
for (int i = 0; i < entityLists.length; i++) {
9595
entityLists[i] = ObjectLists.synchronize(new ObjectArrayList<Entity>());
@@ -315,7 +315,7 @@ public void generateSkylightMap() {
315315
* Propagates a given sky-visible block's light value downward and upward to neighboring blocks as necessary.
316316
*/
317317
private void propagateSkylightOcclusion(int p_76595_1_, int p_76595_2_) {
318-
this.updateSkylightColumns.set(p_76595_1_ + p_76595_2_ * 16, true);
318+
this.updateSkylightColumns.get()[p_76595_1_ + p_76595_2_ * 16] = true;
319319
this.isGapLightingUpdated.set(true);
320320
}
321321

@@ -324,12 +324,8 @@ private void recheckGaps(boolean p_150803_1_) {
324324
if (this.worldObj.doChunksNearChunkExist(this.xPosition * 16 + 8, 0, this.zPosition * 16 + 8, 16)) {
325325
for (int i = 0; i < 16; ++i) {
326326
for (int j = 0; j < 16; ++j) {
327-
if (this.updateSkylightColumns.get(i + j * 16)) {
328-
329-
boolean expected;
330-
do {
331-
expected = this.updateSkylightColumns.get(i + j * 16);
332-
} while (expected && !this.updateSkylightColumns.compareAndSet(i + j * 16, expected, false));
327+
if (this.updateSkylightColumns.get()[i + j * 16]) {
328+
this.updateSkylightColumns.get()[i + j * 16] = false;
333329

334330
int k = this.getHeightValue(i, j);
335331
int l = this.xPosition * 16 + i;

src/main/java/com/gamma/spool/concurrent/providers/ConcurrentChunkProviderServer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import com.gamma.spool.concurrent.ConcurrentChunk;
3131
import com.gamma.spool.concurrent.providers.gen.IFullAsync;
3232
import com.gamma.spool.config.ThreadsConfig;
33-
import com.gamma.spool.core.Spool;
33+
import com.gamma.spool.core.SpoolManagerOrchestrator;
3434
import com.gamma.spool.thread.ManagerNames;
3535
import com.gamma.spool.util.concurrent.CompletedFuture;
3636
import com.gamma.spool.util.concurrent.interfaces.IAtomic;
@@ -295,7 +295,7 @@ private Chunk originalLoadChunk1(int x, int z) {
295295
// Load the chunk (includes generating!)
296296
if (!(futureTask instanceof CompletedFuture)) { // Only run the task if it needs to be run. Reasonable, right?
297297
if (ThreadsConfig.isThreadedChunkLoadingEnabled()) {
298-
Spool.REGISTERED_THREAD_MANAGERS.get(ManagerNames.CHUNK_LOAD)
298+
SpoolManagerOrchestrator.REGISTERED_THREAD_MANAGERS.get(ManagerNames.CHUNK_LOAD)
299299
.execute(futureTask);
300300
} else {
301301
futureTask.run();

src/main/java/com/gamma/spool/config/ThreadManagerConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ public class ThreadManagerConfig {
2424
@Config.Name("Drop tasks on timeout?")
2525
public static boolean dropTasksOnTimeout;
2626

27+
@Config.Comment("If the dimension thread manager should use a load-balancing implementation. This can very slightly increase overhead, however it greatly improves performance when the server's dimension count is greater than the pool size.")
28+
@Config.DefaultBoolean(true)
29+
@Config.Name("Use load-balancing dimension thread manager?")
30+
public static boolean useLoadBalancingDimensionThreadManager;
31+
32+
@Config.Comment("How often (every n ticks) the load-balancing pools should re-balance. Lower values lead to slower response times (for rebalancing), potentially causing lag spikes, however higher values increase overhead significantly.")
33+
@Config.DefaultInt(5)
34+
@Config.Name("Load balanced pool frequency")
35+
public static int loadBalancerFrequency;
36+
2737
@Config.Comment("If the managers should optimize lambdas (pulling scoped values) using Consumers. Sometimes increases performance, sometimes doesn't.")
2838
@Config.DefaultBoolean(true)
2939
@Config.Name("Use lambda optimization?")

0 commit comments

Comments
 (0)