Problem/Motivation

Anonymous user, frontpage, without page_cache (entire request time 94ms).

In there we spend 1ms in theme_get_setting(), which does quite a lot:

Function Name Calls Calls% Incl. Wall Time
(microsec)
IWall% Incl.
MemUse
(bytes)
IMemUse% Incl.
PeakMemUse
(bytes)
IPeakMemUse%
Current Function
theme_get_setting 8 9.4% 1,138 1.2% 175,496 1.1% 173,384 1.0%
Exclusive Metrics for Current Function 121 10.6% 6,840 3.9% 3,368 1.9%
Parent functions
system_page_attachments 3 37.5% 1,036 91.0% 174,120 99.2% 173,384 100.0%
template_preprocess_page 3 37.5% 61 5.4% 736 0.4% 0 0.0%
_bartik_process_page 2 25.0% 41 3.6% 640 0.4% 0 0.0%
Child functions
file_create_url 2 2.9% 568 49.9% 118,088 67.3% 110,760 63.9%
Drupal::config 2 2.9% 195 17.1% 10,608 6.0% 38,376 22.1%
Drupal\Core\Config\ConfigBase::get 14 20.0% 120 10.5% 8,552 4.9% 2,376 1.4%
spl_autoload_call 1 1.4% 40 3.5% 10,896 6.2% 11,144 6.4%
Drupal\Core\Config\ConfigBase::setData 1 1.4% 33 2.9% 6,432 3.7% 0 0.0%
Drupal::theme 8 11.4% 18 1.6% 632 0.4% 584 0.3%
Drupal\Core\Config\ConfigBase::set 2 2.9% 16 1.4% 4,648 2.6% 3,936 2.3%
drupal_static 8 11.4% 9 0.8% 944 0.5% 944 0.5%
file_exists 1 1.4% 6 0.5% 624 0.4% 0 0.0%
Drupal\Core\Config\Config::get 2 2.9% 4 0.4% 648 0.4% 0 0.0%
Drupal\Core\Extension\Extension::getPath 2 2.9% 4 0.4% 864 0.5% 0 0.0%
Drupal::service 1 1.4% 3 0.3% 632 0.4% 0 0.0%
_system_default_theme_features 1 1.4% 1 0.1% 1,816 1.0% 0 0.0%
Drupal\Core\Theme\ActiveTheme::getName 8 11.4% 0 0.0% 656 0.4% 656 0.4%
Drupal\Core\Extension\ThemeHandler::listInfo 1 1.4% 0 0.0% 664 0.4% 0 0.0%
Drupal\Core\Theme\ThemeSettings::__construct 1 1.4% 0 0.0% 664 0.4% 576 0.3%
in_array 7 10.0% 0 0.0% 624 0.4% 0 0.0%
Drupal\Core\Theme\ThemeManager::getActiveTheme 8 11.4% 0 0.0% 664 0.4% 664 0.4%

Proposed resolution

Try to cache the theme settings not in the request but between requests. One really good place could be the cache entry for the active theme object.
In case we would store it there, we would avoid the call to $themes = \Drupal::service('theme_handler')->listInfo(); in there.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

dawehner’s picture

@effulgentsia and myself talked about that and we agreed it would be worth try to cache this information.
In an ideal world file_create_url() would have the cacheablity metadata so the generated URL can be cached. For normal URls we rely on higher level render caching, but for this case, we could not.

claudiu.cristea’s picture

Status: Active » Needs review
StatusFileSize
new5.48 KB

The changes are few lines but the patch footprint is bigger because of indentation increase.

Status: Needs review » Needs work

The last submitted patch, 2: theme_get_setting-2531958-2.patch, failed testing.

claudiu.cristea’s picture

Well, this is weird. Those tests are passing locally.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new0 bytes

Status: Needs review » Needs work

The last submitted patch, 5: theme_get_setting-2531958-5.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new9.86 KB

Oops. Sorry!

lauriii’s picture

Issue tags: +needs profiling
dawehner’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/src/EventSubscriber/ThemeSettingsSubscriber.php
@@ -0,0 +1,106 @@
+      }
+
+      list($theme, ) = explode('.', $config_key, 2);
+      $this->cacheBin->delete('theme_settings.' . $theme);

This is wrong. Use cache tags and be done.

Should we include the language at least in the caching? What do we do with config overrides? Things aren't simple sadly.

wim leers’s picture

Issue summary: View changes
StatusFileSize
new18.45 KB
new18.74 KB

I'm afraid this is a dead end also :(

Tested with 1000 requests to /contact, as the anon users, with page cache off.

Before
Requests per second:    14.11 [#/sec] (mean)
Time per request:       70.888 [ms] (mean)
Time per request:       70.888 [ms] (mean, across all concurrent requests)
Transfer rate:          195.59 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    68   71   1.2     71      76
Waiting:       60   64   1.2     63      69
Total:         68   71   1.2     71      76

Percentage of the requests served within a certain time (ms)
  50%     71
  66%     71
  75%     71
  80%     72
  90%     72
  95%     73
  98%     74
  99%     75
 100%     76 (longest request)
After
Requests per second:    14.07 [#/sec] (mean)
Time per request:       71.094 [ms] (mean)
Time per request:       71.094 [ms] (mean, across all concurrent requests)
Transfer rate:          195.02 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    64   71   1.4     71      79
Waiting:       59   64   1.3     64      72
Total:         64   71   1.4     71      79

Percentage of the requests served within a certain time (ms)
  50%     71
  66%     71
  75%     72
  80%     72
  90%     73
  95%     74
  98%     74
  99%     75
 100%     79 (longest request)

dawehner’s picture

It would be great to profile both issues at the same time.

claudiu.cristea’s picture

@dawehner,

+ $this->cacheBin->delete('theme_settings.' . $theme);
This is wrong. Use cache tags and be done.

+++ b/core/modules/system/src/EventSubscriber/ThemeSettingsSubscriber.php
@@ -0,0 +1,106 @@
+    else {
+      // Check if the config key is theme settings key. Exit if not.
+      $keys = array_map(function ($theme) {
+        return "$theme.settings";
+      }, array_keys($this->themeHandler->listInfo()));
+      if (!in_array($config_key, $keys)) {
+        return;
+      }
+
+      list($theme, ) = explode('.', $config_key, 2);
+      $this->cacheBin->delete('theme_settings.' . $theme);
+    }

I'm using here ->listInfo() and maybe this is slowing the whole stuff (?) I can drop the check of theme name and invalidate by tag. The cons is that we'll remove also other theme cache (and the global settings). Opinions?

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +stale-issue-cleanup

Thank you for creating this issue to improve Drupal.

We are working to decide if this task is still relevant to a currently supported version of Drupal. There hasn't been any discussion here for over 8 years which suggests that this has either been implemented or is no longer relevant. Your thoughts on this will allow a decision to be made.

Since we need more information to move forward with this issue, the status is now Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.

Thanks!

berdir’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)

I did test this with blackfire and theme_get_settings() doesn't show up at all, with a scenario of disabled page cache so that most blocks are cached and only the whole page is not and this is being called.

I stepped through the call in xdebug and all things that we call are essentially already initialized and ready, such as the active theme and theme handler list info or is config that's loaded from fast cache.

This hasn't been updated since 2015, so I'm going to close it.

We have #3035288: Deprecate theme_get_setting() to convert this to OOP which will simplify the code a bit I think.