NancyJ
08-12-2006, 05:08 PM
Hey guys, need a bit of brainstorming help. We're having a problem with an application - its basically a hotel availability listing that gets data from 2 external sources, then compiles the results into a single listing, sorted by cheapest price.
I've taken a few chunks out of the code - just to keep it to the point and not overload you with info that you dont need.
The problem is that searches are using way too much CPU, like up to 40% for a single search - now I'm assuming the problem is the sorting by price and compositing the two arrays but I could be wrong - what worries me is that I've seen 1 search that took 13s, 12.1% CPU, 8% Memory and only returned a single result. Now how can that be?
Anyway - this is the code
//soap call to get data from first source goes here
//check if we got a response
if($this->response)
{
foreach($this->response as $offer)
{
///the data we get back is quite complex its structure is basically a Hotel, then a listing of all available rooms and prices
$arrHotels[(string)$offer->Hotel->Id] = array("HotelName"=>$offer->Hotel->Name, "Resort"=>$offer->Hotel->Region->Name, "Stars"=> $offer->Hotel->Stars, "Thumbnail"=>$offer->Hotel->Photo->ThumbnailUrl, "Accom" =>$offer->Hotel->Type, "Type"=> "OHG", "Rooms"=>array());
//$offer->Result is the rooms
foreach($offer->Result as $result)
{
$arrHotels[(string)$offer->Hotel->Id]["Rooms"][]= array("RoomDesc" => str_ireplace(array(" pax", " ssv", " sv", " mv"), array(" passengers", " sea side view", " sea view", " mountain view") ,$result->Room->RoomType->Text). " ".$result->Room->MealType->Text, "Price"=>$result->Room->SellingPrice->Amount);
}
}
//sort OHG data into cheapest
$startTime = microtime(true);
foreach($arrHotels as $key => $val)
{
$numOfRooms = count($val['Rooms']);
$rooms +=$numOfRooms;
$arrPrices = array();
for($i=0; $i< $numOfRooms; $i++)
{
$arrPrices[] = $val['Rooms'][$i]['Price'];
}
asort($arrPrices);
$tempPrices= array();
foreach($arrPrices as $key2=>$val2)
{
$tempPrices[] = $val['Rooms'][$key2];
}
$arrHotels[$key]['Rooms'] = $tempPrices;
$arrCheapestPrices[$key] = $arrHotels[$key]['Rooms'][0]['Price'];
$arrOHGHotels[$key] = $arrHotels[$key]['HotelName'];
}
asort($arrCheapestPrices);
}
//dump OHG hotel data into array (easier than renaming code later)
$arrHotels1 = $arrHotels;
//clear arrHotels array.
$arrHotels = array();
$start = time();
//Med Hotels search
//dont search 1star - not worth it
$min = $_GET['r']>1?$_GET['r']:2;
//loop through each star rating or until 15 seconds passed
for($s=5; $s>=$min; $s--)
{
if(time()-$start < 15)
{
//CURL request to get data from second source goes here
$xml = @simplexml_load_string($rawData);
$hotels = $xml->Reservation;
if($hotels->Hotel)
{
foreach($hotels->Hotel as $hotel)
{
if(is_array($arrHotels[(string)$hotel['ID']]))
{
if((float)$hotel->Star_Category >= $s)
{
if(is_numeric(substr($hotel->Room_Title, 0,1)))
{
//if the first character is space we need to strip off everything from the first . or space.
$pos = strpos($hotel->Room_Title, ".");
if($pos === false)
{
$pos = strpos($hotel->Room_Title, " ");
}
$hotel->Room_Title = substr($hotel->Room_Title, $pos+1);
}
$arrHotels[(string)$hotel['ID']]["Rooms"][]= array("RoomDesc"=>$hotel->Room_Title, "Price"=>$hotel->Price);
}
}
else
{
if(is_numeric(substr($hotel->Room_Title, 0,1)))
{
//if the first character is space we need to strip off everything from the first . or space.
$pos = strpos($hotel->Room_Title, ".");
if($pos === false)
{
$pos = strpos($hotel->Room_Title, " ");
}
$hotel->Room_Title = substr($hotel->Room_Title, $pos+1);
}
$arrHotels[(string)$hotel['ID']]= array("HotelName"=>str_replace(" (".ucwords(strtolower($hotel->Area)).")", "",$hotel->Hotel_Name), "Resort"=>ucwords(strtolower($hotel->City)), "Stars"=>$hotel->Star_Category, "Thumbnail"=>$hotel->Thumbnail, "Accom" => "Hotel", "Type" => "MedHotels", "Rooms" => array(array("RoomDesc"=>$hotel->Room_Title, "Price"=>$hotel->Price)));
}
}
}
unset($xml);
}
}
//sort by price again
foreach($arrHotels as $key => $val)
{
$numOfRooms =count($val['Rooms']);
$rooms +=$numOfRooms;
$arrPrices = array();
for($i=0; $i< $numOfRooms; $i++)
{
$arrPrices[]=$val['Rooms'][$i]['Price'];
}
asort($arrPrices);
$tempPrices= array();
foreach($arrPrices as $key2=>$val2)
{
$tempPrices[]= $val['Rooms'][$key2];
}
$arrHotels[$key]['Rooms']=$tempPrices;
$arrCheapestPrices[$key]= $arrHotels[$key]['Rooms'][0]['Price'];
}
asort($arrCheapestPrices);
//ok we have 2 arrays now - we need to remove duplicates.
//medhotels list should be smallest because of star rating issue so we'll loop through that one
foreach($arrHotels as $key2 => $hotel)
{
$key = array_search($hotel['HotelName'], $arrOHGHotels);
if($key!= false)
{
//we have duplicate
//check for cheapest
if($arrCheapestPrices[$key]>$hotel['Rooms'][0]['Price'])
{
//we need to replace that data
$arrCheapestPrices[$key]= $hotel['Rooms'][0]['Price'];
//we also need to change the type to OHG because of the key being used to indentify it
$hotel['Type']= "OHG";
$arrHotels1[$key]= $hotel;
}
}
else
{
//no duplicate so lets just plop it on the end
$arrHotels1[$key2]= $hotel;
}
}
asort($arrCheapestPrices);
$this->hotels = $arrHotels1;
$this->prices = $arrCheapestPrices;
unset($arrHotels1);
unset($arrHotels);
unset($arrCheapestPrices);
So can anyone help with my CPU load issues or making this sort less intensive without losing functionality?
I've taken a few chunks out of the code - just to keep it to the point and not overload you with info that you dont need.
The problem is that searches are using way too much CPU, like up to 40% for a single search - now I'm assuming the problem is the sorting by price and compositing the two arrays but I could be wrong - what worries me is that I've seen 1 search that took 13s, 12.1% CPU, 8% Memory and only returned a single result. Now how can that be?
Anyway - this is the code
//soap call to get data from first source goes here
//check if we got a response
if($this->response)
{
foreach($this->response as $offer)
{
///the data we get back is quite complex its structure is basically a Hotel, then a listing of all available rooms and prices
$arrHotels[(string)$offer->Hotel->Id] = array("HotelName"=>$offer->Hotel->Name, "Resort"=>$offer->Hotel->Region->Name, "Stars"=> $offer->Hotel->Stars, "Thumbnail"=>$offer->Hotel->Photo->ThumbnailUrl, "Accom" =>$offer->Hotel->Type, "Type"=> "OHG", "Rooms"=>array());
//$offer->Result is the rooms
foreach($offer->Result as $result)
{
$arrHotels[(string)$offer->Hotel->Id]["Rooms"][]= array("RoomDesc" => str_ireplace(array(" pax", " ssv", " sv", " mv"), array(" passengers", " sea side view", " sea view", " mountain view") ,$result->Room->RoomType->Text). " ".$result->Room->MealType->Text, "Price"=>$result->Room->SellingPrice->Amount);
}
}
//sort OHG data into cheapest
$startTime = microtime(true);
foreach($arrHotels as $key => $val)
{
$numOfRooms = count($val['Rooms']);
$rooms +=$numOfRooms;
$arrPrices = array();
for($i=0; $i< $numOfRooms; $i++)
{
$arrPrices[] = $val['Rooms'][$i]['Price'];
}
asort($arrPrices);
$tempPrices= array();
foreach($arrPrices as $key2=>$val2)
{
$tempPrices[] = $val['Rooms'][$key2];
}
$arrHotels[$key]['Rooms'] = $tempPrices;
$arrCheapestPrices[$key] = $arrHotels[$key]['Rooms'][0]['Price'];
$arrOHGHotels[$key] = $arrHotels[$key]['HotelName'];
}
asort($arrCheapestPrices);
}
//dump OHG hotel data into array (easier than renaming code later)
$arrHotels1 = $arrHotels;
//clear arrHotels array.
$arrHotels = array();
$start = time();
//Med Hotels search
//dont search 1star - not worth it
$min = $_GET['r']>1?$_GET['r']:2;
//loop through each star rating or until 15 seconds passed
for($s=5; $s>=$min; $s--)
{
if(time()-$start < 15)
{
//CURL request to get data from second source goes here
$xml = @simplexml_load_string($rawData);
$hotels = $xml->Reservation;
if($hotels->Hotel)
{
foreach($hotels->Hotel as $hotel)
{
if(is_array($arrHotels[(string)$hotel['ID']]))
{
if((float)$hotel->Star_Category >= $s)
{
if(is_numeric(substr($hotel->Room_Title, 0,1)))
{
//if the first character is space we need to strip off everything from the first . or space.
$pos = strpos($hotel->Room_Title, ".");
if($pos === false)
{
$pos = strpos($hotel->Room_Title, " ");
}
$hotel->Room_Title = substr($hotel->Room_Title, $pos+1);
}
$arrHotels[(string)$hotel['ID']]["Rooms"][]= array("RoomDesc"=>$hotel->Room_Title, "Price"=>$hotel->Price);
}
}
else
{
if(is_numeric(substr($hotel->Room_Title, 0,1)))
{
//if the first character is space we need to strip off everything from the first . or space.
$pos = strpos($hotel->Room_Title, ".");
if($pos === false)
{
$pos = strpos($hotel->Room_Title, " ");
}
$hotel->Room_Title = substr($hotel->Room_Title, $pos+1);
}
$arrHotels[(string)$hotel['ID']]= array("HotelName"=>str_replace(" (".ucwords(strtolower($hotel->Area)).")", "",$hotel->Hotel_Name), "Resort"=>ucwords(strtolower($hotel->City)), "Stars"=>$hotel->Star_Category, "Thumbnail"=>$hotel->Thumbnail, "Accom" => "Hotel", "Type" => "MedHotels", "Rooms" => array(array("RoomDesc"=>$hotel->Room_Title, "Price"=>$hotel->Price)));
}
}
}
unset($xml);
}
}
//sort by price again
foreach($arrHotels as $key => $val)
{
$numOfRooms =count($val['Rooms']);
$rooms +=$numOfRooms;
$arrPrices = array();
for($i=0; $i< $numOfRooms; $i++)
{
$arrPrices[]=$val['Rooms'][$i]['Price'];
}
asort($arrPrices);
$tempPrices= array();
foreach($arrPrices as $key2=>$val2)
{
$tempPrices[]= $val['Rooms'][$key2];
}
$arrHotels[$key]['Rooms']=$tempPrices;
$arrCheapestPrices[$key]= $arrHotels[$key]['Rooms'][0]['Price'];
}
asort($arrCheapestPrices);
//ok we have 2 arrays now - we need to remove duplicates.
//medhotels list should be smallest because of star rating issue so we'll loop through that one
foreach($arrHotels as $key2 => $hotel)
{
$key = array_search($hotel['HotelName'], $arrOHGHotels);
if($key!= false)
{
//we have duplicate
//check for cheapest
if($arrCheapestPrices[$key]>$hotel['Rooms'][0]['Price'])
{
//we need to replace that data
$arrCheapestPrices[$key]= $hotel['Rooms'][0]['Price'];
//we also need to change the type to OHG because of the key being used to indentify it
$hotel['Type']= "OHG";
$arrHotels1[$key]= $hotel;
}
}
else
{
//no duplicate so lets just plop it on the end
$arrHotels1[$key2]= $hotel;
}
}
asort($arrCheapestPrices);
$this->hotels = $arrHotels1;
$this->prices = $arrCheapestPrices;
unset($arrHotels1);
unset($arrHotels);
unset($arrCheapestPrices);
So can anyone help with my CPU load issues or making this sort less intensive without losing functionality?