Skip to content

Commit 9207f96

Browse files
committed
perf: consolidate level update notifications
1 parent eb9ff30 commit 9207f96

File tree

4 files changed

+81
-13
lines changed

4 files changed

+81
-13
lines changed

c2me-base/src/main/java/com/ishland/c2me/base/common/scheduler/SchedulingManager.java

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import net.minecraft.server.world.ChunkLevels;
77
import net.minecraft.util.math.ChunkPos;
88

9+
import java.util.ArrayDeque;
10+
import java.util.Queue;
911
import java.util.concurrent.ConcurrentHashMap;
1012
import java.util.concurrent.ConcurrentMap;
1113
import java.util.concurrent.Executor;
@@ -30,6 +32,9 @@ protected void rehash(int newN) {
3032
private final int id = COUNTER.getAndIncrement();
3133
private volatile ChunkPos currentSyncLoad = null;
3234

35+
private boolean consolidatingLevelUpdates = false;
36+
private Queue<Runnable> consolidatedLevelUpdates = new ArrayDeque<>();
37+
3338
private final Executor executor;
3439

3540
{
@@ -80,21 +85,52 @@ public Executor positionedExecutor(long pos) {
8085

8186
public void updatePriorityFromLevel(long pos, int level) {
8287
this.executor.execute(() -> {
83-
if (this.getPriorityFromMap(pos) == level) return;
84-
final long stamp = this.prioritiesLock.writeLock();
85-
try {
86-
if (level < MAX_LEVEL) {
87-
this.prioritiesFromLevel.put(pos, level);
88-
} else {
89-
this.prioritiesFromLevel.remove(pos);
90-
}
91-
} finally {
92-
this.prioritiesLock.unlockWrite(stamp);
93-
}
94-
updatePriorityInternal(pos);
88+
updatePriorityFromLevel0(pos, level);
9589
});
9690
}
9791

92+
private void updatePriorityFromLevel0(long pos, int level) {
93+
if (this.getPriorityFromMap(pos) == level) return;
94+
final long stamp = this.prioritiesLock.writeLock();
95+
try {
96+
if (level < MAX_LEVEL) {
97+
this.prioritiesFromLevel.put(pos, level);
98+
} else {
99+
this.prioritiesFromLevel.remove(pos);
100+
}
101+
} finally {
102+
this.prioritiesLock.unlockWrite(stamp);
103+
}
104+
updatePriorityInternal(pos);
105+
}
106+
107+
public void updatePriorityFromLevelOnMain(long pos, int level) {
108+
if (this.consolidatingLevelUpdates) {
109+
this.consolidatedLevelUpdates.add(() -> updatePriorityFromLevel0(pos, level));
110+
} else {
111+
updatePriorityFromLevel(pos, level);
112+
}
113+
}
114+
115+
public void setConsolidatingLevelUpdates(boolean value) {
116+
this.consolidatingLevelUpdates = value;
117+
if (!value) {
118+
if (!this.consolidatedLevelUpdates.isEmpty()) {
119+
Queue<Runnable> runnables = this.consolidatedLevelUpdates;
120+
this.consolidatedLevelUpdates = new ArrayDeque<>();
121+
this.executor.execute(() -> {
122+
for (Runnable runnable : runnables) {
123+
try {
124+
runnable.run();
125+
} catch (Throwable t) {
126+
t.printStackTrace();
127+
}
128+
}
129+
});
130+
}
131+
}
132+
}
133+
98134
private void updatePriorityInternal(long pos) {
99135
final int priority = getPriority(pos);
100136
final FreeableTaskList locks = this.pos2Tasks.get(pos);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.ishland.c2me.base.mixin.scheduler;
2+
3+
import com.ishland.c2me.base.common.scheduler.IVanillaChunkManager;
4+
import com.ishland.c2me.base.common.scheduler.SchedulingManager;
5+
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
6+
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
7+
import net.minecraft.server.world.ChunkLevelManager;
8+
import net.minecraft.server.world.ServerChunkLoadingManager;
9+
import net.minecraft.server.world.ServerChunkManager;
10+
import org.spongepowered.asm.mixin.Final;
11+
import org.spongepowered.asm.mixin.Mixin;
12+
import org.spongepowered.asm.mixin.Shadow;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
15+
@Mixin(ServerChunkManager.class)
16+
public class MixinServerChunkManager {
17+
18+
@Shadow @Final public ServerChunkLoadingManager chunkLoadingManager;
19+
20+
@WrapOperation(method = "updateChunks", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ChunkLevelManager;update(Lnet/minecraft/server/world/ServerChunkLoadingManager;)Z"))
21+
private boolean consolidatePriorityUpdates(ChunkLevelManager instance, ServerChunkLoadingManager chunkLoadingManager, Operation<Boolean> original) {
22+
SchedulingManager schedulingManager = ((IVanillaChunkManager) this.chunkLoadingManager).c2me$getSchedulingManager();
23+
schedulingManager.setConsolidatingLevelUpdates(true);
24+
try {
25+
return original.call(instance, chunkLoadingManager);
26+
} finally {
27+
schedulingManager.setConsolidatingLevelUpdates(false);
28+
}
29+
}
30+
31+
}

c2me-base/src/main/java/com/ishland/c2me/base/mixin/scheduler/MixinThreadedAnvilChunkStorage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class MixinThreadedAnvilChunkStorage implements IVanillaChunkManager {
2222

2323
@Inject(method = "setLevel", at = @At("RETURN"))
2424
private void onUpdateLevel(long pos, int level, ChunkHolder holder, int i, CallbackInfoReturnable<ChunkHolder> cir) {
25-
this.c2me$schedulingManager.updatePriorityFromLevel(pos, level);
25+
this.c2me$schedulingManager.updatePriorityFromLevelOnMain(pos, level);
2626
}
2727

2828
}

c2me-base/src/main/resources/c2me-base.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"access.fapi.IArrayBackedEvent",
5959
"instrumentation.MixinServerChunkManager",
6060
"report.MixinDedicatedServerWatchdog",
61+
"scheduler.MixinServerChunkManager",
6162
"scheduler.MixinThreadedAnvilChunkStorage",
6263
"theinterface.MixinStorageIoWorker",
6364
"util.log4j2shutdownhookisnomore.MixinMain",

0 commit comments

Comments
 (0)