3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-16 21:10:30 +01:00

Start optimizing server list ping.

Dieser Commit ist enthalten in:
Andrew Steinborn 2020-10-04 15:30:28 -04:00
Ursprung cb74210cd8
Commit 3bf252cf45
10 geänderte Dateien mit 216 neuen und 39 gelöschten Zeilen

Datei anzeigen

@ -7,10 +7,10 @@ fi
echo "Compiling libdeflate..."
cd libdeflate || exit
CFLAGS="-fPIC -O2" make
CFLAGS="-fPIC -O2 -fomit-frame-pointer" make
cd ..
CFLAGS="-O3 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack"
CFLAGS="-O2 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack -fomit-frame-pointer"
ARCH=$(uname -m)
mkdir -p src/main/resources/linux_$ARCH
gcc $CFLAGS -Ilibdeflate src/main/c/jni_util.c src/main/c/jni_zlib_deflate.c src/main/c/jni_zlib_inflate.c \

Datei anzeigen

@ -63,6 +63,23 @@ public class LibdeflateVelocityCompressor implements VelocityCompressor {
}
}
@Override
public boolean deflateSingle(ByteBuf source, ByteBuf destination) throws DataFormatException {
ensureNotDisposed();
long sourceAddress = source.memoryAddress() + source.readerIndex();
long destinationAddress = destination.memoryAddress() + destination.writerIndex();
int produced = deflate.process(deflateCtx, sourceAddress, source.readableBytes(),
destinationAddress, destination.writableBytes());
if (produced > 0) {
destination.writerIndex(destination.writerIndex() + produced);
return true;
}
return false;
}
private void ensureNotDisposed() {
Preconditions.checkState(!disposed, "Object already disposed");
}

Datei anzeigen

@ -14,4 +14,9 @@ public interface VelocityCompressor extends Disposable, Native {
throws DataFormatException;
void deflate(ByteBuf source, ByteBuf destination) throws DataFormatException;
default boolean deflateSingle(ByteBuf source, ByteBuf destination) throws DataFormatException {
deflate(source, destination);
return true;
}
}

Datei anzeigen

@ -15,6 +15,7 @@ import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.ProxyVersion;
@ -34,8 +35,11 @@ import com.velocitypowered.proxy.plugin.VelocityEventManager;
import com.velocitypowered.proxy.plugin.VelocityPluginManager;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.packet.Chat;
import com.velocitypowered.proxy.protocol.util.FaviconSerializer;
import com.velocitypowered.proxy.protocol.util.ping.FaviconSerializer;
import com.velocitypowered.proxy.protocol.util.GameProfileSerializer;
import com.velocitypowered.proxy.protocol.util.ping.PlayersSerializer;
import com.velocitypowered.proxy.protocol.util.ping.ServerPingSerializer;
import com.velocitypowered.proxy.protocol.util.ping.VersionSerializer;
import com.velocitypowered.proxy.scheduler.VelocityScheduler;
import com.velocitypowered.proxy.server.ServerMap;
import com.velocitypowered.proxy.util.AddressUtil;
@ -77,8 +81,6 @@ import java.util.stream.Collectors;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.asynchttpclient.AsyncHttpClient;
@ -91,20 +93,26 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
private static final Logger logger = LogManager.getLogger(VelocityServer.class);
public static final Gson GENERAL_GSON = new GsonBuilder()
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
.registerTypeAdapter(Favicon.class, FaviconSerializer.INSTANCE)
.registerTypeHierarchyAdapter(GameProfile.class, GameProfileSerializer.INSTANCE)
.create();
private static final Gson PRE_1_16_PING_SERIALIZER = ProtocolUtils
.getJsonChatSerializer(ProtocolVersion.MINECRAFT_1_15_2)
.serializer()
.newBuilder()
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
.registerTypeAdapter(Favicon.class, FaviconSerializer.INSTANCE)
.registerTypeAdapter(ServerPing.class, ServerPingSerializer.INSTANCE)
.registerTypeAdapter(ServerPing.Version.class, VersionSerializer.INSTANCE)
.registerTypeAdapter(ServerPing.Players.class, PlayersSerializer.INSTANCE)
.create();
private static final Gson POST_1_16_PING_SERIALIZER = ProtocolUtils
.getJsonChatSerializer(ProtocolVersion.MINECRAFT_1_16)
.serializer()
.newBuilder()
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
.registerTypeAdapter(Favicon.class, FaviconSerializer.INSTANCE)
.registerTypeAdapter(ServerPing.class, ServerPingSerializer.INSTANCE)
.registerTypeAdapter(ServerPing.Version.class, VersionSerializer.INSTANCE)
.registerTypeAdapter(ServerPing.Players.class, PlayersSerializer.INSTANCE)
.create();
private final ConnectionManager cm;

Datei anzeigen

