loadModel Speed Testing

So the other day in #cakephp chat on irc.freenode.net (which by the way is a great place to hang out and help if you not busy, or just to learn too) , I had a discussion with a person in there about the use of $this->loadModel(); versus var $uses = array();

Their argument was that applying a model into the controllers var $uses would slow down an app as it scaled into a larger configuration. My argument was that it was easier to simply apply it globally to the controller, rather than a per case use, especially if you need it more than a couple of times within a controllers logic actions.

Well, as we both agreed to disagree, it didn't set well with me, as there was no proof either way. So, I set out to prove either my point, or their's as the case may be. I'd let the data tell the tale.

To be honest, I could see thier point. If you have a complex model and you apply it globally, you could essentially bring an app to it's knees. especially if the logic is written poorly. However after running some load tests, I have come to find that in most cases, applying a model globally is faster. How much faster you ask?

Well, first let me explain the testing scenario. I created 2 identical tables in a db. Next, I baked the project, and then did a bake all. The 2 tables are Foos and Bars. My theory is Foos, and thier theory is Bars. I then wrote an interface for the home page, and placed an Ajax script to run each set of tests seperately.

The following is an excerpt from the Bars controller. The only main difference between the Bars controller and the Foos controller is that within each private action i.e. Bars::__one() when FooModel is needed, it's loaded via $this->loadModel('Foo');. Where as, the Foos controller is simply set with BarModel in the $uses var.

<?php
class BarsController extends AppController {
 
	var $name = 'Bars';
/**
* This is the main test block. It itterates each test phase depending on the repeat setting.
*/
function stress($count = 1, $repeat = 1) { $this->sName = rand(0, 10); for ( $r = 0; $r < $repeat; $r++ ) { $this->__start_timer(); $this->__one($count); $this->__end_timer(); $totalTimeOne[$r] = ($this->iEndTime - $this->iStartTime); } for ( $r = 0; $r < $repeat; $r++ ) { $this->__start_timer(); $this->__two($count); $this->__end_timer(); $totalTimeTwo[$r] = ($this->iEndTime - $this->iStartTime); } for ( $r = 0; $r < $repeat; $r++ ) { $this->__start_timer(); $this->__three($count); $this->__end_timer(); $totalTimeThree[$r] = ($this->iEndTime - $this->iStartTime); } for ( $r = 0; $r < $repeat; $r++ ) { $this->__start_timer(); $this->__four($count); $this->__end_timer(); $totalTimeFour[$r] = ($this->iEndTime - $this->iStartTime); } for ( $r = 0; $r < $repeat; $r++ ) { $this->__start_timer(); $this->__five($count); $this->__end_timer(); $totalTimeFive[$r] = ($this->iEndTime - $this->iStartTime); } for ( $r = 0; $r < $repeat; $r++ ) { $this->__start_timer(); $this->__six($count); $this->__end_timer(); $totalTimeSix[$r] = ($this->iEndTime - $this->iStartTime); } $this->Bar->query('TRUNCATE TABLE `bars` '); $this->Bar->query('TRUNCATE TABLE `foos` '); $this->set( array( 'count' => $count, 'repeat' => $repeat, 'totalTimeOne' => $totalTimeOne, 'totalTimeTwo' => $totalTimeTwo, 'totalTimeThree' => $totalTimeThree, 'totalTimeFour' => $totalTimeFour, 'totalTimeFive' => $totalTimeFive, 'totalTimeSix' => $totalTimeSix ) ); if ($this->RequestHandler->isAjax()) { $this->layout = 'ajax'; } }   /**
* Begin Create Section
*/
function __one($count = 1) { for ($i = 0; $i < $count; $i++) { $this->data['Bar']['name'] = $this->sName; $this->data['Bar']['data'] = $this->sModelData; $this->Bar->create(); $this->Bar->save($this->data); } }   function __two($count = 1) { for ($i = 0; $i < $count; $i++) { $this->loadModel('Foo'); $this->data['Foo']['name'] = $this->sName; $this->data['Foo']['data'] = $this->sModelData; $this->Foo->create(); $this->Foo->save($this->data); } }   /**
* Begin Read Section
*/
function __three($count = 1) { for ($i = 0; $i < $count; $i++) { $this->Bar->findAll(); } }   function __four($count = 1) { for ($i = 0; $i < $count; $i++) { $this->loadModel('Foo'); $this->Foo->findAll(); } }   /**
* Begin Update Section
*/
  function __five($count = 1) { for ($i = 0; $i < $count; $i++) { $finds = $this->Bar->findAll(); foreach($finds as $find) { $this->data[] = $find; $this->data[]['Bar']['name'] = $this->sName . $this->sName; } $this->Bar->save($this->data); } }   function __six($count = 1) { for ($i = 0; $i < $count; $i++) { $this->loadModel('Foo'); $finds = $this->Foo->findAll(); foreach($finds as $find) { $this->data[] = $find; $this->data[]['Foo']['name'] = $this->sName . $this->sName; } $this->Foo->save($this->data); } } } ?>

There are some referrences to timers and such that are located within the AppController itself. I will be releasing this project into the public, for people to test it for themselves. Now, for the results. This set of results was a count of 5 and a repeat value of 5 as well.

 

Bar Stress Test

Total time for the complete run was 8.07537889481 seconds.

Create

Test One Test Two
0.096240997314453 0.054368972778320

Read

Test Three Test Four
0.053762197494507 0.052159786224365

Update

Test Three Test Four
1.867883205413818 5.950963735580444

Foo Stress Test

Total time for the complete run was 7.46506261826 seconds.

Create

Test One Test Two
0.057495832443237 0.048748731613159

Read

Test Three Test Four
0.047458887100220 0.050731658935547

Update

Test Three Test Four
1.726682186126709 5.533945322036744
 

Part 2 of this posting.

Add Comment