Process termination when using objects

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
peoplesrepublican
Forum Newbie
Posts: 6
Joined: Sat Jan 29, 2005 6:33 am

Process termination when using objects

Post by peoplesrepublican »

Hi,

I have some code which runs through a loop. In each iteration of the loop, a function is called which returns a reference to an object (created from a class) to a variable.

The loop never runs to completion; after between 75-80 loops processing appears to just terminate...there are no error messages displayed. Am I hitting some kind of allowed memory or max number of objects limit?

Any help would be greatly appreciated.

Cheers

Tim
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Post some code, possible you have hit the max execution time ?
peoplesrepublican
Forum Newbie
Posts: 6
Joined: Sat Jan 29, 2005 6:33 am

Post by peoplesrepublican »

Here is a snippet of the code in question:


for ($i=0;$i<100;$i++)
{
$this_ad = get_ad($cat,false);
$sample_ads[$this_ad->get_filename()] += 1;
}

mysql_close();

$ad_keys = array_keys($sample_ads);
sort($ad_keys);

echo "<table border='1'>\n";

foreach ($ad_keys as $ad_key)
{
echo "<tr><td>$ad_key</td><td align='right'>".$sample_ads[$ad_key]."</td></tr>\n";
}

echo "</table>";


Basically, this call:

$this_ad = get_ad($cat,false);

returns an object into $this_ad. This is then used to keep a count of the filenames returned by this repeated call, and these counts are shown in the table generated at the foot of the script.

I should have put in my original post (sorry) that I don't think the max execution time is the problem, the script finishes running within about 10 secs and the server has max_execution_time set to 30 secs. I used set_time_out(0) and stuck some sleeps in the code, to eliminate the max_execution_time theory. The script ran for 94 secs and finished at around the same place (around 80 iterations out of an expected 100).

Thanks in advance for any help.
magicrobotmonkey
Forum Regular
Posts: 888
Joined: Sun Mar 21, 2004 1:09 pm
Location: Cambridge, MA

Post by magicrobotmonkey »

try echo-ing out $i in your loop and make sure its counting up all the way through the loop. How do you know its only going up through 80?
peoplesrepublican
Forum Newbie
Posts: 6
Joined: Sat Jan 29, 2005 6:33 am

Post by peoplesrepublican »

heh. I know it only goes up to 80 because I echoed out $i in the loop - but I took that out before posting the code. Even if I take out the entries to $sample_ad it still stops at around 80.

The most frustrating thing about this is that this isn't even a functional part of the system - it's just a benchmark script to prove the system works. I've wasted hours of valuable dev time on this seemingly insignificant script!

Any further help is greatly appreciated.

BTW another forum asked for the phpinfo() output - it's here if anyone's interested:

http://personal.crystalduck.com/phpinfo.php
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

there is nothing that would make that loop stop short in your code, however the script could time out if it's taking too long.

make sure to have something like this in the code (for now)

Code: Select all

error_reporting(E_ALL);
ini_set('display_errors','1');
make sure this appears as close to the top of the php code as possible.
peoplesrepublican
Forum Newbie
Posts: 6
Joined: Sat Jan 29, 2005 6:33 am

Post by peoplesrepublican »

Thanks, I have done this. Unfortunately it didn't show any errors relating to why the script would stop, here's the end of the output:

<snip>
82
5.4493758678436
83
5.5015079975128
84
5.5538709163666
85
5.606085062027


I added back in the output of the loop var $i, and also a cumulative time - so you can see this stops a just over 5.6 seconds.

Thanks for all of your help so far, is there anything else I could try?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

post the definitions of those two functions and any user defined functions they call please.
peoplesrepublican
Forum Newbie
Posts: 6
Joined: Sat Jan 29, 2005 6:33 am

Post by peoplesrepublican »

This is the script I call in the browser:

Code: Select all

<?php
include_once "su_lm_common.php";
include_once AD_CLASS;

$start = microtime_float();

error_reporting(E_ALL);
ini_set('display_errors','1');

// get params
$sample = $_REQUEST&#1111;"sample"];
// set default value
if ($sample == "")
&#123;
  $sample = 100;
&#125;
$cat = $_REQUEST&#1111;"cat"];
// set default value
if ($cat == "")
&#123;
  $cat = 1;
