diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php index 91135e1..f5cf256 100644 --- a/core/lib/Drupal/Core/Config/ConfigFactory.php +++ b/core/lib/Drupal/Core/Config/ConfigFactory.php @@ -26,6 +26,8 @@ class ConfigFactory { protected $container; + protected $configObjects = array(); + public function __construct(ContainerBuilder $container) { $this->container = $container; } @@ -40,8 +42,28 @@ class ConfigFactory { * A configuration object with the given $name. */ public function get($name) { + // "Caching" the instantiated objects per name cuts off a fair amount of CPU + // time and memory. Only the data within the configuration object changes, + // so the additional cost of instantiating duplicate objects can be happily + // avoided. It is not uncommon for a configuration object to be retrieved + // many times during a single request; e.g., 'system.performance' alone is + // retrieved around 10-20 times within a single page request. Sub-requests + // via HttpKernel will most likely only increase these counts. + // @todo Benchmarks were performed with a script that essentially retained + // all instantiated configuration objects in memory until script execution + // ended. A variant of that script called config() within a helper + // function only, which inherently meant that PHP destroyed all + // configuration objects after leaving the function. Consequently, + // benchmark results looked entirely different. Profiling should probably + // redone under more realistic conditions; e.g., actual HTTP requests. + // @todo The decrease of CPU time is interesting, since that means that + // ContainerBuilder involves plenty of function calls (which are known to + // be slow in PHP). + if (isset($this->configObjects[$name])) { + return $this->configObjects[$name]; + } $class = $this->container->getParameter('config.object'); - $config = new $class($this->container->get('config.manager')); - return $config->setName($name); + $this->configObjects[$name] = new $class($this->container->get('config.manager')); + return $this->configObjects[$name]->setName($name); } }