1

I've inherited a Class-based PHP site where every page of the site is its own Class. The index.php handles what page you view based on the p parameter, and then calls that specific Class. For example, the search page of the site is simply mysite.com/?p=search

One of the first lines in the index.php calls an Autoload.php file which does an include of every single Class-based page of the site. This means that no matter which page you are on, the script is loading every single other page/class.

My questions:

  1. There is NO connection between those pages/classes, so is it really necessary to load all of them on every pageload?
  2. Does it slow down the script having to include over 50 pages/classes on every pageload or is it negligible?
  3. If so, then shouldn't I do an if-based check to determine which page/class I should load based on the p parameter and ONLY load that one rather than load every page on every pageload?
  4. Or is there some other potential downside of doing that that I'm not aware of?
ProgrammerGirl
  • 3,157
  • 7
  • 45
  • 82

2 Answers2

3

That's a confusing name for the file, as autoloading is a mechanism in PHP that allows you to load classes as and when they are needed, a good solution when you have many classes and only a few will be needed for each execution.

For example:

function autoload($class_name) {
  $file = "classes/$class_name.php";

  // You could add some checks here (e.g. whether the file exists, whether the
  // class indeed exists after the file is loaded) to facilitate better errors,
  // of course this would marginally increase the time needed to load each class.

  require $file;
}

// Register the `autoload` function with PHP's autoload mechanism
spl_autoload_register('autoload');

// This will execute `autoload('Class')` (unless `Class` is already defined)
$instance = new Class;

So, to answer your questions:

  1. It is not necessary to load them all, however classes that are used must be available, either by loading them all together (current situation), loading them conditionally (if(p == 'whatever') require 'classes/whatever.php'), or by using autoloading.

  2. There is some delay whenever a file is included as the file must be parsed/executed. PHP is fairly fast but still, including files you do not need is a waste. If you're using bytecode caching, the retrieved bytecode must still be executed.

  3. That is one avenue of improvement, autoloading presents a more dynamic alternative.

  4. Dependencies may be a problem if any of your page classes depend on another class, as your conditional loading could get very bloated.

Also a little additional material regarding bytecode caching, if you're using it:

The summary seems to be that, as long as you use include or require to load the file, bytecode caching will work as intended.

Community
  • 1
  • 1
connec
  • 7,231
  • 3
  • 23
  • 26
2

Using conditional require or include is slow.

Just require_once all classes in the main file you mentioned without any conditions, right in the global scope. The compiled code will be cached as one and you won't suffer a penalty from loading extra code at runtime.

Edit: You will benefit from having PHP APC enabled or some other PHP accelerator.

Edit 2: PHP APC will become part of the core in PHP in future releases (this has been announced). You will benefit from PHP APC, regardless of wether you go with conditional loading, or load all at once. If you already have it, load all at once for your 50 pages might be just fine.

Edit 3: Download PHP APC source code and find a find file called apc.php. Run apc.php from your server to see some very nicely done APC status and statistics, among which current memory usage and max memory (also see here).