&#125;

$db = get_db_connection();

// show headers
echo "<b>New ad threshold: ".NEW_AD_THRESHOLD."</b><br><br>\n";
echo "<b>New ad share: ".NEW_AD_SHARE."</b><br><br>\n";
echo "<table border='1'>\n";
echo "<tr><th>Ad</th><th>Served</th><th>Clicked</th><th>Weighting</th></tr>\n";

// get ads for specified category
$ads = get_ads_by_category($cat);

foreach ($ads as $ad)
&#123;
  echo "<tr align='center'><td>".$ad->get_filename().
    "</td><td>".$ad->get_serves()."</td><td>".$ad->get_clicks()."</td><td>".
    $ad->get_weighting()."</td></tr>\n";
&#125;
echo "</table><br><br>\n";

for ($i=0;$i<$sample;$i++)
&#123;
  echo $i."<br>\n".(microtime_float() - $start)."<br>\n";
  $this_ad = get_ad($cat,false);
  $sample_ads&#1111;$this_ad->get_filename()] += 1;
&#125;

mysql_close();

$ad_keys = array_keys($sample_ads);
sort($ad_keys);

echo "<table border='1'>\n";

foreach ($ad_keys as $ad_key)
&#123;
  echo "<tr><td>$ad_key</td><td align='right'>".$sample_ads&#1111;$ad_key]."</td></tr>\n";
&#125;

echo "</table>";
?>
get_ad:

Code: Select all

function get_ad($cat,$external_use=true)
&#123;
  // this var is used to decide which set of ads to choose from,
  // if any new (served <= NEW_AD_THRESHOLD) exist
  $use_new_ads = false;

  // get all ads for specified category
  $ads = get_ads_by_category($cat);

  // create empty new_ads array;
  $new_ads = array();

  // loop through all returned ads
  foreach($ads as $ad)
  &#123;
    // build two arrays of ads - those with serves greater than NEW_AD_THRESHOLD ($ads),
    // and those with serves equal to or less than NEW_AD_THRESHOLD ($new_ads)
    if ($ad->get_serves() > NEW_AD_THRESHOLD)
    &#123;
      $ads&#1111;] = $ad;
    &#125;
    else
    &#123;
      $new_ads&#1111;] = $ad;
    &#125;
  &#125;

  if (count($ads) > 0 && count($new_ads) > 0)
  &#123;
    // decide which array of ads to use
    if (rand(1,100) <= NEW_AD_SHARE)
    &#123;
      $use_new_ads = true;
    &#125;
  &#125;
  else if (count($ads) == 0 && count($new_ads) > 0)
  &#123;
    $use_new_ads = true;
  &#125;

  if ($use_new_ads)
  &#123;
    $ad_to_use = rand(0,count($new_ads)-1);
    $return_ad = $new_ads&#1111;$ad_to_use];
  &#125;
  else
  &#123;
    if (count($ads) > 0)
    &#123;
      foreach ($ads as $ad)
      &#123;
        for ($i=0;$i<$ad->get_weighting();$i++)
        &#123;
          $ad_tombola&#1111;] = $ad;
        &#125;
      &#125;

      $ad_to_use = rand(0,count($ad_tombola)-1);
      $return_ad = $ad_tombola&#1111;$ad_to_use];

      // if this is for external use, increment the serve count for the ad
      if ($external_use)
      &#123;
        $return_ad->increment_serves();
      &#125;
    &#125;
    else
    &#123;
      $return_ad = default_ad($cat);
    &#125;
  &#125;
  return $return_ad;
&#125;
get_ads_by_category:

Code: Select all

