Page 1 of 1

OOP, PHP and performance

Posted: Mon Jul 14, 2008 8:53 am
by eagleprof
I've been considering the whole question of OOP with respect to PHP and I was wondering if anyone can shed any light on how it affects performance.

My understanding, which is probably pretty limited, is that when a client makes a request to the PHP server, the server loads the page requested (plus any included files), parses and executes the code, and then gracefully closes the request and frees up any resources used in the request.

One of the (many) advantages of using objects is that it makes it easier to maintain state and share the values of the member variables between the member functions. However, if you look at it in terms of the model above, then this benefit is somewhat limited as state is not maintained between requests. This is a fundamental fact about programming with the web.

Also, since you don't want to have to work out which files to include on every page in terms of classes, then most people take the option of having one file list every class file and then just include that global class list. In any particular page request there are many classes you may not use and even many member functions you may not use in a class you do use in other ways. And I have noticed that there are a lot of people out there using classes in their PHP programming and many of these sites don't rate too well in terms of my performance.

So my question is, are my performance concerns founded? Is there a performance hit if we code many classes like this? Does PHP have a way of optimising the code out of the box without any extra add-ons? What are the real benefits of using classes in PHP (apart from the benefits of OOP in general)?

Pondering, pondering....

Re: OOP, PHP and performance

Posted: Mon Jul 14, 2008 9:04 am
by Eran
There are other ways such as using __autoload for loading classes. Also using caches such as APC and Memcached helps a lot
The real bottlenecks in the web-environment is usually not in the parsing of scripts, but rather in IO operations such as database queries. A good OO design will go a long way to help profile and optimize those bottlenecks, which more than offsets some minor performance loss due to abstraction and number of includes.

Re: OOP, PHP and performance

Posted: Mon Jul 14, 2008 12:41 pm
by Christopher
eagleprof wrote:So my question is, are my performance concerns founded?
The real question is: Do you have an actual performance problem? You can ponder all you want, but unless you have an actual performance problem then you are wasting your time. Improving the design of your code should be your main goal.

Honestly, I have never heard of or experienced a performance problem associated with using OOP. I have seen people try to loop excessively; I have seen lots of slow SQL queries; I have seen subsystems like email, LDAP, etc. perform poorly. But never the actual structure of the code cause a problem in PHP.

Re: OOP, PHP and performance

Posted: Mon Jul 14, 2008 2:24 pm
by alex.barylski
Depending on how you design or implement your system you might have a need to worry about performance.

As it's been said, using __autoload will only load the classes which are actually required.

Keep your classes simple and specific and you shouldn't experience any extraneous overhead. My only classes which are processed and take up extra time are my models, which I can accept.

I agree with arborint in that unless you have a performance problem don't bother worrying about it. On the same hand, what you have described above is fundemental issue which should be addresses ASAP. Unlike when dealing with a method which you "feel" is running poorly...I wouldn't bother improving it until I knew there was a problem with it.

Including classes lazy dazy and other such includes is horrible practice and will slow your application down no dought because every request might require 12 classes but you might be including 25 -- thats huge waste!

I would look into using __autoload for sure as it effectively eliminates this issue.

Cheers :)

Re: OOP, PHP and performance

Posted: Mon Jul 14, 2008 2:26 pm
by alex.barylski
Honestly, I have never heard of or experienced a performance problem associated with using OOP. I have seen people try to loop excessively; I have seen lots of slow SQL queries; I have seen subsystems like email, LDAP, etc. perform poorly. But never the actual structure of the code cause a problem in PHP.
Look at the classes in most projects. 20 data memebers 50 methods all in one class...that will likely create a bottle neck and slow things down but that isn't so much the fault of OOP but instead the bad practice of the developers responsible for the class.

Re: OOP, PHP and performance

Posted: Mon Jul 14, 2008 2:34 pm
by Christopher
Hockey wrote:Look at the classes in most projects. 20 data memebers 50 methods all in one class...
I have honestly just never seen anything like that. They may exist, but they can't be very common. So me code like that, that is causing a performance problem in any application anywhere...

Re: OOP, PHP and performance

Posted: Mon Jul 14, 2008 3:45 pm
by alex.barylski
SugaCRM:

sugarcrm/data/sugarbean.php

- 33 data memebers
- 94 methods

PHPMailer:

- 39 data memebers
- 52 methods

nuSoap:

- 13 data memebers
- 141 methods

CMSMS:

cmsmadesimple/lib/classes/class.module.inc.php

- 19 data memebers
- 191 methods

The list goes on and on... :P

In fact I can't think of a single open source project that uses classes that doesn't have at least one common class (used on almost every request) that is small enough for my likings.

Maybe I'm just pedantic (I know I am) but whenever a class has more than 5 or 6 data members or methods I start to reconsider the design and this has helped my application enormously in both understanding the codebase and improving execution time.

