I have always wanted a faster Drupal. While Drupal is currently not slow at all, it could be faster, especially for authenticated users. I've always wanted to try the impact of splitting up the Drupal modules into a .module which should hald menu callbacks, hooks and the mist common function and a .inc which should hold the rest.

I've done this for user.module, our largest module.

I've found that for a minimal Drupal (required modules + node.module, no content) the memory usage of the /node page goes from about 4.3MB to 3.7 MB. Also 30 queries with ab go from about 235 ms to 220 ms.

I attach the files I used.

The process is as follows:

Identify seldomly called functions (anything that is called from a block is not a good idea).
You can also split up lengthy menu callbacks (admin menus!) into a wrapper and a helper function.
I've prefixed all functions that go into the .inc file with _.

CommentFileSizeAuthor
#1 user.inc48.19 KBkilles@www.drop.org
user.module31.05 KBkilles@www.drop.org

Comments

killes@www.drop.org’s picture

StatusFileSize
new48.19 KB

And the .inc.

moshe weitzman’s picture

I think this might be a good direction for handling the "we include too much code for registered users" issue. one minor problem is that other modules use some of the functions that you've moved to the .inc file. for example, user_authenticated_id() and user_save() are used by webserver_auth and probably others. those modules will need to include user.inc I guess ... i'm not so sure you need to prefix all those functions with _. those functions are legitimately called from other modules.

killes@www.drop.org’s picture

Moshe,. thanks for the feedback. I will move move user_authenticated_id back to the module and provide a wrapper for user_save. The reason I prefixed the functions in user.inc is that I like to know where to look for a function by looking at its name.

killes@www.drop.org’s picture

The wrapper was actually already there. I have also moved the most of the docs into the .inc function, as it is only admin related.

I've uploaded the module and the .inc file to my sandbox:

http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/killes/speed-...
http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/killes/speed-...

I will try to provide some guidelines on how to split module files up.

moshe weitzman’s picture

I think the _ at the beginning of a function name indicates that other modules should call the function directly. So you are slightly misusing the _ convention when it signifies 'look in the .inc file'.

killes@www.drop.org’s picture

Well, Drupal is inconsistent with what _ should mean. There are API functions that are prefixed by _ (_taxonomy_term_select) and there are non-prefixed functions in .inc files (locale.inc). I propose that we purely treat the underscore as an indicator to where a function's definition can be found.

I've split statistics.module as well. Apparently it is easily possible to split the modules' sizes in half by going the .inc way (and considering that I left the inline docs in the module).

robertdouglass’s picture

I thought the _ signified a private function that should *not* be called by other modules, only internally.

from the coding standards:

Private class members (meaning class members that are intended
to be used only from within the same class in which they are
declared; PHP 4 does not support truly-enforceable private
namespaces) are preceded by a single underscore. For example:

_node_get()

$this->_status

killes@www.drop.org’s picture

I'd be in favour of changing the coding standards...

Anyway: With both user and system module split up, I get:

4.3 MB and 230 ms/30 requests for the unchanged minimal Drupal and 3.5 MB and 140 ms/30 requests for my "speed-drupal" version. I declare myself impressed.

Anyboy who wants to make his own tests is welcome to benchmark http://killes.drupaldevs.org/cvs/ vs. http://killes.drupaldevs.org/cvs2/. You should be able to tell which is which. Both versions use the same very empty database, caching is off.

killes@www.drop.org’s picture

Hmm, I cannot reproduce the 140ms reading anymore. Their must have been some parse error which made the execution time plummet. The reading is more like 210 ms. If I split up filter module as well, it goes down to 200 ms, which is still a nice improvement. Memory consumption is down to 3.2MB.

robertdouglass’s picture

Killes, I've taken a look at your speed-drupal work and like it a lot. I have come to agree with you completely that the _ convention in the .inc files is very logical and will help with the new dispersal of the functions plus the addition of wrappers. It is also consistent with the private concept, since calling any of these functions directly risks the function not yet being included, thus an error. Programmers would be encouraged to never call a _ function. In contrast, everybody calls them now, if it seems useful. The _taxonomy_term_select function is a prime example. There 18 matches for this function in contrib/modules.

I am currently rewriting some of the modules on one of my more performance-needy sites using your guidelines. I encourage others to test this work and add it to the list of things that should really be carefully considered for 4.6. I know we've had a code freeze, but ignoring this for 6 months would be depriving a lot of users a better Drupal and wasting a lot of server CPU cycles, imo.

killes@www.drop.org’s picture

Thanks for your review. While my approach does make Drupal somewhat faster (and uses lots less memory) I have an even better idea up the sleeve. That idea will also avoid the wrappers which don't really look nice.

If you need better performance from yur Drupal site you should also look into using a php cache.

robertdouglass’s picture

Please share your trick sooner than later - it could have a major impact on how I and my team develop. Thanks for the great work!

killes@www.drop.org’s picture

Status: Active » Closed (duplicate)

This issue is a precursor to:

http://drupal.org/node/15572

killes@www.drop.org’s picture