Improve PHP performance try php __autoload()
Of all magic in PHP I probably like the __autoload() hook the most. It saves a good deal of tedious script inclusion calls and may drastically speed up your application by saving the parser from doing unnecessary work. Allthough it has been around since the release of PHP5, I havenât found any convincing applications for it yet. Most of them follow the same scheme: Whenever an undefined class is being instantiated, a little __autoload() function tries to include a PHP file, which has to be named after itâs class:
< ?php
function __autoload($name) {
require_once(âclasses/â.$name.â.phpâ);
}
?>
Loading smartly
What if we had a little âclass finderâ, which searched directories recursively for PHP scripts and parsed each one of them for class definitions? One, that would be aware of all classes in those folders and tell us which file to find them in. We could combine this with __autoload() to help it find any required class by itself. âThatâs silly, it would produce way to much overheadâ, you might say. Thatâs correct! So what if we would cache the results after each search, knowing that the file structure rarely changes, unless a developer is working on it? Of course, Iâm talking about the best way of caching, thus generating the class list as PHP code and saving it for later use.
No sooner said than done. I wrote a class which implements this idea and pretentiously called it âSmartLoaderâ, as itâs smart enough to find any class of your PHP application without any help. You can download it here under the Lesser General Public License. Now letâs take a closer look on how it works:
Behind the scenes
Step 1: SmartLoader recursively searches for PHP scripts and parses them for containing classes with the following regular expression:
(interface|class)\s+(\w+)\s+(extends\s+(\w+)\s+)?(implements\s+\w+\s*(,\s*\w+\s*)*)?{
Step 2: We now have a list of all available classes and where to find them. This list will be converted to PHP code and written to a cache file. Itâs contents will look similar to this:
< ?php
// this is a automatically generated cache file.
$GLOBALS[âsmartloader_classesâ][âMainâ] = âclasses/main.class.phpâ;
$GLOBALS[âsmartloader_classesâ][âIterableâ] = âclasses/containers/iterable.class.phpâ;
$GLOBALS[âsmartloader_classesâ][âActiveRecordâ] = âclasses/database/activerecord.class.phpâ;
/* etc. */
?>
Getting ready
smartloader.class.php contains the autoload function as well as the actual SmartLoader class. The only thing that has to be done is to customize the autoload method:
< ?php
function __autoload($class_name) {
/* using a static loader object rather than a singleton to reduce overhead */
static $ldr = null;
/* initializing loader */
if(!$ldr) {
$ldr = new SmartLoader();
}
/* defining cache file, make sure write permissions */
$ldr->setCacheFilename(âcache/smartloader_cache.phpâ);
/* adding directories to parse. better use absolute paths. */
$ldr->addDir(âclassesâ);
/* what are the endings of your class files? */
$ldr->setClassFileEndings(array(â.phpâ, â.classâ));
/* should SmartLoader follow symbolic links? */
$ldr->setfollowSymlinks(false);
/* it should probably ignore hidden dirs/files */
$ldr->setIgnoreHiddenFiles(true);
}
/* load the class or trigger some fatal error on failure */
if(!$ldr->loadClass($class_name)) {
trigger_error(âCannot load class ââ.$class_name.âââ, E_USER_ERROR);
}
}
?>
Advantages
- Convenience: SmartLoader simplifies class file management. You can rename them, move them around or reorganize them in (package) folders. As long as they are in your webspace, SmartLoader can find them.
- Speed: With SmartLoader, class files are only loaded when they are actually needed. This approach called âlazy loadingâ or âjust in timeâ (not to confuse with interactive programming) can save PHP a lot of parsing and compiling caused by redundant inclusions.
- Portability, Backwards Compatibility: You can easily adopt SmartLoader without breaking your existing applications. __autoload() only gets involved when a non-existent class is being instantiated by default.
Potential pitfalls
- Error handling: You may use any flavor of error handling you like. Well, almost: Exceptions canât raise through __autoload(). Remember, thatâs a feature, not a bug. It is possible though with a scary eval() hack but I wonât go further into that.
- Version control systems: If your webspace is a working copy of some version control system you should probably tell SmartLoader to ignore hidden files. This will improve itâs performance and prevent it from scanning those spicious outdated copies of files sitting in the .SVN/.CVS folders.
- I shouldnât be telling you that, but donât let SmartLoader scan symlink loops.
- Profiling: Zend Profiler gets confused by SmartLoader and starts calculating invalid results for itâs execution time.
- Opcode caches: I donât know the inner workings of APC, Zend Optimizer and the likes well enough, but I can imagine that dynamic inclusions as used in SmartLoader negate the performance gained by opcode caching. I havenât been able to verify this, since Zend Profiler refuses to work properly with SmartLoader (see above). Iâd be happy to receive any feedback on this matter.
Originally by Maarten Manders from SitePoint Blogs on November 23, 2005, 3:13am
Related Posts