This is where I think developers split down the middle: Some of us see the big picture more clearly, whereas others are far better at handling details. Personally I get lost in details very quickly and become frustrated. I am much more capable in dealing with lots of simple objects and building the mental image in my head as to how they all work togather.

This does make it easy for new developers to start making changes, because simple objects are easier for anyone to comprehend and it also improves performance if you use __autoload(). However many developers clearly dislike having to work on multiple files at once and would prefer to keep code more monolithic. I'm not sure it's even about ignorance as to the advantages anymore, so much as it is a personal preference.

I think the disscussion of simplicity is just not black and white like I thought it was.

Personally I try and find other techniques to lesson the burden of dealing with multiple files...for instance I always store my templates separate from my views so I can easily switch between XHTML and HTML or PDF, etc. View objets are simple data objects which hold details like $title, etc.

The controller sets the View objects data memebers and sets the template based on what the output should be. The point is, my templates were stored in a core/templates folder and my controller/views were stored in separate folders. It was a PITA to constantly open the View class and then have to click around for the templates file. So what I did was (because of strict conventions) I wrote a small script to basically mirror the templates using soft links inside the View directories.

Now my editor opens the soft link and loads the template saving me from having to navigate away from the View class but not actually storing the templates in the same directory as View classes.

So in essence it's like having the View and templates at least in the same directory and that saves me a lot of accumulated time and hassle.

Cheers

Re: OOP, PHP and performance

Posted: Tue Jul 15, 2008 10:58 am
by Maugrim_The_Reaper
Look at the classes in most projects. 20 data memebers 50 methods all in one class...
Zend_Form springs to mind immediately ;). It's one of the biggest single classes I've seen in recent memory...

But large or not - sometimes a design calls for a large class. Maybe it's only doing one specific task but that task requires a lot of data points to be useful. I have a class here with around 20 properties and 40 accessors/mutators. All it does is handle configuration values but each value needs a sanity check or it will create havoc further down the line when used.

As for performance - if you can't measure or analyse performance of OO against a specific target then there's not much point worrying about it. Just take the sensible approach of knowing how and when to apply caching.

Using APC is a minimum requirement really since it's offer a significant performance boost in the area you are worried about - parsing files and compiling PHP to opcode. The whole load everything up front is usually a sign of an APC cache being present since loading everything at once is like priming a pump so users only experience cached performance and not the early loading slowdown.

But using OO is usually a minimal cost (esp. with APC) since IO ops, template rendering, big integer math (since ext/bcmath is crap compared to the much better ext/gmp ;)) and off-server HTTP requests cause the most problems. If you can cache those specifically you'll make a huge stride in maximising performance. You'd be surprised how many templates are continually rendered with unchanged data, or how many SQL queries return the same results 1000 time in a row.

If anything OO makes detecting the real slowdowns and applying caching a lot easier.

Re: OOP, PHP and performance

Posted: Tue Jul 15, 2008 11:21 am
by onion2k
I think those large classes are really more akin to using OOP as a system for encapsulating procedural code rather than actually doing things in an OOP way.

Re: OOP, PHP and performance

Posted: Tue Jul 15, 2008 11:56 am
by Christopher
Ok, proven wrong again! ;) It looks like PHPMailer and nuSoap (which were early PHP classes) do not use composition. The SugarCRM class is simply a design choice. It looks like a poor one, but I don't understand the problem well enough to know.

Two things: first, long methods is a code smell, not a code problem. Code smells indicate that there may be a problem, not that there is a problem (or they would be called "code problems").

Second, are those large classes causing a performance problem? I have used PHPMailer a number of times and never noticed a performance problem. I think I have used nuSOAP too without any performance problems. Certainly SugarCRM has been around long enough to be considered performant. That large class may have been combined from several classes for performance reasons for all we know. It is much smaller in older versions and does not have the diversity of functionality of the current version.

So back to the original question, it seems that even OOP implementations that use what we consider bad practices still do not have performance problems.

Re: OOP, PHP and performance

Posted: Tue Jul 15, 2008 4:16 pm
by alex.barylski
But large or not - sometimes a design calls for a large class. Maybe it's only doing one specific task but that task requires a lot of data points to be useful. I have a class here with around 20 properties and 40 accessors/mutators. All it does is handle configuration values but each value needs a sanity check or it will create havoc further down the line when used.
I would be hard pressed to agree with you on that one. In my experience, enough thought and consideration into the design of an object will always result in several smaller objects -- if it's large enough to bother refactoring.

The only classes in my own code library which are more than a few methods are typically the models -- actually only the models.

Code: Select all

 
createRecord()
returnRecord()
updateRecord()
deleteRecord()
 
selectAll()
 
movePage(); // Change parent association
 
swapPageOrder(); // Change page order/tab index
 
selectAllByKeywords()
selectAllByParentId()
 
