From f2c6a75145ce62645122ed6055abf1105bce5413 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 5 May 2023 15:26:54 +0100 Subject: [PATCH] BlockStateDictionary: reduce memory footprint of id/meta -> state ID lookup by >60% the aim of the game here is to avoid allocating lots of tiny arrays, which have a terrible overhead:useful-data ratio. This reduces the footprint of the mapping from 1.6 MB to 600 KB. --- .../mcpe/convert/BlockStateDictionary.php | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/network/mcpe/convert/BlockStateDictionary.php b/src/network/mcpe/convert/BlockStateDictionary.php index e52c7d3d37..d20448f95c 100644 --- a/src/network/mcpe/convert/BlockStateDictionary.php +++ b/src/network/mcpe/convert/BlockStateDictionary.php @@ -51,7 +51,7 @@ final class BlockStateDictionary{ /** * @var int[][]|null - * @phpstan-var array>|null + * @phpstan-var array|int>|null */ private ?array $idMetaToStateIdLookupCache = null; @@ -80,15 +80,25 @@ final class BlockStateDictionary{ /** * @return int[][] - * @phpstan-return array> + * @phpstan-return array|int> */ private function getIdMetaToStateIdLookup() : array{ if($this->idMetaToStateIdLookupCache === null){ + $table = []; //TODO: if we ever allow mutating the dictionary, this would need to be rebuilt on modification - $this->idMetaToStateIdLookupCache = []; foreach($this->states as $i => $state){ - $this->idMetaToStateIdLookupCache[$state->getMeta()][$state->getStateName()] = $i; + $table[$state->getStateName()][$state->getMeta()] = $i; + } + + $this->idMetaToStateIdLookupCache = []; + foreach(Utils::stringifyKeys($table) as $name => $metaToStateId){ + //if only one meta value exists + if(count($metaToStateId) === 1){ + $this->idMetaToStateIdLookupCache[$name] = $metaToStateId[array_key_first($metaToStateId)]; + }else{ + $this->idMetaToStateIdLookupCache[$name] = $metaToStateId; + } } } @@ -127,7 +137,12 @@ final class BlockStateDictionary{ * This is used for deserializing crafting recipe inputs. */ public function lookupStateIdFromIdMeta(string $id, int $meta) : ?int{ - return $this->getIdMetaToStateIdLookup()[$meta][$id] ?? null; + $metas = $this->getIdMetaToStateIdLookup()[$id] ?? null; + return match(true){ + $metas === null => null, + is_int($metas) => $metas, + is_array($metas) => $metas[$meta] ?? null + }; } /**