PHP __autoload performance - php

I have a script that uses autoload to load classes that aren't found. I don't deliberately include the file (though I can) but I would like the autoload function to include the required files.
Because the script can be recursive, that is if the class is already loaded, I don't want to check the corresponding file is loaded and if class_exists on each recursion of the script.

If you want to avoid __autoload, you can use require_once instead of include.
The performance hit of using __autoload may be considerable, especially because some opcode caches do not support it properly. However, given it's very handy, I'd say use it unless your opcode cache does not cache autoload includes.

If you have your autoloader set up to load your classes and aren't using require (et al.) the autoloader will only be called if a class is referenced that doesn't exist. So there is never a need to check class_exists in the autoloader (it won't be called if the class exists).
With regard to performance. If you are using large libraries, autoload can actually be faster as it only loads the files/classes that are required. Either way the speed hit is pretty negligible in my experience (always use an opcode cache, as others have mentioned).

Related

performance hit with on demand loading of class files

In my recent projects a decided for a lazy, on demand load of class files with an autoloader. What is the performance hit of using an autoloader pattern for including class files as opposed to including the needed class files or all class files? Will it impact precompiling and caching?
In the majority of configurations, it will give a performance boost.
With just "out of the box" PHP, every file is compiled on demand when you include it. If you include every file on every request, every file is compiled on every request.
With OpCache enabled, each file is cached into shared memory when first compiled. However, that memory may get full, and there may be files that you never actually use, so compiling based on usage is still likely to be better.
With preloading, you can pre-populate OpCache's cache of compiled files. Classes from preloaded files will automatically be available to all processes anyway, so just won't trigger the autoloader.
The only time an autoloader could be costly is if you have multiple places that the same class could be defined, and the autoloading function checks the disk for which ones exist. That's why Composer has options to optimize its generated autoloading routines. If you're not using Composer already, I highly recommend you do so.

How to organize PHP code?

I'm writing an app in modular way, so I can possibly reuse some of the components. I've also written utility functions that are shared among different components. For example, if I have classes A (in A.php), B (in B.php), and C (in C.php), and a function f (in utils.php), and this function is used in both A, B, and C, how does one organize the code?
For testing purposes, I run A.php, B.php, and C.php separately, so I need to include utils.php in all of them. Is doing require_once 'utils.php' in all three files a good solution? I've heard there may be a minor performance issue with using require_once. Or should I maybe write a separate 'test.php', whre I would import all the files I need, and use that code for testing instead of writing tests in actual class files?
First of all, require_once is certainly not "too" slow for running your tests. Remember, premature optimization is the root of all evil. Yes, it has some overhead, but unless it causes errors or slows down your production environment, don't bother. Measure, measure measure.
A good strategy that i tend to use is similar to the one of Zend Framework.
My classnames are based on my directory structure. For example, a class named Http_Client_Curl would be lokated in the following directory:
Http/Client/Curl.php
With a structure like this, it's very easy and convenient to use auto loading. See spl_autoload_register. This means that you can let PHP automatically include all files and classes as you need them, based on a pretty straight forward convention.
If you are speaking in terms of PHP 5.3, I believe namespaces and auto-loading would fit right into your application fairly well. On the other hand, legacy code tends to be organized into "libraries" or "includes" with a core "includes.inc.php" that uses the factory method, or various other design pattern, to load the classes.
If you’re programming object oriented you’d also put the function f into a class; a utils class in your utils.php file.
require_once may have a minimal hit on performance as it will have to remember and check if a file has already been included, but it’s the best way to include files, to make sure you have the files you need. You can then include all the dependencies of that file/class.
Tests should of course not be in your class files. I don’t quite get if all your classes are for testing now or if you’re testing your classes …
Regarding require_once:
Yes, it has some performance issues. When you are sure you are including the file only once, don't put it, it's an unnecessary check.
Some advices:
Try to use absolute_path when calling require
The time difference between require_once() vs. require() is typically not that significant, with the exception of a very large application that has hundreds of require*() calls, which case it really is slow
Use an opcode cache, like APC!

Optimizing PHP require_once's for low disk i/o?

Q1)
I'm designing a CMS (-who isn't!) but priority is being given to caching. Literally everything is cached. DB rows, DB id queries, Configuration data, processed data, compiled templates. Currently it has two layers of caching.
The first is a opcode cache or memory cache such as apc, eaccelerator, xcache or memcached. If an entry is not found in there it is then searched for in the secondary slow cache, ie php includes.
Are the opcode caches actually faster than doing a require_once to a php file with a var_export'd array of data in it? My tests are inconclusive as my development box (5.3 of XAMPP) keeps throwing errors installing any of the aforementioned programs.
Q2)
The CMS has numerous helper classes that are autoloaded on demand instead of loading all files. Mostly each has a require before it so no autoloading needs to take place, however this is not the question. Because a page script can have up to 50/60 helper files included I have a feeling that if the site was under pressure it would buckle because of all the i/o that this incurs. Ignore for the moment that there is output cache in place that would remove the need for what I am about to suggest, and also that opcode caches would render this moot. What I have tried to do is join all the helper files required for the scripts execution in one single file. This is achievable and works well, however it has a side effect of greatly increasing the memory usage dramatically even though technically the same code is being used.
What are your thoughts and opinions on this?
Using a compiler cache like APC should help out as it will take your helper files and cache them after they are converted to opcode. That will mean the files will not only be cached but already in opcode so they do not need to be parsed and compiled each time they are required.
Looks like you just have no idea what you want to cache (and why).
You just cannot compare "opcode cache" and "require_once". Opcode cache will cache required code as well as other code.
First, keep in mind that your operating system will cache files in memory if they are being accessed frequently enough.
Also, don't use require_once. It is significantly slower than require. If you aren't using an autoloader, you should be. There is no reason to be manually including files in a modern php application (very few exceptions).
50-60 helper files is crazy. Isn't there some way to combine these? Can't you put them all in a related helper class, like OutputHelper or CacheHelper? That way you only have to include the class, which, again, should be taken care of your autoloader. It sounds to me you're doing something like putting one function per file.
Opcode caching greatly reduces memory usage and execution speed, but I'm not sure what effect it has on require statements.
I agree with ryeguy. require_once is slower than require or include because it has to log every include and check against it. If your only doing one require/include (which you should be for classes) then you don't need require_once or include_once.
Autoloading is great for optimization. As you only will load in classes when needed. So if your app has 500 classes, but only needs 15 to run a certain page/script. Then only those 15 get loaded. Which is nice.
If you take a peak at any big framework. You will notice that they have migrated to using autoloaders. They use to use require_once at the last moment like this example from the Zend Framework Version 1.
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception('Adapter name must be specified in a string');
Zend Framework Version 2 is going to be using auto loaders instead. I believe this is the fastest and it's also the easiest to code for.

