Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

PHP database slow response via AJAX 1

Status
Not open for further replies.

johnwm

Programmer
Feb 7, 2001
8,469
GB
Sorry this is a bit long-winded - I seem to be missing a trick somewhere - I think it may be with my use of mysqli_fetch_row. I am translating an existing ASP website to PHP, and using AJAX to fetch a day's worth of images with a button onclick event. Everything seems OK, but I am seeing a 2-3 second delay from the button click to the thumbnails loading, whereas I was seeing less than 0.5 second on the original page.

The ASP action can be seen at the original site:
The PHP version is at Both versions are on the same physical server, and read the same database. Page source for the aveling3.php page (with ads etc removed for brevity):
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">[/URL]
<html xmlns="[URL unfurl="true"]http://www.w3.org/1999/xhtml">[/URL]
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1" />
<body>
<!-- Header -->
<div id="hdr">
<h1>Essex Steam Aveling &amp; Porter Steam Roller</h1>
<div class="clearer">&nbsp;</div>
<!-- left column -->
<div id="lhc">
<?php include("lhc.inc"); ?>
</div>
<!-- end of left column -->
<div id="rhc"> 
<script type="text/javascript" src="getpic.js"></script>
<!-- right column -->
  <div id="logo"> 
<a name="beginning"></a><a style="float:right" href="[URL unfurl="true"]http://www.essexsteam.co.uk"[/URL] title="Go to main page." ><img class="pics"src="images/logo.gif" alt="Home"/></a>    <h2>Essex Steam Aveling &amp; Porter</h2>
    <h4>NEWSFLASH - The Aveling roller is now completely up and running but we sadly have decided to let it go. It is entered in <a href="[URL unfurl="true"]http://www.cheffins.co.uk/catalogue/vintage/cambridge-vintage-sale-21-0">Cheffins[/URL] July auction.</a> We look forward to seeing you there.</h4>
 </div>
 <hr style="clear:right"/>
  <p> The Aveling &amp; Porter 8 Ton was acquired locally in 2004. It has had
    a very active life, and was ready for some maintenance. </p>
  <a href="#end">Latest story</a> 
<?php
$strSQL = "Select paraID, parahead, paratext, picserial From tblparas Where storyid = '1'  Order by paraID";
$link = mysql_connect('**.**.**.**', 'loginname', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db("steamdates");
$result = mysql_query($strSQL);
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
echo("<hr/><h4>" . $row[1] . "</h4>" . $row[2]);
$temp=$row[3];
//echo $temp;
echo("<button type='button'  style='cursor:pointer' value='a$temp' id='a$temp' onclick='showpics(this.id)'>");
if ($temp < 65000)
{
echo("Show pictures");

}
echo("</button><div id='myText$temp' >&nbsp;</div><a href='#beginning'>TOP</a>");
echo("<div style='clear:left'>&nbsp;</div>");
}
mysql_free_result($result);
mysql_close($link);
?> 
 <a name="end"></a> 
  <hr/>
<div style="clear:left">&nbsp;</div>
</div>
</body>
</html>
The onclick event calls getpics.js (which is the same on both sites other than the target URL)
Code:
var xmlHttp
var muNum
function showpics(str)
{ 
muNum=str
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
alert ("Browser does not support HTTP Request")
return
} 
var url="getpics2.php"
str=str.substr(1)
url=url+"?q="+str
url=url+"&sid="+Math.random()
xmlHttp.onreadystatechange=stateChanged 
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}

function stateChanged() 
{ 
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{ 
muNum=muNum.substr(1)
document.getElementById("myText"+muNum).innerHTML=xmlHttp.responseText 
document.refresh
} 
} 

