Multiple PHP classes in one file - php

I have multiple PHP classes with approximately 20 functions each all in one PHP file. Will the server store every class and every function in memory once I include this file?
Or will it only load the class and its functions once I instantiate like so?:
$ajax = new ajax();
Or will the server only cache the functions that I specifically call?:
$ajax->make_request();
I'm wondering if it is OK to have so many classes and functions housed in one single PHP file or if I should put in some type of logic that includes only the classes and functions that are required for the job.

I think you are a bit confused about how PHP works.
Every request the PHP parser, parses the requested file, e.g. index.php
If index.php include's another file, PHP will the parse that file.
Once a PHP file is parsed, it is stored in memory with "byte codes" (an almost machine language), during that request.
Regardless of how many functions or classes are in a file, it will all be stored in memory for that request.
There are extensions like APC that cache these parsed byte codes in memory between requests, but they need to be added on to PHP.
It is however better (in terms of memory usage) to use auto loading for your classes.
http://php.net/manual/en/language.oop5.autoload.php
PSR0 is a good set of guidelines for autoloading classes:
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md

The logic you need is called "Autoloading",
this is the process to include magicaly the class Ajax when the php executable hit a new Ajax(); instruction.
This way, there is never useless classes loaded in memory.
Look at PSR-0 and this good ClassLoader component.
(If you only have 20 classes on your project, you don't need to add an autoloader - the profit will be very low).

No, server by default will not cache anything unless it is set up to cache stuff with use of APC or similar extensions. So if your code uses all these classes then it would be perhaps better to put them in one file to reduce I/O. But if you do not use, separate the code into logical classes, put into separate file and use autoloading.

Related

PHP: bootstrap.php

What is bootstrap.php? I got a project that in the .htaccess reads SetEnv AE_BOOTSTRAP /full/path/to/_app/bootstrap.php
However, that file does not exist in the project... Is this something from PHP?
No, bootstrapping is not a part of PHP. Rather it is a file that is generally ran at installation time, or with PHP for every request, that takes care of making sure everything is included and general startup procedures are taken care of.
You can find more information about BootStrapping here .
It's not a PHP feature but just some code that is executed at the start.
With regards to computer technology, “bootstrap PHP code” means creating a bootstrapper that handles all the dynamic requests coming to a server and apply the true MVC (Model View Component) framework so that in future you can change the functionality for each unique component or application without changing the entire code or application.
This file should be on the server otherwise, nothing can be assigned via code...
bootstrap.php is just a conventional name for a PHP file that loads up your project environment. If you have a .htaccess that's pointing to one that doesn't exist, that sounds like garbage left over from a dead software installation.
That's probably a line from a previous (or current) php framework, which would use that constant to define the path to their bootstrapping script.
A Bootstrap is a script consisting of multiple clasees definitions in a single file, to reduce overhead of large variety of classes.

require_once at the beginning or when really needed?

Where should I put require_once statements, and why?
Always on the beginning of a
file, before the class,
In the actual method when the
file is really needed
It depends
?
Most frameworks put includes at the beginning and do not care if the file is really needed.
Using autoloader is the other case here.
Edit:
Surely, we all agree, that the autoloader is the way to go. But that is the 'other case' I was not
asking here. (BTW, Zend Framework Application uses autoloader, and the files are still hard-required, and placed at the beginning).
I just wanted to know, why do programmers include required files at the beginning of the file, even when they likely will not be used at all (e.g. Exception files).
Autoloading is a much better practice, as it will only load what is needed. Obviously, you also need to include the file which defines the __autoload function, so you're going to have some somewhere.
I usually have a single file called "includes.php" which then defines the __autoload and includes all the non-class files (such as function libraries, configuration files, etc). This file is loaded at the start of each page.
I'd say 3. It depends. If you're dealing with a lot of code, it may be worth loading the include file on request only, as loading code will take time to do, and eat up memory. On the other hand, this makes maintenance much harder, especially if you have dependencies. If you load includes "on demand", you may want to use a wrapper function so you can keep track of what module is loaded where.
I think the autoloader mechanism really is the way to go - of course, the application's design needs to be heavily object oriented for that to work.

How many PHP includes are too many?

Each page on my website is rendered using PHP.
Each PHP file uses around 10 includes. So for every page that is displayed, the server needs to fetch 10 files, in addition to the rest of its functions (MySQL, etc).
Should I combine them into a single include file? Will that make ANY difference to the real-world speed? It's not a trivial task as there would be a spaghetti of variable scope to sort out.
Include files are processed on the server, so they're not "fetched" by the browser. The performance difference of using includes vs. copy and pasting the code or consolidating files is so negligible (and I'm guessing we're talking about in the 10 ms to 100 ms range, at the absolute most), that it isn't at all worth it.
Feel free to include and require to your heart's content. Clean code is substantially more important than shaving less than 100 ms off a page load. If you're building something where timing is that critical, you shouldn't be using PHP anyway.
What takes time is figuring out where the files are actually located in the include path. If you got multiple locations in your include path, PHP will search each location until it either finds the file or fails (in which case it throws an error). That's why you should put the include path where most of the included files are to be found on top of the include path.
If you use absolute paths in your include path, PHP will cache the path in the realpath cache, but note that this gets stale very quickly. So yes, including ten files is potentially slower than including one large file, simply because PHP has to check the include path more often. However, unless your webserver is a really weak machine, ten files is not enough to make an impact. This gets only interesting when including hundreds of files or have many locations to search, in which case you should use an OpCode cache anyway.
Also note that when including files, it is not good practice to include each and every file right at the beginning, because you might be including files that are never called by your application for a specific request.
Reference
http://de2.php.net/manual/en/ini.core.php#ini.include-path
http://de2.php.net/manual/en/ini.core.php#ini.sect.performance
http://en.wikipedia.org/wiki/List_of_PHP_accelerators
Although disk I/O operations among the biggest performance-eaters, a regular site won't notice any sensible number of includes.
Before you hit any problems with includes, you probably already would have some opcode cache that eliminates this problem too.
include\ andrequires` only open file on the server side, but that might be time consumming depending on the hardware/filesystem, etc.
Anyway, if you can, use autoloader. Only needed files will be loaded that way.
Then if you think included files are a source of slowdown (and I think there is a lot of other points to look for improvement before), you can try to automatically merge the files. You still have one file per class when developping, but you can build a file that contains each class' definition to have only one include (something like cat <all your included file>.php > to_include.php).

Optimize PHP framework loading

I have a custom built application framework written in PHP which I have been tasked to optimize. This framework is a shared codebase which loads MVC "modules" to provide various functionality. Each module is a directory containing multiple PHP classes for controllers and models and PHP files for views.
The entire framework loads for almost all requests, including images and stylesheets. This is because the modules are designed to be self contained packages, and they may contain images, stylesheets, javascripts or other static files within them. Because of this, there is overhead in serving what would normally be a very simple request because the system has to load all the modules just to determine what modules are available from which to pull static files.
The general process for handling any given URI is as follows:
All base system classes are included
A global exception handler and some global variables are set
A system-wide configuration file is read. (This is a file filled with PHP statements to set config variables)
A connection to the database is made
The modules folder is scanned via opendir() and each module is verified to be valid and free of syntax errors, and then included.
A second configuration file is loaded which sets up configuration for the modules
A new instance of each module is created (calling it's __construct() method and possibly creating other database connections, performing individual startup routines, etc)
The URI is examined and passed off to the appropriate module(s)
Steps 1 - 7 will almost always be exactly the same. They will always perform the exact same operations unless new modules are installed or the configuration file is changed. My question is, what could be done to optimize the process? Ideally, I'd like some sort of way of handling multiple requests, similar to the way KeepAlive requests work. All the overhead of initializing all modules seems like a waste just to readfile() a single image or css file, just to have that same overhead again to serve another request.
Is there any way to reduce the overhead of a framework like this? (I don't even know if anyone can help me without studying all the code, this may be a hopeless question)
It's generally a bad idea to tie up a dynamic web server thread serving static content. Apache, IIS, Nginx, et. al. already do everything you need to serve up these files. If each static asset is located somewhere within the public docroot and has a unique URL, you shouldn't need to worry about PHP being involved in loading them.
Furthermore, if you can ensure that your cache-related headers (ETag, Last-Modified, etc.) are being generated correctly, and each client should only request each file once. Free caching == win!
Is there a reason all of the modules need to be loaded for every request? Why not allow controllers to specify which modules they require to be loaded, and only load those which are requested?
Why not move step 8 before step 5? Examine the URL first, then load modules based on the results.
Another one:
each module is verified to be valid and free of syntax errors, and then included.
Are you really syntax checking files before including() them? If so, why is this necessary?

How to create a fast PHP library?

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.
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
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.
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.
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');
}
}
}
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.
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.
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).
Use a profiler. If you try to optimise without having measures, you're working blind.

Categories