Do PHP opcode cache work with __autoload?

Sorry if this is basic, I am trying to learn as much as I can about OO in PHP and I am slowly learning how to use it (very limited).
So I am wanting to know if __autoload() has any affect on PHP opcode cache's?
Opcode caches work (or at least should work) with autoloading but you can potentially take a performance hit from.
From Remember: be nice to byte code caches:
<arnaud_> does autoload have a performance impact when using apc ?
<Rasmus_> it is slow both with and without apc
<Rasmus_> but yes, moreso with apc because anything that is autoloaded is pushed down into the executor
<Rasmus_> so nothing can be cached
<Rasmus_> the script itself is cached of course, but no functions or classes
<Rasmus_> Well, there is no way around that
<Rasmus_> autoload is runtime dependent
<Rasmus_> we have no idea if any autoloaded class should be loaded until the script is executed
<Rasmus_> top-level clean deps would speed things up a lot
<Rasmus_> it's not just autoload
<Rasmus_> it is any sort of class or function declaration that depends on some runtime context
<Rasmus_> if(cond) function foo...
<Rasmus_> if(cond) include file
<Rasmus_> where file has functions and classes
<Rasmus_> or heaven forbid: function foo() { class bar { } }
and this mail from Ramus:
To clarify, of course conditionally
included files get compiled and
cached. The issue is not the included
files but the resulting conditionally
defined classes and functions needing
to be redefined on every request.
Whether that is significant or not
comes down to the specifics of the
situation, but there is no doubt that
it is slower. It comes down to a NOP
vs. a FETCH_CLASS, for example and the
NOP is obviously way faster.
(Disclaimer : I only know APC)
What an opcode cache do is :
when a file is included/required, it take the full path to that file
check if the opcodes corresponding to that file are already in RAM (in opcode cache)
if yes, return those opcode so they are executed
if no, load the file and compile it to opcodes ; and store opcodes in cache.
The important point, here, is the entry point : the full path to the file.
What autoloading generally do is :
get the name of a class
transform it to the name of a file
include/require that file
So, the informations that are relevant for the opcode cache (full path to the file, and the fact that it is included/required) are still here.
In consequence, autoload shouldn't bring any trouble with op code caching.
(And, when using APC, it doesn't, as far as I can tell)

Caching always loading files in PHP

In my index.php file I always load some classes used later. From profiler it states it sometimes can take about 20% of entire code. Is there any improvement that can make this process faster?
I would try to make this list of classes shorter, but app is very big and checking all dependencies will be costly.
Op-code caches such as APC and eAccelerator store a compiled version of your scripts in a cache. This dramatically reduces memory usage and loading time for frequently used static scripts.
While using an opcode cache (such as APC) will reduce the impact of loading/parsing/compiling the class, you'll still be loading them all on every page load & doing whatever initialization accompanies a require_once() call. If you were to set up an autoload function then the classes won't be loaded until your code actually needs to use them. There's a little overhead involved in using a class autoloader but it makes the code easier to maintain.
As always, YMMV, so benchmark your application to see if it's worthwhile in your case.
You might want to look at apc php.net/apc

Categories