Unneeded calls to the autoloader
TimWolla opened this issue · comments
Please consider the following code:
<?php
namespace NS;
use CuyZ\Valinor\MapperBuilder;
require('vendor/autoload.php');
\spl_autoload_register(function (string $class) {
echo "L: ", $class, PHP_EOL;
});
final class Target
{
/**
* @param array{
* foo?: string,
* bar?: int,
* baz?: array<string, int>,
* } $foo
* @param array<string,string> $bar
*/
public function __construct(
public readonly array $foo,
public readonly array $bar,
)
{
}
}
try {
$payload = (new MapperBuilder())
->mapper()
->map(
Target::class,
[
"bar" => [],
"foo" => [
"foo" => "foo",
]
]
);
var_dump($payload);
} catch (\CuyZ\Valinor\Mapper\MappingError $error) {
$messages = \CuyZ\Valinor\Mapper\Tree\Message\Messages::flattenFromNode(
$error->node()
);
foreach ($messages as $message) {
echo $message, PHP_EOL;
}
}
When running this code, the following output is emitted:
L: NS\array
L: NS\array
L: NS\foo
L: NS\foo
L: foo
L: foo
L: foo
L: NS\string
L: NS\string
L: NS\bar
L: NS\bar
L: bar
L: bar
L: bar
L: NS\int
L: NS\int
L: NS\baz
L: NS\baz
L: baz
L: baz
L: baz
L: NS\array
L: NS\array
L: NS\string
L: NS\string
L: NS\int
L: NS\int
L: NS\array
L: NS\array
L: NS\string
L: NS\string
L: NS\string
L: NS\string
L: NS\array
L: NS\array
L: NS\foo
L: NS\foo
L: foo
L: foo
L: foo
L: NS\string
L: NS\string
L: NS\bar
L: NS\bar
L: bar
L: bar
L: bar
L: NS\int
L: NS\int
L: NS\baz
L: NS\baz
L: baz
L: baz
L: baz
L: NS\array
L: NS\array
L: NS\string
L: NS\string
L: NS\int
L: NS\int
L: NS\array
L: NS\array
L: NS\string
L: NS\string
L: NS\string
L: NS\string
/pwd/test.php:44:
class NS\Target#146 (2) {
public readonly array $foo =>
array(1) {
'foo' =>
string(3) "foo"
}
public readonly array $bar =>
array(0) {
}
}
It becomes clear that the autoloader is uselessly called for classnames that are never going to result in a hit. This can get expensive for an autoloader that checks the file system for a class to include. Especially since the calls are repeated multiple times:
NS\int
,NS\string
andNS\array
can never successfully load a class, becauseint
,string
andarray
are reserved class names.foo
,bar
andbaz
as keys of the array shape and thus should not be considered class names in the first place.
As a result I did not expect any calls to my autoloader happening at all.
Thanks for the investigation! I took some time to submit #499 which will reduce the number of calls to the autoloader by a lot. Preventing class existence checks for shaped array keys would require a lot more work, which I may have time to do later (so I'm keeping this issue opened for now).
Good news, I found some time to submit #515 which fixes this issue.
Thanks again for reporting it!