[PHP] class object vs array for db table model

2010-10-12 Thread Tommy Pham
Hi everyone,

It's been a couple years since I've did a project in PHP.  The current
project I'm working on is for PHP 5.3 and I noticed a performance issue.  Is
it just me or is there a BIG difference in performance between class object
vs array for PHP 5.3?  Below is the sample:

class MyTable
{
private $_id; // int
private $_name; // varchar
private $_description; // text

public  function __construct() {}

public function getId()
{
return $this-_id;
}
public function getName()
{
return $this-_name;
}
public function getDescription()
{
return $this-_description;
}

public function setId($id)
{
$this-_id = $id;
}
public function setName($name)
{
$this-_name = $name;
}
public function setDescription($description)
{
$this-_description = $description;
}
}

$my_table = array ('id' = 'id value', 'name' = 'name value', 'description'
= 'long description text');

The above are representations for my table as class and as array,
respectively.  The only difference is how I represent the results from db:

1) as class object
$list = array();
while ($row = $db-fetch($result))
{
$my_table = new MyTable();
$my_table-setId($row['id']);
$my_table-setName($row['name']);
$my_table-setDescription($row['description']);

$list[$my_table-getId()] = $my_table;
}

2) as table
$list = array();
while ($row = $db-fetch($result))
{
$my_table['id'] = $row['id'];
$my_table['name'] = $row['name'];
$my_table['description'] = $row['description'];

$list[$my_table['id'] = $my_table;
}

The performance difference I get is about 1.4 seconds with the array in the
lead!!!  Does anyone have the same problem? 

Thanks,
Tommy

PS: The above executed in 4.2 sec and 1.8 sec (on average) respectively w/o
actually showing the results to html, while my ASP.NET project executes it
and displays in html in about 2 seconds for all 3684 rows, using class
similar to the MyTable.  All codes, PHP  ASP.NET C#, access the same MySQL
DB on the same development box.


-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] class object vs array for db table model

