Huge memory leak in PHPUnit TypeInferenceTest when using data providers #9914
-
Hello there, I've noticed today that our project's test suite failed locally with a memory exhausted error, even though we run it with 4 GB (:speak_no_evil:). I've narrowed it down to an implementation of a PHPStan's After a bit of fiddling, I tried removing the data provider and loading the 31 files directly in the test method using a foreach, and here's the difference : With the data provider :
Without :
So, I created two Blackfire profiles, and it seems like an almost infinite loop, looking at the number of calls to Test code before : /**
* @return iterable<mixed>
*/
public static function dataAsserts(): iterable
{
foreach ((new Finder())->in(__DIR__ . '/dataproviders')->files()->name('*.php') as $file) {
yield from self::gatherAssertTypes($file->getRealPath());
}
}
#[DataProvider('dataAsserts')]
public function testAsserts(string $assertType, string $file, mixed ...$args): void
{
$this->assertFileAsserts($assertType, $file, ...$args);
} Test code after : public function testAsserts(): void
{
foreach ((new Finder())->in(__DIR__ . '/dataproviders')->files()->name('*.php') as $file) {
/** @var array{0: string, 1: string, 2: array<mixed>} $args */
foreach (self::gatherAssertTypes($file->getRealPath()) as $args) {
$this->assertFileAsserts(...$args);
}
}
} I'm not sure if I should open an issue on PHPUnit, Exporter or here, so I'll start here. 🤷♂️ gnutix |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 23 replies
-
/cc @sebastianbergmann You might be interested by this. |
Beta Was this translation helpful? Give feedback.
-
This is expected, at least to me. The data provided to a test by a data provider is exported to a string for the value object that represents the test for the event system. If you use data providers to create object graphs that are expensive to export then yes, this will be slow. Ideally, data providers should only provide scalar values or "small" value objects. If your test fixture has to be a large object graph, then construct that in your test method from the aforementioned scalar values or "small" value objects. |
Beta Was this translation helpful? Give feedback.
-
So I guess a better middle ground here would be to load the 31 files paths in the data provider, then use gatherAssertTypes in the test to do each assertions ? I wouldn't have thought that the object graph would be that big.. but I didn't know that all of it was converted into a string either. Thanks for the info. |
Beta Was this translation helpful? Give feedback.
-
Also, as an alternative, you can analyze the |
Beta Was this translation helpful? Give feedback.
-
Please note that this is no longer a problem as of PHPStan 1.10.66 thanks to this fix: phpstan/phpstan-src@da87a65 So make sure you've updated to this version. Your test suite should be fast even with PHPUnit 10 and 11. |
Beta Was this translation helpful? Give feedback.
Please note that this is no longer a problem as of PHPStan 1.10.66 thanks to this fix: phpstan/phpstan-src@da87a65
So make sure you've updated to this version. Your test suite should be fast even with PHPUnit 10 and 11.