9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-27 10:59:16 +00:00
Files
Leaf/patches/server/0063-Hearse-Multithreaded-tracker.patch
2023-01-27 08:39:13 -05:00

273 lines
11 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: wangxyper <wangxyper@163.com>
Date: Wed, 18 Jan 2023 14:39:00 +0800
Subject: [PATCH] Hearse: Multithreaded tracker
Original license: MIT
Original project: https://github.com/Era4FunMC/Hearse
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index dfb747eba6bf7088af0ff400da169de00a076365..0f18f7ce182e35ee6f3f385553e1bdb5ee4ad587 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1,5 +1,7 @@
package net.minecraft.server.level;
+import co.earthme.hearse.concurrent.WorkerThreadPoolExecutor;
+import co.earthme.hearse.concurrent.threadfactory.DefaultWorkerFactory;
import com.google.common.collect.*;
import com.google.common.collect.ImmutableList.Builder;
import com.google.gson.JsonElement;
@@ -13,10 +15,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.*;
-import it.unimi.dsi.fastutil.objects.ObjectIterator;
-import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
-import it.unimi.dsi.fastutil.objects.ReferenceSet;
-import it.unimi.dsi.fastutil.objects.ReferenceSets;
+import it.unimi.dsi.fastutil.objects.*;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
@@ -61,10 +60,7 @@ import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
import java.util.*;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.Executor;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.*;
@@ -1194,78 +1190,64 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
entity.tracker = null; // Paper - We're no longer tracked
}
+ private final Executor asyncTrackWorker = new WorkerThreadPoolExecutor(
+ 0,
+ 2,
+ 5L,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<>(),
+ new DefaultWorkerFactory("tracker-async"));
+ private final Executor concurrentTrackWorker = new WorkerThreadPoolExecutor(
+ Runtime.getRuntime().availableProcessors(),
+ Runtime.getRuntime().availableProcessors(),
+ 5L,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<>(),
+ new DefaultWorkerFactory("tracker-concurrent"));
+
+ private final AtomicInteger totalRunning = new AtomicInteger();
+
// Paper start - optimised tracker
private final void processTrackQueue() {
- //this.level.timings.tracker1.startTiming(); // Purpur
- try {
- for (TrackedEntity tracker : this.entityMap.values()) {
- // update tracker entry
- tracker.updatePlayers(tracker.entity.getPlayersInTrackRange());
- }
- } finally {
- //this.level.timings.tracker1.stopTiming(); // Purpur
+ if(this.totalRunning.get() > 0){
+ return;
}
+ this.totalRunning.set(2);
+
+ this.asyncTrackWorker.execute(()->{
+ //this.level.timings.tracker1.startTiming(); // Purpur
+ try {
+ CompletableFuture.allOf(this.entityMap.values()
+ .stream()
+ .map(tracker -> CompletableFuture.runAsync(()->{
+ tracker.updatePlayers(tracker.entity.getPlayersInTrackRange());
+ },this.concurrentTrackWorker))
+ .toArray(CompletableFuture[]::new)).join();
+ } finally {
+ //this.level.timings.tracker1.stopTiming(); // Purpur
+ this.totalRunning.getAndDecrement();
+ }
+ });
- //this.level.timings.tracker2.startTiming(); // Purpur
- try {
- for (TrackedEntity tracker : this.entityMap.values()) {
- tracker.serverEntity.sendChanges();
+ this.asyncTrackWorker.execute(()->{
+ //this.level.timings.tracker2.startTiming(); // Purpur
+ try {
+ for (TrackedEntity tracker : this.entityMap.values()) {
+ tracker.serverEntity.sendChanges();
+ }
+ } finally {
+ //this.level.timings.tracker2.stopTiming(); // Purpur
+ this.totalRunning.getAndDecrement();
}
- } finally {
- //this.level.timings.tracker2.stopTiming(); // Purpur
- }
+ });
}
// Paper end - optimised tracker
protected void tick() {
// Paper start - optimized tracker
- if (true) {
- this.processTrackQueue();
- return;
- }
+ this.processTrackQueue();
// Paper end - optimized tracker
- List<ServerPlayer> list = Lists.newArrayList();
- List<ServerPlayer> list1 = this.level.players();
- Iterator objectiterator = this.entityMap.values().iterator();
- //level.timings.tracker1.startTiming(); // Paper // Purpur
-
- ChunkMap.TrackedEntity playerchunkmap_entitytracker;
-
- while (objectiterator.hasNext()) {
- playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next();
- SectionPos sectionposition = playerchunkmap_entitytracker.lastSectionPos;
- SectionPos sectionposition1 = SectionPos.of((EntityAccess) playerchunkmap_entitytracker.entity);
- boolean flag = !Objects.equals(sectionposition, sectionposition1);
-
- if (flag) {
- playerchunkmap_entitytracker.updatePlayers(list1);
- Entity entity = playerchunkmap_entitytracker.entity;
-
- if (entity instanceof ServerPlayer) {
- list.add((ServerPlayer) entity);
- }
-
- playerchunkmap_entitytracker.lastSectionPos = sectionposition1;
- }
-
- if (flag || this.distanceManager.inEntityTickingRange(sectionposition1.chunk().toLong())) {
- playerchunkmap_entitytracker.serverEntity.sendChanges();
- }
- }
- //level.timings.tracker1.stopTiming(); // Paper // Purpur
-
- if (!list.isEmpty()) {
- objectiterator = this.entityMap.values().iterator();
-
- //level.timings.tracker2.startTiming(); // Paper // Purpur
- while (objectiterator.hasNext()) {
- playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next();
- playerchunkmap_entitytracker.updatePlayers(list);
- }
- //level.timings.tracker2.stopTiming(); // Paper // Purpur
- }
-
}
public void broadcast(Entity entity, Packet<?> packet) {
@@ -1446,7 +1428,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
final Entity entity;
private final int range;
SectionPos lastSectionPos;
- public final Set<ServerPlayerConnection> seenBy = new ReferenceOpenHashSet<>(); // Paper - optimise map impl
+ public final Set<ServerPlayerConnection> seenBy = ReferenceSets.synchronize(new ReferenceOpenHashSet<>()); // Paper - optimise map impl //Hearse - multithread tracker
public TrackedEntity(Entity entity, int i, int j, boolean flag) {
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit
@@ -1464,12 +1446,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (newTrackerCandidates != null) {
Object[] rawData = newTrackerCandidates.getBackingSet();
- for (int i = 0, len = rawData.length; i < len; ++i) {
- Object raw = rawData[i];
+ for (Object raw : rawData) {
if (!(raw instanceof ServerPlayer)) {
continue;
}
- ServerPlayer player = (ServerPlayer)raw;
+ ServerPlayer player = (ServerPlayer) raw;
this.updatePlayer(player);
}
}
@@ -1500,14 +1481,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void broadcast(Packet<?> packet) {
- Iterator iterator = this.seenBy.iterator();
-
- while (iterator.hasNext()) {
- ServerPlayerConnection serverplayerconnection = (ServerPlayerConnection) iterator.next();
-
+ for (ServerPlayerConnection serverplayerconnection : this.seenBy) {
serverplayerconnection.send(packet);
}
-
}
public void broadcastAndSend(Packet<?> packet) {
@@ -1519,14 +1495,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
public void broadcastRemoved() {
- Iterator iterator = this.seenBy.iterator();
-
- while (iterator.hasNext()) {
- ServerPlayerConnection serverplayerconnection = (ServerPlayerConnection) iterator.next();
-
+ for (ServerPlayerConnection serverplayerconnection : this.seenBy) {
this.serverEntity.removePairing(serverplayerconnection.getPlayer());
}
-
}
public void removePlayer(ServerPlayer player) {
@@ -1534,7 +1505,6 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
}
-
}
public void updatePlayer(ServerPlayer player) {
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 50cf4d200bc2892f2140c9929193b4b20ad2bd17..afccc8e6d6a6f8d324a58570c7c2245544516e7b 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -3,14 +3,12 @@ package net.minecraft.server.level;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Pair;
import com.mojang.logging.LogUtils;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+
+import java.util.*;
import java.util.function.Consumer;
import javax.annotation.Nullable;
+
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
@@ -373,7 +371,7 @@ public class ServerEntity {
}
if (this.entity instanceof LivingEntity) {
- Set<AttributeInstance> set = ((LivingEntity) this.entity).getAttributes().getDirtyAttributes();
+ List<AttributeInstance> set = new ArrayList<>(((LivingEntity) this.entity).getAttributes().getDirtyAttributes());
if (!set.isEmpty()) {
// CraftBukkit start - Send scaled max health
@@ -394,6 +392,5 @@ public class ServerEntity {
if (this.entity instanceof ServerPlayer) {
((ServerPlayer) this.entity).connection.send(packet);
}
-
}
}