2010-10-12 Thread chris h
On Tue, Oct 12, 2010 at 2:38 AM, Tommy Pham tommy...@gmail.com wrote:

 Hi everyone,

 It's been a couple years since I've did a project in PHP.  The current
 project I'm working on is for PHP 5.3 and I noticed a performance issue.
  Is
 it just me or is there a BIG difference in performance between class object
 vs array for PHP 5.3?  Below is the sample:

 class MyTable
 {
private $_id; // int
private $_name; // varchar
private $_description; // text

public  function __construct() {}

public function getId()
{
return $this-_id;
}
public function getName()
{
return $this-_name;
}
public function getDescription()
{
return $this-_description;
}

public function setId($id)
{
$this-_id = $id;
}
public function setName($name)
{
$this-_name = $name;
}
public function setDescription($description)
{
$this-_description = $description;
}
 }

 $my_table = array ('id' = 'id value', 'name' = 'name value',
 'description'
 = 'long description text');

 The above are representations for my table as class and as array,
 respectively.  The only difference is how I represent the results from db:

 1) as class object
 $list = array();
 while ($row = $db-fetch($result))
 {
$my_table = new MyTable();
$my_table-setId($row['id']);
$my_table-setName($row['name']);
$my_table-setDescription($row['description']);

$list[$my_table-getId()] = $my_table;
 }

 2) as table
 $list = array();
 while ($row = $db-fetch($result))
 {
$my_table['id'] = $row['id'];
$my_table['name'] = $row['name'];
$my_table['description'] = $row['description'];

$list[$my_table['id'] = $my_table;
 }

 The performance difference I get is about 1.4 seconds with the array in the
 lead!!!  Does anyone have the same problem?

 Thanks,
 Tommy

 PS: The above executed in 4.2 sec and 1.8 sec (on average) respectively w/o
 actually showing the results to html, while my ASP.NET project executes it
 and displays in html in about 2 seconds for all 3684 rows, using class
 similar to the MyTable.  All codes, PHP  ASP.NET C#, access the same
 MySQL
 DB on the same development box.


When you are adding a row as an object you are calling 4 user
functions: MyTable::__construct(), MyTable::setId(),
MyTable::setName(),
and MyTable::setDescription().  This adds some overhead for sure, so you
might want to think about passing the row array into the construct and doing
away with the setters (at least for the initial instantiations).

Something like this...

-
public  function __construct($dataArray=null)
{
  foreach ((array)$dataArray as $rowKey = $rowValue)
  {
$this-$rowKey = $rowValue;
  }
}
==OR==
public  function __construct($dataArray=null)
{
  // maybe add casting here as well?
  $this-_id  = isset($dataArray['id'])?
  $dataArray['id']: null;
  $this-_name = isset($dataArray['name'])?
$dataArray['name']: null;
  $this-_description  = isset($dataArray['description'])?
 $dataArray['description']: null;

}
==And instantiate like this==
$list = array();
while ($row = $db-fetch($result))
{
  // I also changed setting the $list's key with $row['id'] instead of
using the MyTable getter.
  $list[$row['id']] = new MyTable($row);
}
---

I don't know how much faster that will run for you (if at all) but using
your method you were calling 5 user functions per result set from the db
(that's the construct, the getter to set the $list key, and 1 for each of
the 3 properties of the result) for a total of 18,420 user function calls.
 With my method I'm calling 1 user function (the construct) for each set,
for a total of 3,684 calls.  Of course a down-side is that if there's any
logic in your setters then that needs to be replicated in your construct.

Another method is to use a single object for all 3684 records.  Perhaps you
can use the built in Iterator interface which lets your class's objects be
used as if they were an array for the purposes of foreach loops.
http://php.net/manual/en/language.oop5.iterations.php
You would set a pointer to the record you wish to use, and your getters and
setters would key off that element of the master array.  This should be a
fast solution, while still giving you the power of encapsulation, getters
and setters.


Hope that helps!
Chris.


Re: [PHP] class object vs array for db table model

2010-10-12 Thread Tommy Pham
On Tue, Oct 12, 2010 at 4:45 AM, chris h chris...@gmail.com wrote:


snip



 When you are adding a row as an object you are calling 4 user
 functions: MyTable::__construct(), MyTable::setId(), MyTable::setName(), and
 MyTable::setDescription().  This adds some overhead for sure, so you might
 want to think about passing the row array into the construct and doing away
 with the setters (at least for the initial instantiations).
 Something like this...
 -
 public  function __construct($dataArray=null)
 {
   foreach ((array)$dataArray as $rowKey = $rowValue)
   {
     $this-$rowKey = $rowValue;
   }
 }
 ==OR==
 public  function __construct($dataArray=null)
 {
   // maybe add casting here as well?
   $this-_id              = isset($dataArray['id'])?
   $dataArray['id']: null;
   $this-_name         = isset($dataArray['name'])?
 $dataArray['name']: null;
   $this-_description  = isset($dataArray['description'])?
  $dataArray['description']: null;
 }
 ==And instantiate like this==
 $list = array();
 while ($row = $db-fetch($result))
 {
   // I also changed setting the $list's key with $row['id'] instead of
 using the MyTable getter.
   $list[$row['id']] = new MyTable($row);
 }
 ---
 I don't know how much faster that will run for you (if at all) but using
 your method you were calling 5 user functions per result set from the db
 (that's the construct, the getter to set the $list key, and 1 for each of
 the 3 properties of the result) for a total of 18,420 user function calls.
  With my method I'm calling 1 user function (the construct) for each set,
 for a total of 3,684 calls.  Of course a down-side is that if there's any
 logic in your setters then that needs to be replicated in your construct.
 Another method is to use a single object for all 3684 records.  Perhaps you
 can use the built in Iterator interface which lets your class's objects be
 used as if they were an array for the purposes of foreach loops.
 http://php.net/manual/en/language.oop5.iterations.php
 You would set a pointer to the record you wish to use, and your getters and
 setters would key off that element of the master array.  This should be a
 fast solution, while still giving you the power of encapsulation, getters
 and setters.

 Hope that helps!
 Chris.


Hi Chris,

Thanks for the reply.  The sample I made is just for simplicity and
comparison.  As for function calling 'get's, I think the speed would
come out to be same in your sample since you're doing isset()
checking.  My actual class is more sophisticated having the psuedo
overloading as you mentioned.  The class is generated from a PHP class
builder - to save on typing - I made a long time ago with some minor
update.

Anyway, I was frustrated as to why my code took so long to execute and
had to dig deep.  As it turns out, I had xdebug loaded with all
options on ... lol.  Removed the extension and all is good in the
world.  The script runs in less than 150ms :D!!!

Thanks,
Tommy

PS:  This is what I get for not coding in PHP so long ...

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] class object vs array for db table model

