Description
This is a follow-up of this discussion.
Alpine is the default docker linux base distribution. It's widely used. It's based on musl libc, and so, it's quite different of traditional linux distribution as Debian. One the difference is that glob does not handle GLOB_BRACE
.
I knew about it from an old issue on composer that we already experienced.
On a big project, we had quite castrophous boot time, and I finally checked on it.
The first thing is that Iterator/SortableIterator.php/44-46
cost an enormous amout of time and is called 22k time.
Searching why, It seems that we never enter is the optimized path here
.I had that in Kernel::configureContainer
:
const CONFIG_EXTS = '.{php,xml,yaml,yml}';
// ...
$loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob');
$loader->load($confDir . '/{packages}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob');
$loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob');
and in services.yaml
:
Lib\Core\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Translation,Tests,Kernel.php,PHPStan,Fixtures,Traits}'
As I don't have GLOB_BRACE
and every pattern given contains a brace, it always fallback on the symfony/finder
implementation which is wayyy slower.
By removing the /**/*
, and only searching into yaml
extension, I expect to be in the fast path. But the brackets on {packages}
and {services}
prevents it. By removing them it goes into the fast path. And gives a clear boost.
$loader->load($confDir . '/packages/*' . self::CONFIG_EXTS, 'glob');
if (is_dir($confDir . '/packages/' . $this->environment)) {
$loader->load($confDir . '/packages/' . $this->environment . '/*' . self::CONFIG_EXTS, 'glob');
}
$loader->load($confDir . '/services.yaml');
I didn't see any drwabacks (and I have a very extensive tests suites).
Rest the case with multiple option separated by comma in brackets, that stills cost a lot.
I'm absolutly thinks this is a serious issue, but I'm not sure of what todo with it, hance the absence of PR.
- brackets are they really necessary for packages and services? (edit answer: it ONLY ensure that the file / dir is optional. On an app that is older than one day, I'm sure of the structure that I use, and it should be totally recommended in perf reco to update that Kernel stuff to be exact and don't let it guess.)
- should we purpose a better implementation on that hot path than the
symfony/finder
one. @nicolas-grekas purpose to "we could have some logic that splits a single glob-with-braces into several of them" Simplify the default Kernel recipes#705 (comment)