bovigo / vfsStream

vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.
BSD 3-Clause "New" or "Revised" License
1.42k stars 102 forks source link

`vfsStreamDirectory::getChild()` has absurd complexity #256

Open mvorisek opened 3 years ago

mvorisek commented 3 years ago

image

captured when the PrestaShop/Smarty caching is conigured to VFS like:

use org\bovigo\vfs\vfsStream;

$vfsSmartyRoot = vfsStream::setup('smarty', 0000);
$vfsSmartyCompile = vfsStream::newDirectory('compile')->at($vfsSmartyRoot);
$vfsSmartyCache = vfsStream::newDirectory('cache')->at($vfsSmartyRoot);

global $smarty;
$smarty = new SmartyCustom();
$smarty->setConfigDir([]);
$smarty->setCompileDir($vfsSmartyCompile->url());
$smarty->setCacheDir($vfsSmartyCache->url());

in https://github.com/PrestaShop/PrestaShop/blob/1.7.7.4/config/smarty.config.inc.php#L37

and basic page like /index.php is opened.

I belive there is some exponential complexity when traversing directories with depth like 10 as xdebug profiler shows for 2181 calls of getContent getChild is executed more than million times.

Callers:

image


image

jaapio commented 3 years ago

Hi,

To get started, I think you didn't have a look at the code in this method. If you did, you would have noticed that this method has some recursion. Maybe there is some bug in there, but I cannot see in your reports what the actual calls are about. The method itself isn't that complex.

I would like to ask you to re-think your post, although it provides a lot of information about how you are using vfsStream, it doesn't really provide any information about what we as maintainers can do to fix this issue. If it was an issue in vfsStream. It would be useful if you could provide us some more information about what the arguments of these calls are.

Please keep in mind that some caching libraries have odd file structures which are optimized to do quick inode lookups which do work very well in regular filesystems. But will not perform as nice in vfsStream. Therefor vfsStream might not be the right choice for you to cache your smarty templates.

mvorisek commented 3 years ago

I belive the deeply nested calls are invoked from here - https://github.com/bovigo/vfsStream/blob/v1.6.8/src/main/php/org/bovigo/vfs/vfsStreamDirectory.php#L183 - it iterates over all children and hasChild calls getChild again.

I belivery it can be easily replicated when you create vfs with depth like 3 and 3 files in each directory.