drupal_load() already has a static to prevent it loading a module more than once, and there's no reason not to use it, so we should use include() there instead of include_once().

Here's how it looks in strace, I included the first request immediately after starting apache to strace it (i.e. with a cold start on PHP-level caches), and the third request (where PHP caches are warmed). As you can see the cached version is considerably cleaner. Also note that with 150 modules installed, the strace output will be 50 times as long as it is here, this is just a cached page.

HEAD:

(first request after restart)
8125  lstat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8125  lstat("/home/catch/www/7/modules/dblog", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8125  lstat("/home/catch/www/7/modules", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8125  open("/home/catch/www/7/modules/dblog/dblog.module", O_RDONLY) = 11
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8125  mmap(NULL, 6768, PROT_READ, MAP_SHARED, 11, 0) = 0x7fb438363000
8125  stat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8125  munmap(0x7fb438363000, 6768)      = 0
8125  close(11)                         = 0
8125  lstat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8125  lstat("/home/catch/www/7/modules/overlay", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8125  open("/home/catch/www/7/modules/overlay/overlay.module", O_RDONLY) = 11
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8125  mmap(NULL, 33497, PROT_READ, MAP_SHARED, 11, 0) = 0x7fb43835c000
8125  stat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8125  brk(0x7fb4394a2000)               = 0x7fb4394a2000
8125  munmap(0x7fb43835c000, 33497)     = 0
8125  close(11)                         = 0
8125  lstat("/home/catch/www/7/modules/system/system.module", {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8125  lstat("/home/catch/www/7/modules/system", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8125  open("/home/catch/www/7/modules/system/system.module", O_RDONLY) = 11
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8125  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8125  mmap(NULL, 138592, PROT_READ, MAP_SHARED, 11, 0) = 0x7fb438312000
8125  stat("/home/catch/www/7/modules/system/system.module", {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8125  brk(0x7fb4394e5000)               = 0x7fb4394e5000
8125  brk(0x7fb439525000)               = 0x7fb439525000
8125  brk(0x7fb439568000)               = 0x7fb439568000
8125  brk(0x7fb4395ab000)               = 0x7fb4395ab000
8125  munmap(0x7fb438312000, 138592)    = 0
8125  close(11)                         = 0

(third request)

7904  lstat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7904  lstat("/home/catch/www/7/modules/dblog", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
7904  lstat("/home/catch/www/7/modules", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
7904  open("/home/catch/www/7/modules/dblog/dblog.module", O_RDONLY) = 11
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7904  mmap(NULL, 6768, PROT_READ, MAP_SHARED, 11, 0) = 0x7f954fcdf000
7904  stat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7904  munmap(0x7f954fcdf000, 6768)      = 0
7904  close(11)                         = 0
7904  lstat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7904  lstat("/home/catch/www/7/modules/overlay", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
7904  open("/home/catch/www/7/modules/overlay/overlay.module", O_RDONLY) = 11
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7904  mmap(NULL, 33497, PROT_READ, MAP_SHARED, 11, 0) = 0x7f954fcd8000
7904  stat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7904  munmap(0x7f954fcd8000, 33497)     = 0
7904  close(11)                         = 0
7904  lstat("/home/catch/www/7/modules/system/system.module", {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
7904  lstat("/home/catch/www/7/modules/system", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
7904  open("/home/catch/www/7/modules/system/system.module", O_RDONLY) = 11
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
7904  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
7904  mmap(NULL, 138592, PROT_READ, MAP_SHARED, 11, 0) = 0x7f954fc8e000

Patch:

(first request after restart)
8020  stat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8020  lstat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8020  lstat("/home/catch/www/7/modules/dblog", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8020  lstat("/home/catch/www/7/modules", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8020  open("/home/catch/www/7/modules/dblog/dblog.module", O_RDONLY) = 11
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
8020  mmap(NULL, 6768, PROT_READ, MAP_SHARED, 11, 0) = 0x7fdc6ff67000
8020  munmap(0x7fdc6ff67000, 6768)      = 0
8020  close(11)                         = 0
8020  stat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8020  lstat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8020  lstat("/home/catch/www/7/modules/overlay", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8020  open("/home/catch/www/7/modules/overlay/overlay.module", O_RDONLY) = 11
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
8020  mmap(NULL, 33497, PROT_READ, MAP_SHARED, 11, 0) = 0x7fdc6ff60000
8020  brk(0x7fdc71997000)               = 0x7fdc71997000
8020  munmap(0x7fdc6ff60000, 33497)     = 0
8020  close(11)                         = 0
8020  stat("/home/catch/www/7/modules/system/system.module", {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8020  lstat("/home/catch/www/7/modules/system/system.module", {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8020  lstat("/home/catch/www/7/modules/system", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
8020  open("/home/catch/www/7/modules/system/system.module", O_RDONLY) = 11
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8020  fstat(11, {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0
8020  mmap(NULL, 138592, PROT_READ, MAP_SHARED, 11, 0) = 0x7fdc6ff16000
8020  brk(0x7fdc719da000)               = 0x7fdc719da000
8020  brk(0x7fdc71a1a000)               = 0x7fdc71a1a000
8020  brk(0x7fdc71a5d000)               = 0x7fdc71a5d000
8020  brk(0x7fdc71aa0000)               = 0x7fdc71aa0000
8020  munmap(0x7fdc6ff16000, 138592)    = 0
8020  close(11)                         = 0


(third request)
7732  stat("/home/catch/www/7/modules/dblog/dblog.module", {st_mode=S_IFREG|0644, st_size=6768, ...}) = 0
7732  stat("/home/catch/www/7/modules/overlay/overlay.module", {st_mode=S_IFREG|0644, st_size=33497, ...}) = 0
7732  stat("/home/catch/www/7/modules/system/system.module", {st_mode=S_IFREG|0644, st_size=138592, ...}) = 0

There is no real change in benchmarks, however http://tag1consulting.com/blog/nfs-drupal-and-realpath-cache - NFS doesn't cache lstat calls at all, also the faster page caching is (like using APC or memcache as a backend, and with other patches in the queue applied) the more chance we have of seeing an improvement in benchmarks with and without this patch, but I don't think that's necessary since this makes sense by itself.

Comments

Status: Needs review » Needs work

The last submitted patch, drupal_load.patch, failed testing.

catch’s picture

Status: Needs work » Needs review
Issue tags: +Needs backport to D7

Installing via the UI is fine, drush doesn't like it though due to this, and a hardcoded require of the install profile.

Attached patch covers the install profile issue, not sure whether this will be enough or not for the test bot.

Patch for drush at #1068964: Remove hardcoded require_once() for system.module.

We will need to move this to D8 since this is going to require a new drush release, although I think we should be able to backport it so adding that tag. Also leaving at D7 so now so the patch gets tested.

catch’s picture

StatusFileSize
new1.47 KB

Status: Needs review » Needs work

The last submitted patch, drupal_load.patch, failed testing.

catch’s picture

Status: Needs work » Needs review
StatusFileSize
new1.99 KB

Fixed those failures.

moshe weitzman’s picture

People do all kinds of crazy things like include .module files from settings.php. They can safely do that because of the include_once. Switching to include() is going to preclude them from doing that. Even more crazy are apps that custom bootstrap drupal like drush. drush can cope with t

I'm not saying that we this patch is bad, but it will cause some pain. I don't think the justification is strong enough yet.

catch’s picture

settings.php is loaded from bootstrap.inc, so they ought to be able to use drupal_load() from there.

fabianx’s picture

Subscribe.

mgifford’s picture

Issue tags: -Performance, -i/o, -Needs backport to D7

#5: drupal_load.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Performance, +i/o, +Needs backport to D7

The last submitted patch, drupal_load.patch, failed testing.

hefox’s picture

Version: 7.x-dev » 8.x-dev
Status: Needs work » Needs review
StatusFileSize
new1.69 KB

Quick reroll, haven't tested that it works/if any syntax errors

Status: Needs review » Needs work

The last submitted patch, drupal_load-1068932-11.patch, failed testing.

yesct’s picture

Issue tags: -i/o +i-o

(the slash in the i/o tag breaks the autocomplete from adding new tags)

catch’s picture

Status: Needs work » Needs review
StatusFileSize
new1.13 KB
new427 bytes

Reviving this, should have some data from a 7.x site soonish.

Status: Needs review » Needs work

The last submitted patch, 14: 1068932_include.patch, failed testing.

catch’s picture

Status: Needs work » Needs review
StatusFileSize
new1.28 KB

7.x patch that won't break drush.

catch’s picture

Just tested this on a site that has the Drupal install on NFS, it reduced time for a full bootstrap from between 500-1200ms to 2-400ms.

mgifford’s picture

Should #16 also run on SimplyTest.me? It fails....

catch’s picture

Version: 8.0.x-dev » 7.x-dev
StatusFileSize
new1.8 KB

Missed a bit. Moving to 7.x to trigger a test.

Status: Needs review » Needs work

The last submitted patch, 19: 1068932_include_once.patch, failed testing.

toamit’s picture

It would nice to get this patch in drupal core, I am seeing significantly variable NFS performance even with APC holding all the files.

Status: Needs work » Needs review

toamit queued 19: 1068932_include_once.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 19: 1068932_include_once.patch, failed testing.

yesct’s picture

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

I didn't see a d8 commit so I think this still needs a d8 fix.

Status: Needs work » Needs review

toamit queued 19: 1068932_include_once.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 19: 1068932_include_once.patch, failed testing.

mgifford’s picture

Status: Needs work » Needs review
StatusFileSize
new1.13 KB

Reroll of #14

Status: Needs review » Needs work

The last submitted patch, 27: 1068932_include-d8-27.patch, failed testing.

mgifford’s picture

I suspect this will get the following error but perhaps this is just what SimplyTest.me is giving me because of some server work:

Fatal error: Cannot redeclare seven_preprocess_html() (previously declared in /home/s1006273f91c79d7/www/core/themes/seven/seven.theme:15) in /home/s1006273f91c79d7/www/core/themes/seven/seven.theme on line 25

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.

catch’s picture

Status: Needs work » Closed (duplicate)

Include files are nearly gone.