Skip to content

Commit dcd7847

Browse files
committed
Improve server tick loop
See Tuinity/Moonrise@0b842a9
1 parent 21b4930 commit dcd7847

File tree

10 files changed

+1120
-38
lines changed

10 files changed

+1120
-38
lines changed

paper-server/patches/features/0032-fixup-paper-File-Patches.patch

Lines changed: 485 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
3+
Date: Sat, 4 Oct 2025 11:13:55 -0700
4+
Subject: [PATCH] fixup! Moonrise optimisation patches
5+
6+
7+
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
8+
index 80f13315e8c7c0e3c82ab98f92387f56bb3b6481..e03faa94df6c77ab4f3f5d9ffe107220387a0dde 100644
9+
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
10+
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java
11+
@@ -1472,6 +1472,11 @@ public final class ChunkHolderManager {
12+
13+
boolean ret = false;
14+
15+
+ if (pendingFullLoadUpdate.isEmpty()) {
16+
+ // avoid allocating changedFullStatus
17+
+ return ret;
18+
+ }
19+
+
20+
final List<NewChunkHolder> changedFullStatus = new ArrayList<>();
21+
22+
NewChunkHolder holder;
23+
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java
24+
index 57f11ed1c8dfe7a10fddc53bcd2abc8cac29b2f4..c47e77ceb15948cbd4a2a370738843c02542f6c1 100644
25+
--- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java
26+
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java
27+
@@ -338,6 +338,17 @@ public final class ChunkTaskScheduler {
28+
return this.mainThreadExecutor.executeTask();
29+
}
30+
31+
+ // run only tasks queued before this function was invoked
32+
+ public void executeAllRecentlyQueuedMainThreadTasks() {
33+
+ // note: order of retrieval is important to avoid race conditions
34+
+ final long executed = this.mainThreadExecutor.getTotalTasksExecuted();
35+
+ final long scheduled = this.mainThreadExecutor.getTotalTasksScheduled();
36+
+
37+
+ final long left = scheduled - executed;
38+
+ // may execute more tasks than expected due to recursion
39+
+ for (long i = 0; i < left && this.mainThreadExecutor.executeTask(); ++i);
40+
+ }
41+
+
42+
public void raisePriority(final int x, final int z, final Priority priority) {
43+
this.chunkHolderManager.raisePriority(x, z, priority);
44+
}
45+
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
46+
index 201e80364daeb02b5aed8327eef5140053b00aa0..20efafc39eb219158c5dc126f527cc009fe15b15 100644
47+
--- a/net/minecraft/server/MinecraftServer.java
48+
+++ b/net/minecraft/server/MinecraftServer.java
49+
@@ -1126,16 +1126,31 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
50+
// execute small amounts of other tasks just in case the number of tasks we are
51+
// draining is large - chunk system and packet processing may be latency sensitive
52+
53+
- // TODO - Chunk System mid-tick
54+
+ ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this).moonrise$executeMidTickTasks(); // Paper - rewrite chunk system
55+
this.packetProcessor.executeSinglePacket();
56+
}
57+
profiler.popPush("moonrise:run_all_packets");
58+
while (this.packetProcessor.executeSinglePacket()) {
59+
// execute possibly latency sensitive chunk system tasks (see above)
60+
- // TODO - Chunk System mid-tick
61+
+ ((ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer)this).moonrise$executeMidTickTasks(); // Paper - rewrite chunk system
62+
}
63+
profiler.popPush("moonrise:run_all_chunk");
64+
- // TODO - Chunk System tasks
65+
+ // Paper start - rewrite chunk system
66+
+ for (final ServerLevel world : this.getAllLevels()) {
67+
+ profiler.push(world.toString() + " " + world.dimension().location()); // keep same formatting from regular tick, see tickChildren
68+
+
69+
+ // note: legacy tasks may expect a distance manager update
70+
+ profiler.push("moonrise:distance_manager_update");
71+
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates();
72+
+ profiler.popPush("moonrise:legacy_chunk_tasks");
73+
+ world.getChunkSource().mainThreadProcessor.executeAllRecentInternalTasks();
74+
+ profiler.popPush("moonrise:chunk_system_tasks");
75+
+ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)world).moonrise$getChunkTaskScheduler().executeAllRecentlyQueuedMainThreadTasks();
76+
+ profiler.pop();
77+
+
78+
+ profiler.pop(); // world name
79+
+ }
80+
+ // Paper end - rewrite chunk system
81+
profiler.pop(); // moonrise:run_all_chunk
82+
profiler.pop(); // moonrise:run_all_tasks
83+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
3+
Date: Sat, 4 Oct 2025 11:15:18 -0700
4+
Subject: [PATCH] fixup! paper File Patches
5+
6+
7+
diff --git a/net/minecraft/util/thread/BlockableEventLoop.java b/net/minecraft/util/thread/BlockableEventLoop.java
8+
index 9407433c431fb4e945a9db1ebd572b0764f47841..ef29b33db3a665621f35a7480892c65fd9045a5a 100644
9+
--- a/net/minecraft/util/thread/BlockableEventLoop.java
10+
+++ b/net/minecraft/util/thread/BlockableEventLoop.java
11+
@@ -33,6 +33,23 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
12+
MetricsRegistry.INSTANCE.add(this);
13+
}
14+
15+
+ // Paper start
16+
+ public final void executeAllRecentInternalTasks() {
17+
+ final int pending = this.pendingRunnables.size();
18+
+
19+
+ // note: due to possible recursive execution, we may execute more tasks than we want to
20+
+
21+
+ for (int i = 0; i < pending; ++i) {
22+
+ final R run = this.pendingRunnables.poll();
23+
+ if (run == null) {
24+
+ // recursion
25+
+ break;
26+
+ }
27+
+ this.doRunTask(run);
28+
+ }
29+
+ }
30+
+ // Paper end
31+
+
32+
protected abstract boolean shouldRun(R runnable);
33+
34+
public boolean isSameThread() {
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package ca.spottedleaf.moonrise.common.time;
2+
3+
4+
/**
5+
* A Schedule is an object that can be used to maintain a periodic schedule for an event of interest.
6+
*/
7+
public final class Schedule {
8+
9+
private long lastPeriod;
10+
11+
/**
12+
* Initialises a schedule with the provided period.
13+
* @param firstPeriod The last time an event of interest occurred.
14+
* @see #setLastPeriod(long)
15+
*/
16+
public Schedule(final long firstPeriod) {
17+
this.lastPeriod = firstPeriod;
18+
}
19+
20+
/**
21+
* Updates the last period to the specified value. This call sets the last "time" the event
22+
* of interest took place at. Thus, the value returned by {@link #getDeadline(long)} is
23+
* the provided time plus the period length provided to {@code getDeadline}.
24+
* @param value The value to set the last period to.
25+
*/
26+
public void setLastPeriod(final long value) {
27+
this.lastPeriod = value;
28+
}
29+
30+
/**
31+
* Returns the last time the event of interest should have taken place.
32+
*/
33+
public long getLastPeriod() {
34+
return this.lastPeriod;
35+
}
36+
37+
/**
38+
* Returns the number of times the event of interest should have taken place between the last
39+
* period and the provided time given the period between each event.
40+
* @param periodLength The length of the period between events in ns.
41+
* @param time The provided time.
42+
*/
43+
public long getPeriodsAhead(final long periodLength, final long time) {
44+
final long difference = time - this.lastPeriod;
45+
final long ret = Math.abs(difference) / periodLength;
46+
return difference >= 0 ? ret : -ret;
47+
}
48+
49+
/**
50+
* Returns the next starting deadline for the event of interest to take place,
51+
* given the provided period length.
52+
* @param periodLength The provided period length.
53+
*/
54+
public long getDeadline(final long periodLength) {
55+
return this.lastPeriod + periodLength;
56+
}
57+
58+
/**
59+
* Adjusts the last period so that the next starting deadline returned is the next period specified,
60+
* given the provided period length.
61+
* @param nextPeriod The specified next starting deadline.
62+
* @param periodLength The specified period length.
63+
*/
64+
public void setNextPeriod(final long nextPeriod, final long periodLength) {
65+
this.lastPeriod = nextPeriod - periodLength;
66+
}
67+
68+
/**
69+
* Increases the last period by the specified number of periods and period length.
70+
* The specified number of periods may be < 0, in which case the last period
71+
* will decrease.
72+
* @param periods The specified number of periods.
73+
* @param periodLength The specified period length.
74+
*/
75+
public void advanceBy(final long periods, final long periodLength) {
76+
this.lastPeriod += periods * periodLength;
77+
}
78+
79+
/**
80+
* Sets the last period so that it is the specified number of periods ahead
81+
* given the specified time and period length.
82+
* @param periodsToBeAhead Specified number of periods to be ahead by.
83+
* @param periodLength The specified period length.
84+
* @param time The specified time.
85+
*/
86+
public void setPeriodsAhead(final long periodsToBeAhead, final long periodLength, final long time) {
87+
final long periodsAhead = this.getPeriodsAhead(periodLength, time);
88+
final long periodsToAdd = periodsToBeAhead - periodsAhead;
89+
90+
this.lastPeriod -= periodsToAdd * periodLength;
91+
}
92+
}

0 commit comments

Comments
 (0)