Closed (won't fix)
Project:
Drupal core
Version:
8.0.x-dev
Component:
base system
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Reporter:
Created:
12 Jan 2007 at 03:02 UTC
Updated:
29 Jul 2014 at 17:33 UTC
Jump to comment: Most recent file
Comments
Comment #1
ChrisKennedy commentedIt's best to include, or at least summarize, benchmarks in the issue entry for both convenience and posterity rather than needlessly making everyone visit your blog. The benchmarks shows a performance improvement of about 2%.
How much does the performance improvement depend on the number of modules you have enabled (and how many functions they define)? You could even use PHP's get_defined_functions() to see how the performance gain varies with the exact number of defined functions for a few test setups (e.g. small, medium, and large number of modules enabled).
Also, your patch is difficult to apply in its current form. See http://drupal.org/patch for info on how to create a basic cvs patch. The IF statement needs a space in it too (see the coding standards).
Comment #2
dannyp commentedMea culpa - was in a bit of a rush last night and didn't have access to a working copy, so I wasn't looking forward to typing twice. Sorry if that inconvienenced anyone.
That benchmark was on out of the box drupal 5rc2. The more modules present, the bigger the expected performance increase.
Good call on the whitespace change - I've incorporated it and generated a diff against 1.93.
Comment #3
RobRoy commentedThat last } has a trailing white space, need to remove that.
Also, IMO all functions that implement static caching need to implement a $reset parameter to reset the static cache and Doxygen. For example, we may programmatically disable a module then run some other code that thinks this hook still exists (omitting a module_exists() call). We would have to add code to module_disable to reset this static cache. See http://drupal.org/node/106015 for a bit more explanation.
Comment #4
ChrisKennedy commentedGood point, a reset parameter should be added.
Comment #5
moshe weitzman commentedi have no idea how php internals work, but can't see a benefit here. php knows in its symbol table about all functions that exist. you can't delete a function once it has been loaded, can you? that synbol table has got to be as fast as our static array. i see that benchmarks prove otherwise, but i'd like to sanity check.
Comment #6
ByteEnable commentedThis is really really low hanging fruit. The benchmark numbers show a delta of only 300ms, but yet the author claims linear correlation with number of modules loaded but offers no proof. IMHO, bogus so far.
Byte
Comment #7
dannyp commentedActually, the msec/first-response is about two standard deviations apart between tests.
without:
msecs/first-response: 54.8222 mean, 64.249 max, 53.426 min, 0.814898 stddev
msecs/first-response: 54.7124 mean, 60.375 max, 53.48 min, 0.636029 stddev
And with it:
msecs/first-response: 53.6751 mean, 58.663 max, 52.455 min, 0.681214 stddev
msecs/first-response: 53.6477 mean, 58.638 max, 52.5 min, 0.508483 stddev
Which does mean that they're statistically different.
It's a fair point about dynamically defining (or undefining) modules, so I think the rest is moot, but there was certainly a performance gain to be had here. I've attached the trace that I used with kcachegrind - if you'll notice, 5.07% of the time of the request ends up getting spent in module_hook, of which 4.61% of the time is spent in module_hook itself.
That's really interesting, because it means that the call to function_exists is cheap, but that the call to module_hook is not - perhaps it's the concatenation of the module and hooknames together, times 329, plus the overhead of a PHP function?
Comment #8
dannyp commentedSorry, here's the trace.
Comment #9
m3avrck commentedVery interesting patch. Clearly the benchmarks are showing improvement which is great.
Moshe, I believe the speedup can be attested to the fact that isset() is extremely fast. This is apparent when compared to function_exists(). That would explain the speedup, and prove the sanity check :-)
Comment #10
dannyp commentedActually, my bet for the mechanism of the speed increase is that it actually has nothing to do with function_exists, rather, it's the time it takes to allocate memory and copy "$module_$hook" into it (and then to free it upon return) - I am no expert on PHP internals, but it would strike me as something that would require ('the equivilent of' if PHP does internal memory management, else 'an actual') malloc and free call and the time required to copy the string.
Apparently, based on the benchmarks and the profiling indicating that function_exists isn't where the time is being spent, that's more expensive than using the hashing and array functions to dereference the result from a multidimensional array.
I don't have the time to test it, especially given that it doesn't seem like it will be able to be used because modules can apparently be defined at runtime, but to test this hypothesis we could use a static array and then use as the key "$module_$hook" and see if the performance gain is lost.
Comment #11
m3avrck commentedBuilding upon this patch, we should repeat this logic in the theme layer, for example:
If we apply this same logic in the theme layer, we could *significantly* improve the performance of Drupal. Without a doubt, the theme area is the slowest area in Drupal. This trick that Danny points out, reused in the theme layer could show some significant performance boost.
Comment #12
m3avrck commentedAny updates? This patch seems pretty solid and worthwhile...
Comment #13
dannyp commentedI think it's near dead, because the functionality of defining a function in a node has to be maintained.
The alternative is to only cache the output if the function does exist (functions won't fall out of existance) but I think the slight performance gain we could have had here would be lost even more by doing so. If someone who has more time than me would like to play with that and see, go ahead.
Comment #14
owen barton commentedI can't reproduce any performance increase at all here:
ab -c1 -n500 on the homepage, default devel content generated and some blocks enabled.
First test:
Second test:
Comment #15
marcingy commentedBumping version
Comment #16
valthebaldFor impatient: patch seems non-relevant for current states of PHP/Drupal
Detailed version:
I have rerolled suggested patch for D8 and tested if it still relevant.
Server environment:
php 5.3.8 with suhosin patch (Debian testing), Apache 2.2.21
Drupal 8: 8.x-dev snapshot d78f6a6 - Patch #61456 by jeffschuler, edmund.kwok, jdefay, David_Rothstein, csevb10, alex_b, xjm, Steve Dondley: Aggregator titles display quotes and other characters with HTML entity equivalents badly (write tests).
Apache bench: ab 2.3 (bundled in Debian)
Tests were performed for the following configurations:
apc on, drupal cache off, CSS/JS aggregation off
apc on, drupal cache on, CSS/JS aggregation on
apc off, drupal cache off, CSS/JS aggregation off
apc off, drupal cache on, CSS/JS aggregation on
with drupal cache off, ab was run with -c1 -n500 parameters
with drupal cache on, ab was run with -c10 -n5000 parameters
after each configuration change, drupal cache was cleared (via admin/config/development/performance), and 5 identical runs of ab were performed.
First run was ignored to compensate cache filling effect, remaining 4 series combined to produce average result.
Finally, test results (less is better):
As you see, results differ within standard deviance.
My guess is that later versions of PHP made internal symbol table more effective.
I suggest to mark this "won't fix", please advise
Comment #17
owen barton commentedComment #18
damien tournoud commentedThe real reason is that the implementation cache kicks in: only direct hook invocations go through
module_hook()in Drupal 7+.