oxygen
  • 5,891
  • 6
  • 37
  • 69
  • PHP is compiled before execution. Loading PHP files at runtime is slow (conditions force loading at runtime). From Wikipedia, since the php.net website is down: "Since PHP 4, the PHP parser compiles input to produce bytecode for processing by the Zend Engine, giving improved performance over its interpreter predecessor.". – oxygen Jun 09 '12 at 15:34
  • Sorry disagree about just saying: "Just require_once all classes in the main file you mentioned". I don't think that's good advice for code maintainability likewise using require_once is generally not recommended as you do still suffer a performance hit (albeit with APC not much) by using _once. I would say connec's answer is better and would result in a cleaner coding practise, as what happens when you create another 50 scripts (just add another 50 lines of code I suppose?). – Steve H Jun 09 '12 at 16:20
  • When loading dependencies such as class, function and constant definitions, redefinition is not allowed. Of course require_once is the way to go. He already has a mess. His "views" are classes, instead of simple PHP files (template like). 50 pages are easy for an op-code cache, and the question's author asked about the speed of loading classes, and that's what I was answering, please read the question before downvoting an answer. – oxygen Jun 09 '12 at 16:31
  • "I don't think that's good advice for code maintainability". He already has a central file (index.php) where he is already loading all classes. There's nothing in my advice changing that. Also, my advice is rather an answer to a performance question, which does not improve and/or does not reduce code maintainability. – oxygen Jun 09 '12 at 16:38
  • The usefulness of this really depends on whether or not @Programmer is using an opcode cache. If he is not, requiring all classes on every execution is very inefficient, sufficiently so that autoloading or conditional including will probably offer savings. In the event he is using a cache, little is lost by using autoloading and adding new classes is a lot easier (just add the class file in the expected place and you can start using the class, rather than adding a new `require_once` line somewhere). – connec Jun 09 '12 at 16:42
  • "rather than adding a new require_once line somewhere". I was proposing adding all require_once in one place (index.php) (of course this will not work if all page classes have the same name, but if things are that messy, I don't see any choices here). – oxygen Jun 09 '12 at 16:49
  • @Tiberiu-Ionuț Stan - yes I did read the question thanks, I was mainly referring to the OP question 4 (which maintainability is a valid downside to using require_once for all files, do you not agree?). I would also argue that he wouldn't probably need to use require_once (require would suffice) for the files since the files are all loaded in a central place (but again could be argued). Lastly from what I remember you had to configure APC to deal with *_once calls correctly as it didn't play nice with them VS require / include which it cached correctly? – Steve H Jun 09 '12 at 17:02
  • There is no maintainability cost if all requires are in a single file. – oxygen Jun 09 '12 at 17:13
  • Lastly even from a performance perspective without knowing the app I don't think you should say "The compiled code will be cached as one and you won't suffer a penalty from loading extra code at runtime" as you assume running opcache and also it just does not make sense, period. What if one page only uses 3 classes - just seems total inefficient, using APC to override this problem is just a band aid. Like I said better answer is connec's AND use APC. Yes 50 lines of code needs to be maintained - for example what if OP wanted to change the folder layout / change a class name? – Steve H Jun 09 '12 at 17:13
  • Please refer to these links for further reading / perspective: http://stackoverflow.com/questions/186338/why-is-require-once-so-bad-to-use and http://stackoverflow.com/questions/209728/php-opcode-caching-zend-acceleration-and-include-once-vs-require-once – Steve H Jun 09 '12 at 17:23
  • "as you assume running opcache and also it just does not make sense, period." It does make sense. The include language construct/function actually states in the documentation it is suposed to act as if the included file's contents are inserted in that position. Thus it is legal (and practiced) by optimisers to make it all a whole, if an unconditioned include is found in the global scope. – oxygen Jun 09 '12 at 17:30
  • @Tiberiu-Ionuț Stan: I think we will have to agree to disagree on this one (but your answer could greatly be improved, hence down vote). In a nutshell the answer to the OP questions should be 1) No, 2) Yes, 3) See connec's answer, 4) Yes, maintainability. Granted we have to make a number of assumptions from the provided question, but assuming the OP can / will have to use APC should not be one of them. A safer assumption would be that performance would be better only loading the required classes (hence autoloading) - much cleaner, and you would have to assume better. Lastly benchmark the app. – Steve H Jun 09 '12 at 18:20
  • I have already brought argument against the "Yes, maintainability" thing, you have not addressed it. Please do not conclude what the answers should be while skipping a discussion, otherwise I don't see the point of this comment thread. – oxygen Jun 09 '12 at 18:24
  • The comment thread is not the same as a discussion and besides I thought I had addressed the maintainability thing (the OP question 4 - is that not clear?).I also can't see why you would have (assuming it was you) down voted my comments, other than because I down voted your answer? You have failed to address any of the things I mentioned to support your original answer. I really can't see why you think loading 50 files is a good idea when the solution (autoload) takes care of this problem, and without benchmarking on the specific app you would have to conclude this is a better answer. – Steve H Jun 09 '12 at 21:37
  • " had addressed the maintainability thing" I said you didn't address my argument against your claim, ignored it, and used your maintanability claim as a conclusion. I didn't downvote your comment (is that possible?). Please reread your maintainability claims in the first comments you made. I just had to disagree, given the situation presented by the author. – oxygen Jun 09 '12 at 22:08
  • This is my last comment, as we're going round in circles. I think you missed the point, I tried not to reiterate performance issues because connec had all ready quite rightly addressed the reasoning for using autoload in both answer and comments (which you chose to ignore). So you're answer was 'keep as is' and use APC, granted this could be true if a number of conditions were right. My point is this , because you don't know how many classes need to be loaded per instance it would be safe to assume loading all 50 classes is not only inefficient but also WILL effect performance (by how much we – Steve H Jun 10 '12 at 11:05
  • don't know). Therefore your answer 'just keep with require_once' is not really the best for performance (assuming the above is true). My problem with your answer was you just blindly said keep using the 50 require_once statements even though the OP has stated this could be a cause for concern (so YOU didn't really answer their FULL question(s) and too mention is pretty much frowned upon. Maintainability issues is part of a full answer (which relates to OP question 4) and is a valid reason of why MOST people use autoload. So without knowing more about the OP app I can't see how saying to .. – Steve H Jun 10 '12 at 11:11
  • continue to use require_once statements is best for performance (because it is not - assuming autoload is available). So unless the OP comes back and says autoload is not an option or at least 30 or 40 classes are used in EVERY request I can't see how not using autoload would be the best option. One question to you is, if APC is not available (for what ever reason) your answer is wrong, as the OP asked about performance, and of course loading classes using require_once (especially 50 when you don't even use them all) IS a performance hit, how much of a hit should be determined by benchmarking. – Steve H Jun 10 '12 at 11:16
  • This is a the third time you change your stance to match the development of the discussion, without invalidating your previous points. At least now you make a strong point that you are assuming. I was advising from experience, that 50 requires has no noticeable performance penalty (+ APC). – oxygen Jun 10 '12 at 12:58