foundry
foundry copied to clipboard
Performance Problem with random
While diagnosing why some of our tests are so slow, I discovered the culprit for us is with random(). We have a function:
public static function randomApiUser(): ApiUser
{
$user = self::random()->object();
return new ApiUser($user);
}
And it was making tests take five times as long as when we didn't use it.
After poking around, I noticed that rather than getting X random records, it's getting ALL of them and then getting random ones from that.
public function randomRange(int $min, int $max, array $attributes = []): array
{
if ($min < 0) {
throw new \InvalidArgumentException(\sprintf('$min must be positive (%d given).', $min));
}
if ($max < $min) {
throw new \InvalidArgumentException(\sprintf('$max (%d) cannot be less than $min (%d).', $max, $min));
}
$all = \array_values($this->findBy($attributes));
\shuffle($all);
if (\count($all) < $max) {
throw new \RuntimeException(\sprintf('At least %d "%s" object(s) must have been persisted (%d persisted).', $max, $this->getClassName(), \count($all)));
}
return \array_slice($all, 0, \random_int($min, $max)); // @phpstan-ignore-line
}
I think it would be more performant if the code used something like this to just get random records from the database (with the appropriate attribute filters):
SELECT *
FROM table_name
ORDER BY RAND()
LIMIT 1;
I am willing to do a PR for this if you would like.