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.
This commit is contained in:
Dylan K. Taylor 2023-05-05 15:26:54 +01:00
parent 09e823e304
commit f2c6a75145
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -51,7 +51,7 @@ final class BlockStateDictionary{
/**
* @var int[][]|null
* @phpstan-var array<int, array<string, int>>|null
* @phpstan-var array<string, array<int, int>|int>|null
*/
private ?array $idMetaToStateIdLookupCache = null;
@ -80,15 +80,25 @@ final class BlockStateDictionary{
/**
* @return int[][]
* @phpstan-return array<int, array<string, int>>
* @phpstan-return array<string, array<int, int>|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
};
}
/**