[TUTORIAL] Improving performance with JLoader::register()

Submit your own tutorials, guides and API documents for inclussion in the Official Developer Documentation.
User avatar
mjaz
Joomla! Guru
Joomla! Guru
Posts: 821
Joined: Thu Nov 10, 2005 10:08 am
Contact:

[TUTORIAL] Improving performance with JLoader::register()

Postby mjaz » Sun Oct 21, 2007 11:23 am

Hi guys,

I wrote a little tutorial about the autoload feature I developed with Jinx for 1.5RC4. As usual, edit as you see fit.

Mathias




Improving performance with JLoader::register()
----------------------------------------------------------------

Note: this tutorial applies to Joomla! 1.5RC4 or later.

1. Lazy loading
--------------

From http://en.wikipedia.org/wiki/Lazy_loading
"Lazy loading is a design pattern commonly used in computer programming to defer initialization of an object until the point at which it is needed. It can contribute to efficiency in the program's operation if properly and appropriately used."

PHP is stateless, so lazy loading is especially important: if we load more than we actually need on each request, it quickly adds up.

2. __autoload
-------------
PHP5 comes with a neat new feature: a special function called __autoload(), that allows us to forget about include and require statements, and that saves us some resources as well.

Let's start with a simple example that uses the 'classic' way of including class files.

Example 1:

mycomponent.php
require_once('myclass.php');

$obj = new MyClass();
?>

myclass.php
class MyClass {
    function __construct() {
        echo "MyClass constructed\n";
    }
}
?>

Of course, with this approach, you always need to make sure you have the necessary require statements, or you get an error. Most people solve this by putting the requires at the top of a file. Often many files are loaded and parsed, even when they aren't needed at all. To prevent this, we can rewrite the example using __autoload.

Example 2:
mycomponent.php
function __autoload($classname) {
    require(strtolower($classname) . '.php');
}

$obj = new MyClass();
?>

myclass.php remains the same.

So what happens?
new MyClass() tries to instantiate a new object of the MyClass class. The class doesn't exist; however, before throwing a warning, PHP will execute __autoload() with the parameter $classname = 'MyClass'. Inside the function we load the file myclass.php. Now PHP will check again if the MyClass class exists. If it doesn't, an error is generated, if it does, $obj is instantiated.

It's important to remember that __autoload will only be executed when a class doesn't exist. We can easily test that with the following example.

Example 3:
mycomponent.php
function __autoload($classname) {
    static $n;
    echo ++$n . "\n";
    require(strtolower($classname) . '.php');
}

$obj1 = new MyClass();
$obj2 = new MyClass();
?>

Output:
1
MyClass constructed
MyClass constructed


3. Problems
-----------
There are three problems that arise when using __autoload:
- Which files need to be loaded for which class?
- Only one __autoload function can exist
- What about PHP4?

The first problem is already partially solved in our example: We use a simple naming scheme for files and class, namely
. Each file only contains one class, with the same name as the file. Of course, when you have a lot of classes, you might want to use subdirectories. A possible solution would a naming scheme that reflects in the directory structure.

Example 4:
classes
    - filesystem
        - folder.php contains class Filesystem_Folder{}
        - folder.php contains class Filesystem_Folder{}
    - formats
        - images
            - jpeg.php contains class Formats_Images_Jpeg{}
            - png.php contains class Formats_Images_Png{}

Our autoload function now looks like this:
function __autoload($classname) {
    // DS is a constant containing the system's directory separator, either slash or backslash.
    $file = str_replace('_', DS, strtolower($classname)) . '.php';
    require(dirname(__FILE__) . DS . 'classes' . DS . $file);
}

4. How does Joomla! handle autoload?
------------------------------------
As mentioned above, only one __autoload() function can exists. In Joomla!, many plugins, modules etc are loaded each time, so these can't each have a separate autoload function. In PHP 5.1.2+, there is a function called spl_autoload_register(), which you can use to register your own functions to be used as autoload. See http://php.net/spl_autoload_register

In Joomla! there is a different approach: you can use JLoader::register(). It stores a list of classnames and their corresponding file.

Example 5:
JLoader::register('MyClass', 'somepath/myclass.php');
JLoader::register('OtherClass', 'somepath/otherclass.php');

if( $somecondition ) {
    $obj = new MyClass();
} else {
    $obj = new OtherClass();
}
?>

In this example, either myclass.php will be loaded, or otherclass.php, but never both.

Programmers are lazy of course, so you can automate the registration of the classes if you have a lot of them. Example 6 makes a list of all files in /classes and registers them with JLoader.

Example 6:
$classpath = dirname(__FILE__).DS.'classes';
foreach( JFolder::files($classpath) as $file ) {
    JLoader::register(JFile::stripExt($file), $classpath.DS.$file);
}
?>

5. PHP4
-------
PHP4 simply ignores __autoload. We worked around this in JLoader by simply loading all files immediately.

Example 7:
// in PHP5
JLoader::register('MyClass', 'myclass.php'); // myclass.php is not loaded yet
$obj = new MyClass(); // myclass.php is loaded, MyClass is instantiated

// in PHP4
JLoader::register('MyClass', 'myclass.php'); // myclass.php is loaded right away, MyClass now exists
$obj = new MyClass(); // MyClass is instantiated
?>

The risk is of course that in PHP4, many files are loaded that aren't necessary, resulting in lower performance. Another reason to tell your users to upgrade to PHP5!
Better SEO & multi-lingual Joomla sites with Nooku Content
http://www.nooku.org
Nooku Framework for advanced Joomla extension development
http://www.nooku.org/framework

Return to “Submit”

Who is online

Users browsing this forum: No registered users and 1 guest