mirror of
https://github.com/SparklyPower/SparklyPaper.git
synced 2025-12-23 08:59:19 +00:00
57 lines
3.9 KiB
Diff
57 lines
3.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: MrPowerGamerBR <git@mrpowergamerbr.com>
|
|
Date: Sun, 19 Nov 2023 12:35:16 -0300
|
|
Subject: [PATCH] Skip EntityScheduler's executeTick checks if there isn't any
|
|
tasks to be run
|
|
|
|
On each tick, Paper runs EntityScheduler's executeTick of each entity. This is a bit expensive, due to ArrayDeque's size() call because it ain't a simple "get the current queue size" function, and due to the thread checks.
|
|
|
|
To avoid the hefty ArrayDeque's size() call, we check if we *really* need to execute the executeTick, by checking if currentlyExecuting is not empty or if oneTimeDelayed is not empty.
|
|
|
|
Most entities won't have any scheduled tasks, so this is a nice performance bonus. These optimizations, however, wouldn't work in a Folia environment, but because in SparklyPaper executeTick is always executed on the main thread, it ain't an issue for us (yay).
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
|
|
index 62484ebf4550b05182f693a3180bbac5d5fd906d..4af6652edc0651ab8ad28a738055d407451e49bf 100644
|
|
--- a/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
|
|
+++ b/src/main/java/io/papermc/paper/threadedregions/EntityScheduler.java
|
|
@@ -45,6 +45,7 @@ public final class EntityScheduler {
|
|
private final Long2ObjectOpenHashMap<List<ScheduledTask>> oneTimeDelayed = new Long2ObjectOpenHashMap<>();
|
|
|
|
private final ArrayDeque<ScheduledTask> currentlyExecuting = new ArrayDeque<>();
|
|
+ private boolean hasScheduledTasks = false; // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
|
|
|
public EntityScheduler(final CraftEntity entity) {
|
|
this.entity = Validate.notNull(entity);
|
|
@@ -124,6 +125,7 @@ public final class EntityScheduler {
|
|
if (this.tickCount == RETIRED_TICK_COUNT) {
|
|
return false;
|
|
}
|
|
+ hasScheduledTasks = true; // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
|
this.oneTimeDelayed.computeIfAbsent(this.tickCount + Math.max(1L, delay), (final long keyInMap) -> {
|
|
return new ArrayList<>();
|
|
}).add(task);
|
|
@@ -138,6 +140,23 @@ public final class EntityScheduler {
|
|
* @throws IllegalStateException If the scheduler is retired.
|
|
*/
|
|
public void executeTick() {
|
|
+ // SparklyPaper start - skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
|
+ // This wouldn't work on a multithreaded environment like Folia!!! But because the executeTick is always executed on the
|
|
+ // main thread, we don't need to care about concurrency
|
|
+ // First, we use a simple boolean check here
|
|
+ // Yeah, this sounds dumb but, after benchmarking, it seems like a simple boolean check like this is actually more performant than calling both is empty checks
|
|
+ // So first we check if the EntityScheduler has any scheduled tasks
|
|
+ // If it doesn't, then we skip all checks entirely
|
|
+ // We don't even need to update the tick count because the tick count is actually relative to this scheduler, not bound to the global current tick, so it isn't a big deal if we don't update the tick count, as long
|
|
+ // as there isn't any pending tasks
|
|
+ if (!this.hasScheduledTasks)
|
|
+ return;
|
|
+ // We do have scheduled tasks then... but do we *really* have scheduled tasks tho?
|
|
+ if (this.currentlyExecuting.isEmpty() && this.oneTimeDelayed.isEmpty()) { // Check if we have any pending tasks and, if not, skip!
|
|
+ this.hasScheduledTasks = false; // We don't! Bye bye!!
|
|
+ return;
|
|
+ }
|
|
+ // SparklyPaper end
|
|
final Entity thisEntity = this.entity.getHandleRaw();
|
|
|
|
TickThread.ensureTickThread(thisEntity, "May not tick entity scheduler asynchronously");
|