Intern strings and other values

This should reduce memory usage at startup by preventing multiple identicals objects being present in memory.
This commit is contained in:
Camotoy 2021-08-11 20:16:10 -04:00
parent 71e2ec989c
commit 0c5b39f35b
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
4 changed files with 39 additions and 27 deletions

View file

@ -71,6 +71,10 @@
<groupId>com.nukkitx.network</groupId>
<artifactId>raknet</artifactId>
</exclusion>
<exclusion>
<groupId>com.nukkitx</groupId>
<artifactId>nbt</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -85,6 +89,13 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.nukkitx</groupId>
<artifactId>nbt</artifactId>
<!-- Used for key/value interning -->
<version>2.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.nukkitx.fastutil</groupId>
<artifactId>fastutil-int-int-maps</artifactId>

View file

@ -40,7 +40,7 @@ public class NbtRegistryLoader implements RegistryLoader<String, NbtMap> {
@Override
public NbtMap load(String input) {
InputStream stream = FileUtils.getResource(input);
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) {
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream, true, true)) {
return (NbtMap) nbtInputStream.readTag();
} catch (Exception e) {
throw new AssertionError("Failed to load registrations for " + input, e);

View file

@ -107,7 +107,7 @@ public class BlockRegistryPopulator {
for (Map.Entry<String, BiFunction<String, NbtMapBuilder, String>> palette : STATE_MAPPER.entrySet()) {
InputStream stream = FileUtils.getResource(String.format("bedrock/block_palette.%s.nbt", palette.getKey()));
NbtList<NbtMap> blocksTag;
try (NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)))) {
try (NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) {
NbtMap blockPalette = (NbtMap) nbtInputStream.readTag();
blocksTag = (NbtList<NbtMap>) blockPalette.getList("blocks", NbtType.COMPOUND);
} catch (Exception e) {
@ -149,10 +149,10 @@ public class BlockRegistryPopulator {
Map.Entry<String, JsonNode> entry = blocksIterator.next();
String javaId = entry.getKey();
NbtMap blockTag = buildBedrockState(entry.getValue(), stateVersion, stateMapper);
int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(blockTag, -1);
int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(buildBedrockState(entry.getValue(), stateVersion, stateMapper), -1);
if (bedrockRuntimeId == -1) {
throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built compound tag: \n" + blockTag);
throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built NBT tag: \n" +
buildBedrockState(entry.getValue(), stateVersion, stateMapper));
}
switch (javaId) {
@ -182,11 +182,11 @@ public class BlockRegistryPopulator {
// Get the tag needed for non-empty flower pots
if (entry.getValue().get("pottable") != null) {
flowerPotBlocks.put(cleanJavaIdentifier, blockTag);
flowerPotBlocks.put(cleanJavaIdentifier.intern(), blocksTag.get(bedrockRuntimeId));
}
if (!cleanJavaIdentifier.equals(entry.getValue().get("bedrock_identifier").asText())) {
javaIdentifierToBedrockTag.put(cleanJavaIdentifier, blockTag);
javaIdentifierToBedrockTag.put(cleanJavaIdentifier.intern(), blocksTag.get(bedrockRuntimeId));
}
javaToBedrockBlockMap.put(javaRuntimeId, bedrockRuntimeId);
@ -274,7 +274,7 @@ public class BlockRegistryPopulator {
JsonNode pickItemNode = entry.getValue().get("pick_item");
if (pickItemNode != null) {
builder.pickItem(pickItemNode.textValue());
builder.pickItem(pickItemNode.textValue().intern());
}
BlockStateValues.storeBlockStateValues(entry.getKey(), javaRuntimeId, entry.getValue());
@ -284,7 +284,7 @@ public class BlockRegistryPopulator {
if (!cleanIdentifiers.contains(cleanJavaIdentifier)) {
uniqueJavaId++;
cleanIdentifiers.add(cleanJavaIdentifier);
cleanIdentifiers.add(cleanJavaIdentifier.intern());
}
builder.javaIdentifier(javaId);
@ -295,7 +295,7 @@ public class BlockRegistryPopulator {
// Keeping this here since this is currently unchanged between versions
if (!cleanJavaIdentifier.equals(bedrockIdentifier)) {
BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier, bedrockIdentifier);
BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern());
}
if (javaId.startsWith("minecraft:bell[")) {

View file

@ -249,24 +249,25 @@ public class ItemRegistryPopulator {
javaOnlyItems.addAll(palette.getValue().getAdditionalTranslatedItems().keySet());
for (Map.Entry<String, GeyserMappingItem> entry : items.entrySet()) {
String javaIdentifier = entry.getKey().intern();
GeyserMappingItem mappingItem;
String replacementItem = palette.getValue().getAdditionalTranslatedItems().get(entry.getKey());
String replacementItem = palette.getValue().getAdditionalTranslatedItems().get(javaIdentifier);
if (replacementItem != null) {
mappingItem = items.get(replacementItem);
} else {
// This items has a mapping specifically for this version of the game
mappingItem = entry.getValue();
}
if (entry.getKey().equals("minecraft:sculk_sensor") && GeyserConnector.getInstance().getConfig().isExtendedWorldHeight()) {
if (javaIdentifier.equals("minecraft:sculk_sensor") && GeyserConnector.getInstance().getConfig().isExtendedWorldHeight()) {
mappingItem.setBedrockIdentifier("minecraft:sculk_sensor");
}
if (usingFurnaceMinecart && entry.getKey().equals("minecraft:furnace_minecart")) {
if (usingFurnaceMinecart && javaIdentifier.equals("minecraft:furnace_minecart")) {
javaFurnaceMinecartId = itemIndex;
itemIndex++;
continue;
}
String bedrockIdentifier = mappingItem.getBedrockIdentifier();
String bedrockIdentifier = mappingItem.getBedrockIdentifier().intern();
int bedrockId = bedrockIdentifierToId.getInt(bedrockIdentifier);
if (bedrockId == Short.MIN_VALUE) {
throw new RuntimeException("Missing Bedrock ID in mappings: " + bedrockIdentifier);
@ -389,7 +390,7 @@ public class ItemRegistryPopulator {
}
ItemMapping.ItemMappingBuilder mappingBuilder = ItemMapping.builder()
.javaIdentifier(entry.getKey())
.javaIdentifier(javaIdentifier)
.javaId(itemIndex)
.bedrockIdentifier(bedrockIdentifier)
.bedrockId(bedrockId)
@ -399,14 +400,14 @@ public class ItemRegistryPopulator {
if (mappingItem.getToolType() != null) {
if (mappingItem.getToolTier() != null) {
mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType())
.toolTier(mappingItem.getToolTier());
mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType().intern())
.toolTier(mappingItem.getToolTier().intern());
} else {
mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType())
mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType().intern())
.toolTier("");
}
}
if (javaOnlyItems.contains(entry.getKey())) {
if (javaOnlyItems.contains(javaIdentifier)) {
// These items don't exist on Bedrock, so set up a variable that indicates they should have custom names
mappingBuilder = mappingBuilder.translationString((bedrockBlockId != -1 ? "block." : "item.") + entry.getKey().replace(":", "."));
GeyserConnector.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated.");
@ -414,11 +415,11 @@ public class ItemRegistryPopulator {
ItemMapping mapping = mappingBuilder.build();
if (entry.getKey().contains("boat")) {
if (javaIdentifier.contains("boat")) {
boats.add(bedrockId);
} else if (entry.getKey().contains("bucket") && !entry.getKey().contains("milk")) {
} else if (javaIdentifier.contains("bucket") && !javaIdentifier.contains("milk")) {
buckets.add(bedrockId);
} else if (entry.getKey().contains("_carpet") && !entry.getKey().contains("moss")) {
} else if (javaIdentifier.contains("_carpet") && !javaIdentifier.contains("moss")) {
// This should be the numerical order Java sends as an integer value for llamas
carpets.add(ItemData.builder()
.id(mapping.getBedrockId())
@ -426,18 +427,18 @@ public class ItemRegistryPopulator {
.count(1)
.blockRuntimeId(mapping.getBedrockBlockId())
.build());
} else if (entry.getKey().startsWith("minecraft:music_disc_")) {
} else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
// The Java record level event uses the item ID as the "key" to play the record
Registries.RECORDS.register(itemIndex, SoundEvent.valueOf("RECORD_" +
entry.getKey().replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH)));
} else if (entry.getKey().endsWith("_spawn_egg")) {
javaIdentifier.replace("minecraft:music_disc_", "").toUpperCase(Locale.ENGLISH).intern()));
} else if (javaIdentifier.endsWith("_spawn_egg")) {
spawnEggs.add(mapping.getBedrockId());
}
mappings.put(itemIndex, mapping);
identifierToMapping.put(entry.getKey(), mapping);
identifierToMapping.put(javaIdentifier, mapping);
itemNames.add(entry.getKey());
itemNames.add(javaIdentifier);
itemIndex++;
}