2010-10-12 Thread chris h
hehe that's pretty funny; also funny oversight of mine in regards to
isset()... so I guess we're both comedians today?  ;-)

Glad you got that worked out Tommy!

Chris.


On Tue, Oct 12, 2010 at 8:46 AM, Tommy Pham tommy...@gmail.com wrote:

 On Tue, Oct 12, 2010 at 4:45 AM, chris h chris...@gmail.com wrote:
 

 snip

 
 
  When you are adding a row as an object you are calling 4 user
  functions: MyTable::__construct(), MyTable::setId(), MyTable::setName(),
 and
  MyTable::setDescription().  This adds some overhead for sure, so you
 might
  want to think about passing the row array into the construct and doing
 away
  with the setters (at least for the initial instantiations).
  Something like this...
  -
  public  function __construct($dataArray=null)
  {
foreach ((array)$dataArray as $rowKey = $rowValue)
{
  $this-$rowKey = $rowValue;
}
  }
  ==OR==
  public  function __construct($dataArray=null)
  {
// maybe add casting here as well?
$this-_id  = isset($dataArray['id'])?
$dataArray['id']: null;
$this-_name = isset($dataArray['name'])?
  $dataArray['name']: null;
$this-_description  = isset($dataArray['description'])?
   $dataArray['description']: null;
  }
  ==And instantiate like this==
  $list = array();
  while ($row = $db-fetch($result))
  {
// I also changed setting the $list's key with $row['id'] instead of
  using the MyTable getter.
$list[$row['id']] = new MyTable($row);
  }
  ---
  I don't know how much faster that will run for you (if at all) but using
  your method you were calling 5 user functions per result set from the db
  (that's the construct, the getter to set the $list key, and 1 for each of
  the 3 properties of the result) for a total of 18,420 user function
 calls.
   With my method I'm calling 1 user function (the construct) for each set,
  for a total of 3,684 calls.  Of course a down-side is that if there's any
  logic in your setters then that needs to be replicated in your construct.
  Another method is to use a single object for all 3684 records.  Perhaps
 you
  can use the built in Iterator interface which lets your class's objects
 be
  used as if they were an array for the purposes of foreach loops.
  http://php.net/manual/en/language.oop5.iterations.php
  You would set a pointer to the record you wish to use, and your getters
 and
  setters would key off that element of the master array.  This should be a
  fast solution, while still giving you the power of encapsulation, getters
  and setters.
 
  Hope that helps!
  Chris.
 

 Hi Chris,

 Thanks for the reply.  The sample I made is just for simplicity and
 comparison.  As for function calling 'get's, I think the speed would
 come out to be same in your sample since you're doing isset()
 checking.  My actual class is more sophisticated having the psuedo
 overloading as you mentioned.  The class is generated from a PHP class
 builder - to save on typing - I made a long time ago with some minor
 update.

 Anyway, I was frustrated as to why my code took so long to execute and
 had to dig deep.  As it turns out, I had xdebug loaded with all
 options on ... lol.  Removed the extension and all is good in the
 world.  The script runs in less than 150ms :D!!!

 Thanks,
 Tommy

 PS:  This is what I get for not coding in PHP so long ...