tags:

views:

91

answers:

3

My application uses a 'central' page controller that grabs a bunch of files (I hesitate to say libraries) each containing a few related classes, using require_once, before fetching the request. As in:

require_once (dir_lib . 'db.php');              
require_once (dir_lib . 'uuid.php');            
require_once (dir_lib . 'data.php');            
require_once (dir_lib . 'token.php');           
require_once (dir_lib . 'logs.php');            
require_once (dir_lib . 'time.php');

etc...

I haven't bothered to check memory usage until recently installing the (awesome, but gigantic) 'HTML Purifier' library and glancing at its autoloader. Apparently, autoloader on not, each script instance now weighs in at a whopping (sweet jesus!) 5376 kilobytes memory usage. (I have no idea what the built-in autoloader is for if that's the end result, but I digress) Without the HTML Purifier, most instances still weight in at over a megabyte.

Reading about the PHP autoload functions I'm getting the impression that the autoloader is meant strictly for OOP. With the exception of the purifier library, I'm using very little object-oriented code. Am I just misunderstanding the concept? Is there any other practical way to avoid blindly loading a bunch of classes that may not be needed for each request? Am I just being lazy for trying to include them all up-front?

EDIT -

Repeating this comment up up here to clarify what I meant by non-oo, if that makes much difference:

I am basically using classes in lieu of namespaces without using (hardly) any actual OOP. That is to say, the "DBFunctions" class may contain, for example, the functions "execute" and "getRow". The functions are invoked with a static method call such as "dbFunctions::execute($sql)."

+1  A: 

Using Autoload shoudn't hit performance as the class them selves aren't loaded until they are called or used. Autoload contruct basically loads class as needed is they haven't been instanciated already.

Find in the code where the class is been instanciated first. Unless class files are instanciated automatically, it shoudn't take any memory. Maybe not all are been instanciated, but not unset when not needed.

When you find where each is been instanciated or the one in question you can use then:

//Gets the object name using the class.
echo get_class($classinstance) , "\n";

You can handle it by placing some break points, using memory_get_peak_usage().

//Output memory usage at start of class instanciation.
echo memory_get_usage()
#memory_get_peak_usage() prior to 5.2.1.

$classobject1 = new theclass();

//Output memory usage after class instanciation.
echo memory_get_usage()

Now try the same thing but this time using unset() after class have been used:

//Output memory usage at start of class instanciation.
echo memory_get_usage()
#memory_get_peak_usage() prior to 5.2.1.

$classobject1 = new theclass();

unset($classobject1);

//Output memory usage after class instanciation.
echo memory_get_usage()

So basically in theory, unset any unused instance across app, find large objects, debug.

This is to clarify @greg's comments regards OOP:

Take this chunk as sample:

class Tun{
    private $run = 'i\'m running';

    function run(){
        echo $this->run;
    }
}

echo Tun::run;

Output:

Error: Fatal error: Undefined class constant 'run' in C:\Work\pro\debug.php on line 16

The above sample because is referencing a function which uses OOP, in this case the class private variable $run. Since the class isn't instantiated(an object instance), it will error out. So, yes you can use functions inside of a class by reference but they mostly have to be plain procedural or constant references.

Hope this help.

Codex73
Yeah, it's hard to tell where the problem might be without looking at the code. make sure your closing processes, loops, unsetting large instances, etc.
Codex73
Again, you're giving me more credit than I deserve. My functions are classed together by purpose but there are very few objects or instances of any sort. Most of it is straight procedural code. I use classes mainly as a way of grouping of related or interdependent functions and their host files as a way of chunking together related classes. I would hardly call this OOP. Am I wrong? So yeah, no instances. Straight function calls. ie: db::execute($sql)
Greg
@greg I've added some more info to my answer to clarify previous comment regarding OOP.
Codex73
@Codex73 I'll give that a try, thank you.
Greg
+1  A: 

PHP5's autoload is only for loading classes on the fly. Only one autoload function can be used in your application (but see below). Read the autoload docs for details. Basically, you can define an __autoload() function that will load any file you want (or do anything you want, for that matter), containing any classes you want, when PHP tries to call a class that isn't loaded yet.

The link that you provided in your question is about the Standard PHP Library's autoload, which is different, and more flexible. spl_autoload_register() lets you register a stack of autoload functions, rather than just one. This is most useful when you're using libraries in your code that make use of autoload, because their autoload doesn't have to clobber yours or those of other libraries.

If you're just starting out with OO on small projects, you probably just want __autoload(), but if you want to integrate libraries like HTMLPurifier, which does use spl_autoload, google for spl_autoload for the docs, they're the first results.

michaeltwofish
Thank you, that clarifies it quite a bit. However, like I said, I am not starting out with OO. The code procedural, using classes and static method calls in place of namespaces. (see my comment on tadamson's answer)
Greg
Even if you're just using classes as namespaces, if there is a way of mapping classes to files, you can delay loading the file by using __autoload().
michaeltwofish
+1  A: 

Is there a particular reason for those function files to not be classes? The only one I can think of would be PHP4 compatibility, but autoload doesn't exist in PHP4 anyway.

Just wrapping those existing code files in class DBFunctions { ... } and prefixing your function calls with DBFunctions:: to match should be enough to let the autoloader go to work (after setting an spl_autoload_register() callback to suit), and it's worth it. It's still stylistically procedural if you wanted to keep the code that way, and a decent step towards OOPifying your whole code base should you want to go that way.

(And HTML Purifier is an elephant, have you checked out PHP's internal filter functions?)

tadamson
If this clarifies it any, I am basically using classes in lieu of namespaces without using (hardly) any actual OOP. That is to say, the "DBFunctions" class may contain, for example, the functions "execute" and "getRow". The functions are invoked with a static method call, like you said, such as "dbFunctions::execute($sql)." Hope that makes sense. For your last question -- I found PHPs filter and related functions very limited if not outright broken. I do use my own regex filters to strip out non-ascii text, make data html-safe, etc. However, I need a true html purifier in places for WYSIWYG
Greg
In that case, autoload should be a good fit. If you can get by with it's default functionality it'll be much quicker, compiled C vs. a PHP function. As for HTML Purifier... hrm. For most huge OO apps (frameworks et al), using APC (http://www.php.net/apc) or a similar cache is always a good idea - looked into that at all?
tadamson
I haven't -- I'll take a look. Thank you.
Greg