Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-09-08 12:32:53 +02:00
Use FastUtil over Trove for maps/collections to reduce memory usage
This should significantly decrease the amount of RAM being used by Geyser. Previously it was using 300mb - 400mb on average. This has dropped it down to 80mb - 120mb. Ideally I'd like to decrease this value further, but that will require some more work.
Dieser Commit ist enthalten in:
Ursprung
c91e8e1958
Commit
cd17dc5f4c
@ -34,6 +34,8 @@ import com.nukkitx.protocol.bedrock.data.EntityDataDictionary;
|
|||||||
import com.nukkitx.protocol.bedrock.data.EntityFlag;
|
import com.nukkitx.protocol.bedrock.data.EntityFlag;
|
||||||
import com.nukkitx.protocol.bedrock.data.EntityFlags;
|
import com.nukkitx.protocol.bedrock.data.EntityFlags;
|
||||||
import com.nukkitx.protocol.bedrock.packet.*;
|
import com.nukkitx.protocol.bedrock.packet.*;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.connector.console.GeyserLogger;
|
import org.geysermc.connector.console.GeyserLogger;
|
||||||
@ -69,7 +71,7 @@ public class Entity {
|
|||||||
|
|
||||||
protected boolean valid;
|
protected boolean valid;
|
||||||
|
|
||||||
protected Set<Long> passengers = new HashSet<>();
|
protected LongSet passengers = new LongOpenHashSet();
|
||||||
protected Map<AttributeType, Attribute> attributes = new HashMap<>();
|
protected Map<AttributeType, Attribute> attributes = new HashMap<>();
|
||||||
protected EntityDataDictionary metadata = new EntityDataDictionary();
|
protected EntityDataDictionary metadata = new EntityDataDictionary();
|
||||||
|
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
package org.geysermc.connector.network.session.cache;
|
package org.geysermc.connector.network.session.cache;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2LongMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
import org.geysermc.connector.entity.PlayerEntity;
|
import org.geysermc.connector.entity.PlayerEntity;
|
||||||
@ -41,8 +45,8 @@ public class EntityCache {
|
|||||||
private GeyserSession session;
|
private GeyserSession session;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private Map<Long, Entity> entities = new HashMap<>();
|
private Long2ObjectMap<Entity> entities = new Long2ObjectOpenHashMap<>();
|
||||||
private Map<Long, Long> entityIdTranslations = new HashMap<>();
|
private Long2LongMap entityIdTranslations = new Long2LongOpenHashMap();
|
||||||
private Map<UUID, PlayerEntity> playerEntities = new HashMap<>();
|
private Map<UUID, PlayerEntity> playerEntities = new HashMap<>();
|
||||||
private Map<UUID, Long> bossbars = new HashMap<>();
|
private Map<UUID, Long> bossbars = new HashMap<>();
|
||||||
|
|
||||||
@ -62,12 +66,10 @@ public class EntityCache {
|
|||||||
|
|
||||||
public boolean removeEntity(Entity entity, boolean force) {
|
public boolean removeEntity(Entity entity, boolean force) {
|
||||||
if (entity != null && entity.isValid() && (force || entity.despawnEntity(session))) {
|
if (entity != null && entity.isValid() && (force || entity.despawnEntity(session))) {
|
||||||
Long geyserId = entityIdTranslations.remove(entity.getEntityId());
|
long geyserId = entityIdTranslations.remove(entity.getEntityId());
|
||||||
if (geyserId != null) {
|
entities.remove(geyserId);
|
||||||
entities.remove(geyserId);
|
if (entity.is(PlayerEntity.class)) {
|
||||||
if (entity.is(PlayerEntity.class)) {
|
playerEntities.remove(entity.as(PlayerEntity.class).getUuid());
|
||||||
playerEntities.remove(entity.as(PlayerEntity.class).getUuid());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
package org.geysermc.connector.network.session.cache;
|
package org.geysermc.connector.network.session.cache;
|
||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket;
|
import com.nukkitx.protocol.bedrock.packet.ModalFormRequestPacket;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.api.window.FormWindow;
|
import org.geysermc.api.window.FormWindow;
|
||||||
@ -38,7 +40,7 @@ public class WindowCache {
|
|||||||
private GeyserSession session;
|
private GeyserSession session;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private Map<Integer, FormWindow> windows = new HashMap<Integer, FormWindow>();
|
private Int2ObjectMap<FormWindow> windows = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
public WindowCache(GeyserSession session) {
|
public WindowCache(GeyserSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
@ -79,7 +79,7 @@ public class ItemTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ItemEntry getItem(ItemData data) {
|
public ItemEntry getItem(ItemData data) {
|
||||||
for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.valueCollection()) {
|
for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.values()) {
|
||||||
if (itemEntry.getBedrockId() == data.getId() && itemEntry.getBedrockData() == data.getDamage()) {
|
if (itemEntry.getBedrockId() == data.getId() && itemEntry.getBedrockData() == data.getDamage()) {
|
||||||
return itemEntry;
|
return itemEntry;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ import com.nukkitx.nbt.tag.CompoundTag;
|
|||||||
import com.nukkitx.nbt.tag.ListTag;
|
import com.nukkitx.nbt.tag.ListTag;
|
||||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||||
|
|
||||||
import gnu.trove.map.TIntObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.console.GeyserLogger;
|
import org.geysermc.connector.console.GeyserLogger;
|
||||||
import org.geysermc.connector.network.translators.block.BlockEntry;
|
import org.geysermc.connector.network.translators.block.BlockEntry;
|
||||||
@ -23,8 +23,8 @@ public class Toolbox {
|
|||||||
public static final Collection<StartGamePacket.ItemEntry> ITEMS = new ArrayList<>();
|
public static final Collection<StartGamePacket.ItemEntry> ITEMS = new ArrayList<>();
|
||||||
public static ListTag<CompoundTag> BLOCKS;
|
public static ListTag<CompoundTag> BLOCKS;
|
||||||
|
|
||||||
public static final TIntObjectMap<ItemEntry> ITEM_ENTRIES = new TIntObjectHashMap<>();
|
public static final Int2ObjectMap<ItemEntry> ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
|
||||||
public static final TIntObjectMap<BlockEntry> BLOCK_ENTRIES = new TIntObjectHashMap<>();
|
public static final Int2ObjectMap<BlockEntry> BLOCK_ENTRIES = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
InputStream stream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/runtime_block_states.dat");
|
InputStream stream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/runtime_block_states.dat");
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package org.geysermc.connector.world.chunk;
|
package org.geysermc.connector.world.chunk;
|
||||||
|
|
||||||
import com.nukkitx.network.VarInts;
|
import com.nukkitx.network.VarInts;
|
||||||
import gnu.trove.list.array.TIntArrayList;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
import org.geysermc.connector.world.GlobalBlockPalette;
|
import org.geysermc.connector.world.GlobalBlockPalette;
|
||||||
import org.geysermc.connector.world.chunk.bitarray.BitArray;
|
import org.geysermc.connector.world.chunk.bitarray.BitArray;
|
||||||
import org.geysermc.connector.world.chunk.bitarray.BitArrayVersion;
|
import org.geysermc.connector.world.chunk.bitarray.BitArrayVersion;
|
||||||
|
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapted from NukkitX: https://github.com/NukkitX/Nukkit
|
* Adapted from NukkitX: https://github.com/NukkitX/Nukkit
|
||||||
*/
|
*/
|
||||||
@ -14,7 +17,7 @@ public class BlockStorage {
|
|||||||
|
|
||||||
private static final int SIZE = 4096;
|
private static final int SIZE = 4096;
|
||||||
|
|
||||||
private final TIntArrayList palette;
|
private final IntList palette;
|
||||||
private BitArray bitArray;
|
private BitArray bitArray;
|
||||||
|
|
||||||
public BlockStorage() {
|
public BlockStorage() {
|
||||||
@ -23,11 +26,11 @@ public class BlockStorage {
|
|||||||
|
|
||||||
public BlockStorage(BitArrayVersion version) {
|
public BlockStorage(BitArrayVersion version) {
|
||||||
this.bitArray = version.createPalette(SIZE);
|
this.bitArray = version.createPalette(SIZE);
|
||||||
this.palette = new TIntArrayList(16, -1);
|
this.palette = new IntArrayList(16);
|
||||||
this.palette.add(0); // Air is at the start of every palette.
|
this.palette.add(0); // Air is at the start of every palette.
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockStorage(BitArray bitArray, TIntArrayList palette) {
|
private BlockStorage(BitArray bitArray, IntArrayList palette) {
|
||||||
this.palette = palette;
|
this.palette = palette;
|
||||||
this.bitArray = bitArray;
|
this.bitArray = bitArray;
|
||||||
}
|
}
|
||||||
@ -57,10 +60,7 @@ public class BlockStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VarInts.writeInt(buffer, palette.size());
|
VarInts.writeInt(buffer, palette.size());
|
||||||
palette.forEach(id -> {
|
palette.forEach((IntConsumer) id -> VarInts.writeInt(buffer, id));
|
||||||
VarInts.writeInt(buffer, id);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onResize(BitArrayVersion version) {
|
private void onResize(BitArrayVersion version) {
|
||||||
@ -109,6 +109,6 @@ public class BlockStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BlockStorage copy() {
|
public BlockStorage copy() {
|
||||||
return new BlockStorage(this.bitArray.copy(), new TIntArrayList(this.palette));
|
return new BlockStorage(this.bitArray.copy(), new IntArrayList(this.palette));
|
||||||
}
|
}
|
||||||
}
|
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren