views:

2181

answers:

9

For our online game, we have written tons of PHP classes and functions grouped by theme in files and then folders. In the end, we have now all our backend code (logic & DB access layers) in a set of files that we call libs and we include our libs in our GUI (web pages, presentation layer) using *include_once('pathtolib/file.inc')*.

The problem is that we have been lazy with inclusions and most include statements are made inside our libs file resulting that from each webpage, each time we include any libs file, we actually load the entire libs, file by file.

This has a significant impact on the performance. Therefore What would be the best solution ?

  • Remove all include statements from the libs file and only call the necessary one from the web pages ?
  • Do something else ?

Server uses a classic LAMP stack (PHP5).

EDIT: We have a mix of simple functions (legacy reason and the majority of the code) and classes. So autoload will not be enough.

+3  A: 

If you've done your programming in an object-oriented way, you can make use of the autoload function, which will load classes from their source files on-demand as you call them.

Edit: I noticed that someone downvoted both answers that referred to autoloading. Are we wrong? Is the overhead of the __autoload function too high to use it for performance purposes? If there is something I'm not realizing about this technique, I'd be really interested to know what it is.

Max
I am actually wondering the same thing. I have not noticed any serious overhead in my use of the __autoload function and it has served me very well.
Twan
Of course I am also interested in the answer.
Veynom
My guess is the downvote is because the poster has said autoload wont work becasue they have a mix of functions and classes.
Jonathan Arkell
My answer was posted before that edit was made to the question, so there must be another reason.
Max
Thats why I personally downvoted the answer. I removed the downvote once I realized that the specification that __autoload wouldn't work wasn't added until later, I removed the downvote.
Jonathan Arkell
+1  A: 

It's been a while since I used php, but shouldn't the Zend Optimizer or Cache help in this case? Does php still load & compile every included file again for every request?

I'm not sure if autoloading is the answer. If these files are included, they are probably needed in the class including it, so they will still be autoloaded anyway.

MattW.
+3  A: 

If you want to get really hard-core, do some static analysis, and figure out exactly what libraries are needed when, and only include those.

If you use "include" and not "include_once", then there is a bit of a speed savings there as well.

All that said, Matt's answer about the Zend Optimizer is right on the money. If you want, try the Advanced PHP Cache (APC), which is an opcode cache, and free. It should be in the PECL repository.

Jonathan Arkell
Thanks. I will update here when results will be available.We have Zend Optimizer already.
Veynom
+1  A: 

Use a byte code cache (ideally APC) so that PHP doesn't need to parse the libraries on each page load. Be aware that using autoload will negate the benefits of using a byte code cache (you can read more about this here).

Danny Amey
+2  A: 
  • Manage all includes manually, only where needed
  • Set your include_path to only where it has to be, the default is something like .:/usr/lib/pear/:/usr/lib/php, point it only at where it has to be, php.net/set_include_path
  • Don't use autoload, it's slow and makes APC and equivalent caches jobs a lot harder
  • You can turn off the "stat"-operation in APC, but then you have to clear the cache manually every time you update the files
thr
Ok, we will try APC after cleaing our include files. Thanks. I will update here when results will be available.
Veynom
Fredrik, can you recommend a good resource for learning about APC and why autoload mucks it up? I've never heard of APC before, and the PHP.net page isn't very clear on where it fits into application development.
Max
+1  A: 

You could use spl_autoload_register() or __autoload() to create whatever rules you need for including the files that you need for classes, however autoload introduces its own performance overheads. You'll need to make sure whatever you use is prepended to all gui pages using a php.ini setting or an apache config.

For your files with generic functions, I would suggest that you wrap them in a utility class and do a simple find and replace to replace all your function() calls with util::function(), which would then enable you to autoload these functions (again, there is an overhead introduced to calling a method rather than a global function).

Essentially the best thing to do is go back through your code and pay off your design debt by fixing the include issues. This will give you the most performance benefit, and it will allow you to make the most of optimisers like eAccelerator, Zend Platform and APC

Here is a sample method for loading stuff dynamically

public static function loadClass($class)
{
 if (class_exists($class, false) ||
  interface_exists($class, false))
 {
  return;
 }

 $file = YOUR_LIB_ROOT.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php';

 if (file_exists($file))
 {
  include_once $file;
  if (!class_exists($class, false) &&
   !interface_exists($class, false))
  {
   throw new Exception('File '.$file.' was loaded but class '.$class.' was not found');
  }
 }
}
Marc Gear
Also a good answer, thanks. I will update here when results will be available.
Veynom
A: 

edit : wrong place

e-satis
+1  A: 

Use a profiler. If you try to optimise without having measures, you're working blind.

troelskn
+2  A: 

What your looking for is Automap PECL extension.

It basically allows for auto loading with only a small overhead of loading a pre-computed map file. You can also sub divide the map file if you know a specific directory will only pull from certain PHP files.

You can read more about it here.

gradbot