@ -21,14 +21,20 @@ public class MinecraftCompressEncoder extends MessageToByteEncoder<ByteBuf> {
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
int uncompressed = msg.readableBytes();
if (uncompressed <= threshold) {
// Under the threshold, there is nothing to do.
// Under the threshold, only indicate the message was too small
ProtocolUtils.writeVarInt(out, 0);
out.writeBytes(msg);
} else {
ProtocolUtils.writeVarInt(out, uncompressed);
ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
try {
compressor.deflate(compatibleIn, out);
if (!compressor.deflateSingle(compatibleIn, out)) {
// The packet would have been too big. Clear the output buffer and use an uncompressed
// packet instead.
out.clear();
ProtocolUtils.writeVarInt(out, 0);
out.writeBytes(msg);
}
} finally {
compatibleIn.release();
}

Datei anzeigen

@ -1,29 +0,0 @@
package com.velocitypowered.proxy.protocol.util;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.velocitypowered.api.util.Favicon;
import java.lang.reflect.Type;
public final class FaviconSerializer implements JsonSerializer<Favicon>, JsonDeserializer<Favicon> {
public static final FaviconSerializer INSTANCE = new FaviconSerializer();
private FaviconSerializer() {
}
@Override
public Favicon deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
return new Favicon(json.getAsString());
}
@Override
public JsonElement serialize(Favicon src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getBase64Url());
}
}

Datei anzeigen

@ -0,0 +1,26 @@
package com.velocitypowered.proxy.protocol.util.ping;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.velocitypowered.api.util.Favicon;
import java.io.IOException;
public final class FaviconSerializer extends TypeAdapter<Favicon> {
public static final FaviconSerializer INSTANCE = new FaviconSerializer();
private FaviconSerializer() {
}
@Override
public void write(JsonWriter writer, Favicon favicon) throws IOException {
writer.value(favicon.getBase64Url());
}
@Override
public Favicon read(JsonReader reader) throws IOException {
return new Favicon(reader.nextString());
}
}

Datei anzeigen

@ -0,0 +1,45 @@
package com.velocitypowered.proxy.protocol.util.ping;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import com.velocitypowered.api.proxy.server.ServerPing.Players;
import com.velocitypowered.api.proxy.server.ServerPing.SamplePlayer;
import java.lang.reflect.Type;
import java.util.List;
public class PlayersSerializer implements JsonSerializer<Players>, JsonDeserializer<Players> {
public static final PlayersSerializer INSTANCE = new PlayersSerializer();
private PlayersSerializer() {
}
@Override
public Players deserialize(JsonElement elem, Type type,
JsonDeserializationContext ctx) throws JsonParseException {
JsonObject object = new JsonObject();
int online = object.get("online").getAsInt();
int max = object.get("max").getAsInt();
List<SamplePlayer> sample = ctx.deserialize(object.get("sample"),
new TypeToken<List<SamplePlayer>>() {}.getType());
return new Players(online, max, sample);
}
@Override
public JsonElement serialize(Players players, Type type, JsonSerializationContext ctx) {
JsonObject object = new JsonObject();
object.addProperty("online", players.getOnline());
object.addProperty("max", players.getMax());
object.add("sample", ctx.serialize(players.getSample()));
return object;
}
}

Datei anzeigen

@ -0,0 +1,52 @@
package com.velocitypowered.proxy.protocol.util.ping;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.proxy.server.ServerPing.Players;
import com.velocitypowered.api.proxy.server.ServerPing.Version;
import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.api.util.ModInfo;
import java.lang.reflect.Type;
import net.kyori.adventure.text.Component;
public class ServerPingSerializer implements JsonSerializer<ServerPing>,
JsonDeserializer<ServerPing> {
public static final ServerPingSerializer INSTANCE = new ServerPingSerializer();
private ServerPingSerializer() {
}
@Override
public ServerPing deserialize(JsonElement elem, Type type,
JsonDeserializationContext ctx) throws JsonParseException {
JsonObject object = elem.getAsJsonObject();
Component description = ctx.deserialize(object.get("description"), Component.class);
Version version = ctx.deserialize(object.get("version"), Version.class);
Players players = ctx.deserialize(object.get("players"), Players.class);
Favicon favicon = ctx.deserialize(object.get("favicon"), Favicon.class);
ModInfo modInfo = ctx.deserialize(object.get("modInfo"), ModInfo.class);
return new ServerPing(version, players, description, favicon, modInfo);
}
@Override
public JsonElement serialize(ServerPing ping, Type type,
JsonSerializationContext ctx) {
JsonObject object = new JsonObject();
object.add("description", ctx.serialize(ping.getDescriptionComponent()));
object.add("version", ctx.serialize(ping.getVersion()));
object.add("players", ctx.serialize(ping.getPlayers().orElse(null)));
object.addProperty("favicon", ping.getFavicon().map(Favicon::getBase64Url).orElse(null));
object.add("modInfo", ctx.serialize(ping.getModinfo().orElse(null)));
return object;
}
}

Datei anzeigen

@ -0,0 +1,47 @@
package com.velocitypowered.proxy.protocol.util.ping;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.velocitypowered.api.proxy.server.ServerPing.Version;
import java.io.IOException;
public class VersionSerializer extends TypeAdapter<Version> {
public static final VersionSerializer INSTANCE = new VersionSerializer();
private VersionSerializer() {
}
@Override
public void write(JsonWriter jsonWriter, Version version) throws IOException {
jsonWriter.beginObject();
jsonWriter.name("protocol");
jsonWriter.value(version.getProtocol());
jsonWriter.name("name");
jsonWriter.value(version.getName());
jsonWriter.endObject();
}
@Override
public Version read(JsonReader jsonReader) throws IOException {
jsonReader.beginObject();
String name = "";
int protocol = -1;
for (int i = 0; i < 2; i++) {
String elem = jsonReader.nextName();
if (elem.equals("name")) {
name = jsonReader.nextString();
} else if (elem.equals("protocol")) {
protocol = jsonReader.nextInt();
} else {
throw new IllegalStateException("Invalid version specification.");
}
}
jsonReader.endObject();
return new Version(protocol, name);
}
}