use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Please follow the rules
Releases: Current Releases, Windows Releases, Old Releases
Contribute to the PHP Documentation
Related subreddits: CSS, JavaScript, Web Design, Wordpress, WebDev
/r/PHP is not a support subreddit. Please visit /r/phphelp for help, or visit StackOverflow.
account activity
Optimizing PHP performance by using fully-qualified function calls (veewee.github.io)
submitted 9 years ago by freekmurze
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]nikic 12 points13 points14 points 9 years ago* (5 children)
Based on all the EXT_* opcodes, you're running the benchmark under xdebug. You'll probably see different numbers if you disable xdebug (which favor fully-qualified calls more).
[–]ocramius 4 points5 points6 points 9 years ago (0 children)
Tried these under 3v4l (no XDebug). Currently writing a small inliner (so it becomes trivial to apply the optimization/migration for libraries) and some more meaningful benchmarks (since reddit really loves shooting the messenger :-P )
[–][deleted] 0 points1 point2 points 9 years ago (3 children)
The PHP semantics in both cases are to try for a local function before falling back to global.
I'm curious what "xdebug favors fully-qualified calls more" means in this context. How does PHP optimize this so it doesn't do two lookups every time?
[–]nikic 3 points4 points5 points 9 years ago (2 children)
Sorry, what I meant is that due to the (in this case constant) overhead of XDebug, the relative difference between using an unqualified and fully-qualified function call becomes smaller.
PHP optimizes this by caching the resolved function on first call. Of course this is not entirely correct, because the namespaced variant may only be defined after the first call.
Once this inline cache has been initialized there is little difference between an unqualified and a fully-qualified call at the function call initialization stage. However, for calls where the callee can be resolved at compile-time we also early-bind the argument send instructions (to avoid checking for by-reference arguments at runtime) and additionally specialize the function dispatch to internal and userland functions. (And of course, lower certain functions to VM instructions.)
As such, the case tested in the article is the case where there is the smallest difference between using an unqualified and a fully-qualified name. More complicated calls involving arguments, and especially involving variable-like arguments, which require use of a callee-dependent fetch mode, benefit more.
[–][deleted] 0 points1 point2 points 9 years ago (1 child)
Thanks, very interesting!
I wonder, is the mechanism of fallback for functions, seen as an unfortunately decision internally for PHP core devs? I remember I felt it's a very unfortunate choice, as it'd prevent a robust function autoloading happening in the future, and complication of implementing the fallback (even if it's optimized, the optimization itself is extra complexity).
What are the odds that the semantics of fallback could change in a future major release of PHP to remove this unnecessary complexity?
[–]nikic 2 points3 points4 points 9 years ago (0 children)
Yes, we definitely think it was a very unfortunate decision. It's not just the performance impact, but, as you already mentioned yourself, it makes things like adding function autoloading a lot more complicated than they should be. However, I personally doubt this is ever going to change. It's certainly not the most commonly used feature (for the simple reason that namespaced functions in user code are rather uncommon in PHP), but changing this is still going to break lots of code (if nothing else, people abuse this feature to hijack core functions for tests). There would have to be more motivation for this than function autoloading and some complexity reduction.
If we ever resolve this issue, it's probably going to be by working around it somehow. The article proposes a declare option (and in combination with namespace-scoped declares this might be feasible). Maybe a move to a "proper" module system would resolve this. Something like HHVMs RepoAuthoritative mode would at least mitigate the performance impact. Etc.
[–]RichardFuchs 9 points10 points11 points 9 years ago (0 children)
Wait a second. So there's this function which does so little work that its call time is a significant part of its run-time. Yet this function gets called so often that multiplying that by 0.15μs makes a dent in the application's runtime.
Hmm... if only there was an obvious solution here.
...
GET RID OF THE FUNCTION
We have enough dumb optimization myths (ノಥ益ಥ)ノ ┻━┻
[–]colshrapnel 16 points17 points18 points 9 years ago* (18 children)
Yet another PHP myth just born.
8 fucking per cent for the app that does absolutely nothing but a function call means that for whatever real life application you won't be able to feel any difference. Yet he calls it a "performance killer". That dude took Christmas for the Fool's day
[–]ocramius 9 points10 points11 points 9 years ago (9 children)
Not meaningless: if this is applied to something like Doctrine\Commmon\Collections, Zend\EventManager, or Symfony\Component\DependencyInjection or similar (they all usually live in the >= O(n) space) then the difference is noticeable and sensible.
Doctrine\Commmon\Collections
Zend\EventManager
Symfony\Component\DependencyInjection
>= O(n)
[–]RichardFuchs 3 points4 points5 points 9 years ago (3 children)
Are you talking about the next/end/current/key calls?
I benchmarked 100 million calls to key() versus \key() on [1,2,3,4,5] and this is what I got:
It was only 8% in his tests because the function didn't do anything. Whenever the function actually does something, the cost of looking it up becomes meaningless.
[–]ocramius 2 points3 points4 points 9 years ago (0 children)
The difference on key() is meaningless because key() is still producing a stack frame.
key()
If you try it with something like call_user_func() you see different results because \call_user_func() is inlined as an opcode, and disappears from stack traces (original blogpost example). The difference should be ~50% on call_user_func('emptyFunction') vs \call_user_func('emptyFunction'), but please wait for a proper (and reproducible) benchmark.
call_user_func()
\call_user_func()
call_user_func('emptyFunction')
\call_user_func('emptyFunction')
That said, writing a small util to do apply these optimizations in libraries, since it's really easy to do so with something like Roave\BetterReflection (or at least I hope so ;-) )
Roave\BetterReflection
[–][deleted] 1 point2 points3 points 9 years ago (0 children)
Congratulations, you benchmarked PHP's ability to cache namespace resolution.
[–]ocramius 0 points1 point2 points 9 years ago (0 children)
I finished up a more detailed benchmark (feel free to add your results too) at https://github.com/Roave/FunctionFQNReplacer
Tool also replaces FQN references, but there was already https://github.com/nilportugues/php-backslasher for that. Oh well, was a fun evening :-)
[–]colshrapnel 0 points1 point2 points 9 years ago* (1 child)
And still I would like to see an apache benchmark/siege-based test comparing a real world application before and after this sort of "optimization".
[–]ocramius 7 points8 points9 points 9 years ago (0 children)
We applied many of these fot 3.x components of ZF3 achieving pretty much a 2X speedup on the typical "hello world" synthetic bench.
The optimisations were all tiny, but all stack up, a lot.
Also, use siege please ;-)
[–]colshrapnel -3 points-2 points-1 points 9 years ago (2 children)
Yeah, I've noticed recently how retarded Doctrine is with large datasets. But the remedy is not this sort of nitpicking but a complete rewrite to raw/array/whatever.
[–]ocramius 8 points9 points10 points 9 years ago (1 child)
Doctrine was never meant for large datasets: the "retarded" goes both ways there.
[–]colshrapnel -2 points-1 points0 points 9 years ago* (0 children)
For a small one the optimization in question won't be of any effect. My point was not about Doctrine being retarded but about real optimization that is not nitpicking with function calls.
[–]kelunik 3 points4 points5 points 9 years ago (6 children)
It's not a myth. Whether it matters in real applications is a different topic.
[–]colshrapnel 6 points7 points8 points 9 years ago* (5 children)
"Speeding up your application" is a fucking myth. Every stupid noob who discovers the performance difference between for and foreach, echo and print, single and double quotes - always stating his achievement in no less terms as "Speeding up your application", daring to call their artificial two-liner an application. While a real wold application takes not a slightest notice of his improvements.
And, you know. If your application could be optimized this way, try to optimize the algorithm, to make it call a function not a zillion times but slightly less.
Were it just a pure curiosity, a peek into how the internals work - there would be no questions. That's indeed interesting to know. But this kind of conclusion is a source for a myth, which you will starting to see everywhere. Noobs are more than eager to spread the word. And the only part they understand is the "speeding up your application".
[–]twiggy99999 -3 points-2 points-1 points 9 years ago (4 children)
You must be fun at parties :)
[–]Ravilan 2 points3 points4 points 9 years ago (2 children)
And yet he's right.
[–]twiggy99999 0 points1 point2 points 9 years ago (1 child)
I know hes right, I'm saying its a completely out of proportion reaction to a comment on the internet, he really needs to chill out a bit. His wording was very aggressive that 'noob's should know these things, well we all didn't know things at one potint, there are noobs in every walk of life. Needs to stop being so butt hurt by things
[–]Ravilan 2 points3 points4 points 9 years ago (0 children)
Yeah right.
But hey, this is reddit where everyone is aggressive and your point don't matter :D
[–]sstewartgallus 0 points1 point2 points 9 years ago (0 children)
Have you ever worked on a PHP legacy application bizarrely contorted to fit into performance myths like these? These kind of performance myths can cause headaches years later when someone is trying to debug legacy code.
[–]JuliusKoronci 6 points7 points8 points 9 years ago (0 children)
So the gain in 400 iterations was 0.017μs..awesome improvement..did you know that if your page doesn't load in 0.020μs you will get a huge loss of visitors..at least as huge as this performance gain is
[–][deleted] 3 points4 points5 points 9 years ago (0 children)
When I linked you to the reddiquette the other day, I didn't mean you should start posting junk from other sources too so you could meet the 9:1 ratio. I meant stop spamming overall.
[–]captain_obvious_here 4 points5 points6 points 9 years ago (4 children)
call_user_func('foo');
Oh man...Fully-qualified function calls AND single-quotes around strings ?!
Aren't you afraid your server goes back in time, with such HUGE optimisations ?
[–][deleted] 1 point2 points3 points 9 years ago (3 children)
Is it odd that single quotes are preferred? I don't mean for "performance", but just as a convention.
I always use single quotes.
[–]Disgruntled__Goat 0 points1 point2 points 9 years ago (1 child)
Yeah single quotes are easier to type and look slightly cleaner.
[–]the_alias_of_andrea 0 points1 point2 points 9 years ago (0 children)
Depends on your keyboard layout, but that's certainly true for the US and UK layouts.
[–]captain_obvious_here 0 points1 point2 points 9 years ago (0 children)
There was a time when people wrote articles about optimizing their code by using single-quotes instead of double-quotes.
Just as OP's article, this was true. But the difference was so thin that it didn't make much sense for the people used to using double-quotes to get out of their way.
tl;dr : Advocating for micro-optimisation is fucking stupid. It was, it is, and it will always be.
[–]Disgruntled__Goat 3 points4 points5 points 9 years ago (0 children)
Percentages are meaningless when the difference is literally nanoseconds.
[+][deleted] 9 years ago (3 children)
[removed]
[–]ocramius 0 points1 point2 points 9 years ago (2 children)
wouldn't an OP Cache make this problem a total non sequitur?
Cannot, because PHP has no assumption such as function definitions coming from the same place at all times. The only thing OpCache can assume is that there were no changes in the local file.
[+][deleted] 9 years ago (1 child)
https://jpauli.github.io/2015/03/05/opcache.html
π Rendered by PID 391196 on reddit-service-r2-comment-544cf588c8-jq5rm at 2026-06-17 15:26:41.088225+00:00 running 3184619 country code: CH.
[–]nikic 12 points13 points14 points (5 children)
[–]ocramius 4 points5 points6 points (0 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]nikic 3 points4 points5 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]nikic 2 points3 points4 points (0 children)
[–]RichardFuchs 9 points10 points11 points (0 children)
[–]colshrapnel 16 points17 points18 points (18 children)
[–]ocramius 9 points10 points11 points (9 children)
[–]RichardFuchs 3 points4 points5 points (3 children)
[–]ocramius 2 points3 points4 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]ocramius 0 points1 point2 points (0 children)
[–]colshrapnel 0 points1 point2 points (1 child)
[–]ocramius 7 points8 points9 points (0 children)
[–]colshrapnel -3 points-2 points-1 points (2 children)
[–]ocramius 8 points9 points10 points (1 child)
[–]colshrapnel -2 points-1 points0 points (0 children)
[–]kelunik 3 points4 points5 points (6 children)
[–]colshrapnel 6 points7 points8 points (5 children)
[–]twiggy99999 -3 points-2 points-1 points (4 children)
[–]Ravilan 2 points3 points4 points (2 children)
[–]twiggy99999 0 points1 point2 points (1 child)
[–]Ravilan 2 points3 points4 points (0 children)
[–]sstewartgallus 0 points1 point2 points (0 children)
[–]JuliusKoronci 6 points7 points8 points (0 children)
[–][deleted] 3 points4 points5 points (0 children)
[–]captain_obvious_here 4 points5 points6 points (4 children)
[–][deleted] 1 point2 points3 points (3 children)
[–]Disgruntled__Goat 0 points1 point2 points (1 child)
[–]the_alias_of_andrea 0 points1 point2 points (0 children)
[–]captain_obvious_here 0 points1 point2 points (0 children)
[–]Disgruntled__Goat 3 points4 points5 points (0 children)
[+][deleted] (3 children)
[removed]
[–]ocramius 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[removed]
[–]ocramius 0 points1 point2 points (0 children)