function GetXmlHttpObject()
{ 
var objXMLHttp=null
//new insert start
if (typeof DOMParser == "undefined") {
   DOMParser = function () {}

   DOMParser.prototype.parseFromString = function (str, contentType) {
      if (typeof ActiveXObject != "undefined") {
         var d = new ActiveXObject("MSXML.DomDocument");
         d.loadXML(str);
         return d;
      } else if (typeof XMLHttpRequest != "undefined") {
         var req = new XMLHttpRequest;
         req.open("GET", "data:" + (contentType || "application/xml") +
                         ";charset=utf-8," + encodeURIComponent(str), false);
         if (req.overrideMimeType) {
            req.overrideMimeType(contentType);
         }
         req.send(null);
         return req.responseXML;
      }
   }
}
//new insert end
if (window.XMLHttpRequest)
{
objXMLHttp=new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
}
return objXMLHttp
}
This populates getpics2.php
Code:
<?php
$q=$_REQUEST["q"];
$link = mysqli_connect('**.**.**.**', 'loginname', 'password','steamdates');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
$sql="Select mynum,PicTitle, picpath, serialID From Pics Where PicType = '";
$sql.=$q."' order by serialid";
if ($result = mysqli_query($link, $sql)) {
    $total= (mysqli_num_rows($result))-1;
	while ($row = mysqli_fetch_row($result)) {
	echo("<div class='thumb'><a class='pics' target='_blank' href='closeup.php?myPicID=$row[3]&amp;myMax=$total&amp;myPicType=$q'><img src='pics/t/$row[2]' alt='$row[1]'  width='115' height='86'  /></a><p> $row[1] </p> </div>");
	}	
}
echo("<div style='clear:both'>&nbsp;</div>");
mysqli_free_result($result);
mysqli_close($link);
?>

Hope you're all still with me! The thing that baffles me is that if I call the getpics2 page manually it loads almost immediately

Where am I going wrong?

PS - excuse the poor layout - my excuse is that I'm a PHP newbie [smile]

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
what does document.refresh() do? i have not come across it in javascript before. i assume you are not trying to refresh the page - as that would be counterproductive for ajax delivered content.

really bad idea to use unfiltered content in your sql queries. read up on sql injection attacks.

why are you using a mixture of mysqli_* and mysql_ commands?

you should expressly end the connection in your php. so add an exit(); as the last line of your script. personally i wouldn't bother expressly closing the mysql connections either.

the real slow down is likely to be being cause by the closeup.php script as it is that script that actually serves the images.
 
Thank you for your time and effort with the reply.

1. I got document.refresh from an old script. I can't find a reference to it at the moment, so I have removed it as you suggest, and it doesn't seem to make any difference. I sort of assumed it was OK as I didn't get any errors on the FF javascript error console.

2. Your point about SQL injection is well taken. I actually use prepared statements for production sites to avoid SQL injection attacks, but it's much easier to show what I'm doing for the purpose of this question if I simply show the underlying query.

3. Good point about the mixed use of mysql and mysqli commands. I have now re-written it all using mysqli commands, but it doesn't seem to have much impact on speed.

4. I clearly misunderstood the mysqli_free_result($result);
mysqli_close($link); commands - I thought I needed to close and release the recordset and connection. I have now removed them and placed an exit(); at the end of the script.

Sadly none of these appear to have altered performance significantly - I am still seeing a 2-3 second delay after the button is clicked before the thumbnails appear.

I don't understand your comment about closeup.php. The only reference to it seems to be in a <a href> so I assume that it will only be called when the link is clicked. The actual thumbnail image comes from
Code:
<img src='pics/t/$row[2]' alt='$row[1]'  width='115' height='86'  />
which is within the getpics2.php

I would be pleased to hear any other comments on the loading speed issue, as I am currently rather disappointed that PHP seems to be be performing so poorly compared to ASP

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
you're right about closeup.php. i misread the code and assumed it was an image service code snip.

if you take the resulting html that the page ends up with, and then deliver that html statically are you still seeing the delay?

could it also be that the asp pages are being cached whereas you're deliberately cache busting using the appending of a time parameter to the ajax query?

and also you can check out the timings of each resource being loaded through firebug. that might show you which resource is slowing you down. remember it could also be a browser issue if the layout semantics (x)(html) are different between the two sites.

 
Thanks again.

The resulting HTML is now saved and uploaded to where it loads very quickly - as quick as the ASP page.

The cache buster in getpic.js is exactly the same for the PHP and ASP pages

Firebug result is interesting - the console shows :
GET 107ms

but the pictures appear around 2 seconds later

