BlockTranslator: cut memory usage in half

this was achieved by storing binary representations of the blockstates, rather than the original BlockStateData.

Due to the insane object:data ratio of Tag objects (40:1 for ByteTag for example), modestly sized NBT can explode in memory footprint. This has been previously seen with the absurd 25 MB footprint on file load.
Previously, I attempted to mitigate this by deduplicating tag objects, but this was mitigating a symptom rather than addressing the cause.

We don't actually need to keep the NBT around in memory, since we don't actually use it for anything other than matching blockstates. In this case, we can allow the code to be possibly a little slower, since the lookup is anyway slow and the result will be cached.
In fact, using encoded ordered states as hash keys significantly improves the speed of lookups for stuff like walls, which have many thousands of states.

We keep around generateStateData(), since it's still possible we may need the BlockStateData associated, and it can be easily reconstructed from the binary-encoded representation in BlockStateDictionaryEntry.
This commit is contained in:
Dylan K. Taylor
2023-05-03 23:11:00 +01:00
parent 32e6fdd95a
commit ed021d193d
7 changed files with 67 additions and 66 deletions

View File

@ -150,7 +150,7 @@ class ParserPacketHandler extends PacketHandler{
if($meta !== 0){
throw new PacketHandlingException("Unexpected non-zero blockitem meta");
}
$blockState = $this->blockTranslator->getBlockStateDictionary()->getDataFromStateId($itemStack->getBlockRuntimeId()) ?? null;
$blockState = $this->blockTranslator->getBlockStateDictionary()->generateDataFromStateId($itemStack->getBlockRuntimeId()) ?? null;
if($blockState === null){
throw new PacketHandlingException("Unmapped blockstate ID " . $itemStack->getBlockRuntimeId());
}
@ -270,7 +270,7 @@ class ParserPacketHandler extends PacketHandler{
if($meta !== 32767){
$blockStateId = $this->blockTranslator->getBlockStateDictionary()->lookupStateIdFromIdMeta($data->name, $meta);
if($blockStateId !== null){
$blockState = $this->blockTranslator->getBlockStateDictionary()->getDataFromStateId($blockStateId);
$blockState = $this->blockTranslator->getBlockStateDictionary()->generateDataFromStateId($blockStateId);
if($blockState !== null && count($blockState->getStates()) > 0){
$data->block_states = self::blockStatePropertiesToString($blockState);
}