mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-27 10:59:16 +00:00
273 lines
11 KiB
Diff
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);
|
|
}
|
|
-
|
|
}
|
|
}
|