Layout semantics are the same on both sites. This suggests to me that I'm doing something wrong in getpics2.php which now only contains
Code:
<?php
$q=$_REQUEST["q"];
$link = mysqli_connect('**.**.**.**', 'loginname', 'password','steamdates');
if (!$link) {
    die('Could not connect: ' . mysqli_error());
}
$sql="Select mynum,PicTitle, picpath, serialID From Pics Where PicType = '";
$sql.=$q."' order by serialid";
if ($result = mysqli_query($link, $sql)) {
    $total= (mysqli_num_rows($result))-1;
	while ($row = mysqli_fetch_row($result)) {
	echo("<div class='thumb'><a class='pics' target='_blank' href='closeup.php?myPicID=$row[3]&amp;myMax=$total&amp;myPicType=$q'><img src='pics/t/$row[2]' alt='$row[1]'  width='115' height='86'  /></a><p> $row[1] </p> </div>");
	}	
}
echo("<div style='clear:both'>&nbsp;</div>");
exit();
?>

Any thoughts?

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
well 107ms looks pretty quick to me.
for some reason your browser is pausing before grabbing the images. it's not a php problem.

you might be able to improve things by output buffering (rely on implicit flushing if you want). i'm thinking, basically that setting a content length might cause the browser to start the secondary loads faster.

 
I don't see the 107ms as the problem - it's the delay between that call and the pictures arriving. As the 2 versions read the same database, use the same js, load the same pictures and run on the same server it's getting harder to see where the problem may be.

If you view the 2 sites, do both versions bring up the thumbnails equally fast? I am seeing the same symptoms on FF, IE6, IE7 and Safari on my local machine and on other machines as well.

Can you suggest the best method of output buffering for this purpose? I have tried with
Code:
ob_flush();
flush();
inside the 'while' loop and it makes no difference.

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
john

a couple of comments on your earlier post:

i wasn't saying that you _should_ not use mysqli_close() etc. just that it is unnecessary and adds to the parsing time. all active conncetions are implicitly closed when the script ends.

i personally have never seen much (if any) advantage in using mysqli_ over mysql_. i wonder whether real benefits would be seen on very large datasets.

like you, i only use prepared statements on production sites. typically i use the pdo abstraction layer.

i've tinkered with your code a wee bit, to convert to plain mysql and try to optimise the output time. like you, i was seeing load times in ff of up to 5 secs. i've not seen this before, so i wonder whether your php server has something funny going on. can you share the phpinfo() output?

Code:
$q=isset($_GET['q']) ? trim($_GET['q']) : '';

//conenct to the db and database
mysql_connect('**.**.**.**', 'loginname', 'password') or die (mysql_error());
mysql_select_db('steadmates') or die(mysql_error());

//escape the query variable
$q = mysql_real_escape_string($q);

$sql="Select mynum,PicTitle, picpath, serialID From Pics Where PicType = '$q' order by serialid";

$result = mysql_query($sql) or die (mysql_error());
$total = mysql_num_rows($result);
$output = '';
while ($row = mysql_fetch_array($result)){
	$url = urlencode("closeup.php?myPicID={$row[3]}&myMax={$total}&myPicType={$q}");
	$output .= <<<HTML
		<div class="thumb">
			<a 	class="pics" 
				target="_blank"
				href="$url" >
				<img src="pics/t/{$row[2]}" alt="{$row[1]}" width="115" height="86" />
			</a>
			<p>
				{$row[1]} 
			</p>
		</div>
HTML;
}
$output .= <<<HTML
		<div style='clear:both'>
			&nbsp;
		</div>
HTML;

//add some cache busting
header('Content-type: text/html');
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
//add the content length so browser knows when to stop listening
header("Content-Length: " . strlen($output) );
echo $output;
exit;
 
Thank you, Thank you, Merci beaucoup, Viele Danke.
Code:
header("Content-Length: " . strlen($output) );
echo $output;
is what did it! using your code brought thumbnail load times right down. I have double checked by remming out the 'header' line, and it slows right down again.

Let's hope this will also be of help to others!

___________________________________________________________
If you want the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
Steam Engine Prints
 
there you go then. it was a browser thing after all. the browser did not want to go do other things until it knew that there was no more content to come. I don't think that all browsers behave the same way (or perhaps their timeouts are different) as safari was definitely a bit quicker than FF. could be just subjective perception though, as i was not doing any timing.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top