_checkRecordHasValidEmail()
-checkRecordNotDuplicate()
 
While I don't think there is a "design problem" with the above API it can certainly be simplified once you fully understand the domain and use of the object.

For instance, the above resembles one such object of mine which is used to manage webpages stored in database table.

Lots of operations, but the object can be partioned into 3 different classes which result in cleaner code, more explicit code and more efficient code.

CRUD operations can go in their own class. They are usually only used by admin panel or page retrieval in the page delivery engine. Because the page delivery engine is used on every single request a user makes to a web site I was really bothered by the fact that advanced searching, filtering and page collating functions were also being tokenized/parsed and never/rarely executed.

Keeping CRUD funcitonality in a single CRUD class saved a lot of execution time.

Next was the advanced filtering or listings functionality typically used in frontend and backend searching. Should be a separate entity IMHO.

Lastly I group helper functions (if available) into a separate object.

When I generate the list of web pages in the admin panel the output resembles something of a tree where a root page has children and it's children might have children, etc.

Because I build this data structure without any SQL code just the CRUD and Advanced API I call it a helper model object. It contains methods for things like swaping page order, moving a page into a new parent, etc.

Consider this quick example:

Code: Select all

 
class Model_Page_Helper{
 
  function __construct()
  {
    $this->_crud = new Model_Page(); // Could just call methods statically as CRUD has no members -- TDG?
  }
 
  function movePage($pkid, $parentid)
  {
    $details = $this->_crud->returnPage($pkid);
 
    // No point in changing parent if it's the same as before
    if($details['parentid'] == $parentid){
      return false; // Not really a concern to end user -- so return false instead of throwing exception
    }
    
    // Update the $parentid ONLY -- use previous details for other attributes -- page now relocated 
    $this->_crud->updatePage($pkid, $parentid, $details['title'], $details['body']);
 
    return true;
  }
 
}
 
Why I like breaking classes down like this is simple...it makes code easy to comprehend, easy to maintain, easier to delegate work, more reusable and more logically partitioned. I know that Helper models conatin no SQL like the CRUD or Listings classes (I call them advanced but I am slowly renaming them 'collate' objects -- cause I'm a stickler for naming) each is used appropriately and excessive parsing is no longer a concern.

Yes I could take it one step further a have each method in it's own function and file...but then you'd loose the appeal of OOP so this is where I stop. :P
arborint wrote:Two things: first, long methods is a code smell, not a code problem. Code smells indicate that there may be a problem, not that there is a problem (or they would be called "code problems").
I guess we differ in opinion there...to me...wasted resources (excessive parsing due to long methods, lots of methods, etc) are not just a code smell but a code problem...
arborint wrote:Second, are those large classes causing a performance problem? I have used PHPMailer a number of times and never noticed a performance problem.
Have you then replaced it with SwiftMailer or an even lighter weight alternative and sent 10k messages? I have and it made a huge difference, so much so that I figure I could have probably scaled to host another 10 clients on the same server, which would equate to an additional $100/month on the same server.
arborint wrote:I think I have used nuSOAP too without any performance problems.
Never used it myself...but when I looked at the source code (which is the first thing I do before I use a library or application) I just about choked and started looking for something better...something leaner...something more simple...
arborint wrote:Certainly SugarCRM has been around long enough to be considered performant. That large class may have been combined from several classes for performance reasons for all we know. It is much smaller in older versions and does not have the diversity of functionality of the current version.
That codebase is a mess and it's hella slow on my shared server...when I switched to vTiger (which is based on Sugar) the user experience was improved 10 fold in terms of speed and response time. They use SugarBean as well but whether it's the AJAXy interface or improved codebase in the backend...it runs a lot smoother than Sugar. So I would say Sugar can use A LOT of improvement in terms of performance.
arborint wrote:So back to the original question, it seems that even OOP implementations that use what we consider bad practices still do not have performance problems.
Performance problems...no...performance issues...for me at least yes... :P

Personally, I would never use any of that code in my own applications...so large and complex anything could break at any time and I wouldn't even know where to begin. The fact that hundreds of lines of code and countless amount of memory were being used for no reason would make me shiver in my sleep.

Re: OOP, PHP and performance

Posted: Fri Jul 18, 2008 3:47 pm
by patrikG
The scripting language and the quality of the code is only one performance aspect. Check the chaching, the network infrastructure, load-balancer, route, data-sources, server-load, configuration and you'll most likely find issues with them causing performance hits. Writing quality code is great, writing quality code that performs really well is even greater, but it's a minor aspect of performance.

What matters is that you write code other people can understand two years down the line, code that helps you to be efficient about your job through re-use, clear architecture, modular design and so on. That's what OOP's big advantage is. Design first, efficiency second, performance a distant third (and if you've covered efficiency, you most probably don't need to worry about performance).