
PHP "require" Performance - bkrausz
http://www.gazehawk.com/blog/php-require-performance/
======
invisible
Always use Autoload if you can for large projects. The DRAMATIC performance
losses of requiring files and classes you do not ever use during a page load
can be pricey. Rasmus' quote was saying that PHP/APC can't save the opcode for
a file WITH all of the includes if there is any conditional associated with
the require. This means that each include's opcode will be pulled from cache
each time (not a big deal!!!). [2006, <http://pooteeweet.org/blog/538/>]

Things in favor of Autoload:

1) Ease-of-use of not worrying about if your class is available

2) If you don't use Autoloading and require clases, you have to load all of
those from the opcode cache (and make APC keep track of them) despite that you
may not be using many of those classes at all.

3) It helps encourage putting things in classes (whether they are static
functions or not).

4) If you ever need to conditionally require a class, you are likely going to
run into the same opcode cache hits (instead of NOPs) as Autoload. You'll have
to include ALL of your classes to avoid the problem.

~~~
skalpelis
I'm not sure #3 is really a benefit.

------
joshfraser
Keep in mind those numbers are microseconds. If you are looking for ways to
improve your performance, there are probably lots of other places to focus
your attention that will have a much greater impact. For example, optimizing
your frontend will give you far more bang for the buck and in fact I'd argue
that sometimes it's worth the extra 300 microseconds for the sanity of your
development team.

~~~
ericd
I don't believe he provided units, since it was over a large number of runs,
and the units would be relative and meaningless due to hardware and setup
differences (he said as much in the comments, as well).

------
wvenable
There should really be no reason why __autoload() should be significantly
slower than require_once(). It's even trivially easy to ensure your classes
are __autoloaded()'d from absolute paths to make opcode caches happy.

~~~
forgotusername
My initial thought was "surely it's just a quick hash lookup", but then
require_once is probably using the canonical path for that lookup, which
involves calling realpath() or abspath(), at that point all bets are probably
off, especially in a shared hosting environments involving things like NFS.

Edit: I looked at the implementation. require_once/include_once
unconditionally opens the file, whether it has been loaded already or not.
Attempting to follow that path through about 10 levels of indirection
(seriously), at some point the PHP implementation passes its notion of the
path back to Zend, which suggests possible abspath() etc. Also somewhere in
PHP's streams.c I see it unconditionally seek()ing the new file too.

If nothing else, then the layers of crap I just trawled through might cause
some slowness, if not some heavy library call like abspath().

I just remembered why I stopped using PHP. :)

~~~
spudlyo
Ugh, you're bringing up bad memories for me. I was once bit badly by the
require_once/realpath() problem.

require_once("/foo/bar/baz/random/crap/foo.php");

The above requires 5 lstat(2) system calls thanks to realpath() and a typical
WordPress-MU page load for us was calling lstat over 5k times. Over NFS that's
5k round trips to the server for every page load. Thankfully there is a knob
you can tune in PHP 5.1.x (realpath_cache_size) that caches all those lstats,
but as usual, the default is (16K) is too small to be of any use.

------
ck2
Hmm, PHP 5.2+ is _still_ that slow with _require_once_ ?

I thought they fixed that.

Anyway, just use _function_exists_ instead.

~~~
bkrausz
Yup, we're on 5.3. May have something to do with the relative vs. absolute
paths (we use relative), but still...

Turns out we didn't need require_once anyway, all but a couple of includes in
our entire codebase were in that one area.

~~~
nbpoole
Out of curiosity, what does your include_path look like? Is ./ the first
element, the last, or somewhere in the middle?

~~~
bkrausz
. is the first entry

------
Sizlak
Every time I see an article like this I thank God I'm not using PHP. It's
always, "Remember to always use do_something() instead of dosomething() or
else something will suck for some reason."

~~~
wvenable
This article is a serious micro-optimization and, in general, not something
people should be that worried about. If you nit-pick enough, all platforms
have these sorts of issues.

~~~
jessedhillon
In a good language, include/require[_once] should all be reduced to the same
one statement, e.g. Python's import. Don't you think it's a ridiculous notion
that the distinctions between include and require (and the once variants) are
meaningful enough that programmers should be able to express them?

~~~
evan0202
PHP using __autoload and namespaces looks and feels exactly like Python using
imports. You see, the PHP developers have been actively improving a lot of
aspects of the language recently, and the latest release, 5.3, had a ton of
really nice improvements and features, such as namespaces.

I'm not going to say PHP is the greatest language every invented, and in fact
I am a huge fan of Python. But I do not think PHP deserves the "In a good
language..." treatment. It is a language that is getting better everyday, with
a strong and vibrant development community and massive user adoption. It is a
good language.

~~~
ooh456
amen. nobody chooses to use php on new projects but at least it's easy, fast,
and pays the bills.

~~~
harisenbon
Really? I choose it every time I have a choice.

Especially with a Rails-like framework like CakePHP, I find that my programing
time is lessened dramatically because of the framework, and my processing time
is much lower than Rails because most of the servers I work on are optimized
out the wazoo for PHP instead of Ruby.

But your mileage may vary.

------
mkjones
One way to improve cpu-bound performance is to switch to something like HipHop
for PHP [1], which compiles PHP down to C++ and runs that. Granted, this
incurs a non-trivial switching cost.

However, it's scary to me that someone is suggesting the potentially fatal-
inducing use of "require" over "require_once" (if you call it twice on the
same file, you end up re-defining whatever classes or methods were required
and the script dies). It seems like optimizing for developer time and
simplicity over cpu utilization is better here. Using HipHop would incur a
one-time operational cost, but I suspect it would be worth the additional
developer and speed gains.

[1]: <https://github.com/facebook/hiphop-php/wiki/>

~~~
jonhohle
By using __autoload and a class/file naming convention, you can get away with
using just require, and not having to write require statements manually.
Decreased time for developers, and near optimal load times.

------
rexreed
I'm trying to understand the metrics here. Doesn't the first test show that
_autoload is actually much faster than require or require_once?

require_once: 1579 require: 1318 __autoload: 578

The second test shows a similar result:

require_once: 1689 require: 1382 __autoload: 658

Am I missing something here?

~~~
bkrausz
Yes, __autoload is much faster, because it only ends up loading ~5 of the
files. Previously we had included 30 files by default, and even though
__autoload is slower on a file-by-file basis, the savings on the files we
didn't need to load at all made it very worthwhile.

------
veb
There's a really nice discussion on Stack Overflow about this:

[http://stackoverflow.com/questions/186338/why-is-require-
onc...](http://stackoverflow.com/questions/186338/why-is-require-once-so-bad-
to-use)

~~~
bkrausz
The require vs. require_once was a byproduct of this research: I was really
interested in __autoload vs. require, as that seems to have fewer numbers
online for it.

------
KevBurnsJr
Asked author to include APC enabled/disabled as a variable in comparison.

Edit: APC was enabled