function get_ads_by_category($cat)
&#123;
  // get all ads for the specified category, ordered by clicks/serves ratio desc
  $sql = "SELECT id FROM ".AD_TABLE." WHERE category = $cat";
  $result = mysql_query($sql);
  while ($ad_id = mysql_fetch_row($result))
  &#123;
    $ad = find_ad($ad_id&#1111;0]);
    if ($ad !== false)
    &#123;
      $ads&#1111;] = $ad;
    &#125;
  &#125;
  return $ads;
&#125;
Ad class:

Code: Select all

<?php
class Ad
&#123;
  // member variables

  var $id;
  var $category;
  var $filename;
  var $width;
  var $height;
  var $submission_date;
  var $serves;
  var $clicks;
  var $conversions;
  var $cs_ratio;
  var $weighting;

  // member functions

  // get and set

  // id
  function set_id($id)
  &#123;
    $this->id = $id;
  &#125;

  function get_id()
  &#123;
    return $this->id;
  &#125;

  // category
  function set_category($category)
  &#123;
    $this->category = $category;
  &#125;

  function get_category()
  &#123;
    return $this->category;
  &#125;

  // filename
  function set_filename($filename)
  &#123;
    $this->filename = $filename;
  &#125;

  function get_filename()
  &#123;
    return $this->filename;
  &#125;

  // width
  function set_width($width)
  &#123;
    $this->width= $width;
  &#125;

  function get_width()
  &#123;
    return $this->width;
  &#125;

  // height
  function set_height($height)
  &#123;
    $this->height= $height;
  &#125;

  function get_height()
  &#123;
    return $this->height;
  &#125;

  function set_submission_date($submission_date)
  &#123;
    $this->submission_date = $submission_date;
  &#125;

  function get_submission_date()
  &#123;
    return $this->submission_date;
  &#125;

  // serves
  function set_serves($serves)
  &#123;
    $this->serves = $serves;
  &#125;  

  function get_serves()
  &#123;
    return $this->serves;
  &#125;

  // clicks
  function set_clicks($clicks)
  &#123;
    $this->clicks = $clicks;
  &#125;

  function get_clicks()
  &#123;
    return $this->clicks;
  &#125;

  // conversions
  function set_conversions($conversions)
  &#123;
    $this->conversions = $conversions;
  &#125;

  function get_conversions()
  &#123;
    return $this->conversions;
  &#125;

  // cs_ratio
  function set_cs_ratio($cs_ratio)
  &#123;
    $this->cs_ratio = $cs_ratio;
  &#125;

  function get_cs_ratio()
  &#123;
    return $this->cs_ratio;
  &#125;

  // weighting
  function set_weighting($weighting)
  &#123;
    $this->weighting = $weighting;
  &#125;

  function get_weighting()
  &#123;
    return $this->weighting;
  &#125;

  // create_in_db - creates the ad in the db
  // returns true if all goes well, false otherwise
  function create_in_db()
  &#123;
    echo $sql;
    $sql = "INSERT INTO ".AD_TABLE." (".CATEGORY_FIELD.",".FILENAME_FIELD.
    ",".SUBMISSION_DATE_FIELD.")".
      " VALUES ('".$this->category."','".$this->filename."',NOW())";
    mysql_query($sql);
    if (mysql_affected_rows() == 1)
    &#123;
      // set the id of the ad
      $this->id = mysql_insert_id();

      return true;
    &#125;
    else
    &#123;
      return false;
    &#125;
  &#125;

  // delete - deletes link
  // returns true if all goes well, false otherwise
  function delete()
  &#123;
    $sql = "INSERT INTO ".DELETED_AD_TABLE." (".ID_FIELD.",".CATEGORY_FIELD.",".
      FILENAME_FIELD.",".DELETION_DATE_FIELD.") ".
      "SELECT ".ID_FIELD.",".CATEGORY_FIELD.",".FILENAME_FIELD.", NOW() FROM ".
      AD_TABLE." WHERE id = ".$this->id;
    mysql_query($sql);
    if (mysql_affected_rows() == 1)
    &#123;
      $sql = "DELETE FROM ".AD_TABLE." WHERE id = ".$this->id;
      mysql_query($sql);
      if (mysql_affected_rows() == 1)
      &#123;
        return true;
      &#125;
      else
      &#123;
        return false;
      &#125;
    &#125;
    else
    &#123;
      return false;
    &#125;
  &#125;

  // increment_serves - increments serve_count by 1 in the db
  // no return value (will never be checked)
  function increment_serves()
  &#123;
    $sql = "UPDATE ".AD_TABLE." SET ".SERVE_COUNT_FIELD." = (".SERVE_COUNT_FIELD.
      " + 1) WHERE "."id = ".$this->id;
    $result = mysql_query($sql);
  &#125;

&#125;
?>
Thanks a lot.
Post Reply