2
\$\begingroup\$

Today, I do not have a coding question, but just a general question about a piece of code that I have written.

As you guys can see, I run the following JavaScript code every ten seconds. I tried to run it every second, but it started eating up the CPU of my hosting company like crazy. With it running every ten seconds, I have no problems when there are a few users online, but have not massively tested this with a lot of people online at once.

Let's say that I have 100 users online at a time; do you guys think that running this code once every ten seconds would flood the server and cause it to run slowly? Should I keep it at 10 seconds, or maybe push it back to, let's say, 20 seconds? Or maybe even reduce it to 5 seconds? The shorter the time here, the better; I just do not want to be running too many processes at once and flood my server.

Here it is:

<script language='javascript' type='text/javascript'>
   setInterval( function() {
      $('#clicktoenteraconversation').load('getnewonlinefriends.php');
      //$('#friendstochatwith').load('checkloggedinchat.php?username=<?php echo $username; ?>&otherchatuser=<?php echo $otherchatuser; ?>');
   }, 10000);
</script>

Here is getnewonlinefriends.php:

<?php
if($username)
{
$resettime = time();
mysql_query("UPDATE loggedin SET time = '$resettime' WHERE username='$username'");
echo "<div id='showfriendsforchat'><div id='friendstochatwithcontainer'><div     id='friendstochatwith'>";
    $construct = "SELECT * FROM acceptedfriends WHERE profilename='$username'     ORDER BY id DESC";
    $run = mysql_query($construct);
    while ($runrows = mysql_fetch_assoc($run))
    {
    $users = $runrows['username'];
    $location = $runrows['chatpictures'];
    $image = "<img src='$location' style='width:25px; height:20px;' />";
    $readmessagequery = mysql_query("SELECT * FROM conversation WHERE yourusername='$username' and theirusername='$users' and readmessages='0'");
    $numrowsreadmessagequery = mysql_num_rows($readmessagequery);
    if ($numrowsreadmessagequery > 0)
    {
    $echonumrowsreadmessagequery = '<div id="numberofunreadmessages"><div style="padding:1px; padding-left:4px; padding-right:4px;">'.$numrowsreadmessagequery.'</div></div>';
    echo "
    <style>
    #clicktoenteraconversation{
    background: #C67171; /* Old browsers */
    background: -moz-linear-gradient(top,  #DEDEDE 0%, #C67171 100%); /* FF3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#DEDEDE), color-stop(100%,#C67171)); /* Chrome,Safari4+ */
    background: -webkit-linear-gradient(top,  #DEDEDE 0%,#C67171 100%); /* Chrome10+,Safari5.1+ */
    background: -o-linear-gradient(top,  #DEDEDE 0%,#C67171 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top,  #DEDEDE 0%,#C67171 100%); /* IE10+ */
    background: linear-gradient(top,  #DEDEDE 0%,#C67171 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#DEDEDE', endColorstr='#C67171',GradientType=0 ); /* IE6-9 */
    }
    }
    </style>
    ";
    }
    $subtractlogintime = time() - 600;
    $data4 = mysql_query("SELECT * FROM loggedin WHERE username='$users' and     time > '$subtractlogintime'");
    if (mysql_num_rows($data4)==1)
    {
    $loggedninpicture2 = '<img src="loggedin.png">';
    $loggedintally = $loggedintally + 1;
    }
    else
    {
    $loggedninpicture2 = '';
    }
    echo '<div id="hoverfriendstochatwith" onclick="showchat(\'' . $users . '\')"><table><tr><td>'.$image.'</td><td><div style="margin-left:5px;">'.$users.'</div></td><td>'.$echonumrowsreadmessagequery.'</td><td style="margin-left:5px;"><div style="margin-bottom:1px;">'.$loggedninpicture2.'</div></td></tr></table></div>';
    }
echo "</div><div id='clicktoenteraconversation2'    onclick='hideshowfriendstab()'>Close</div></div></div>";
echo "<div id='chatwithafriendhere'></div>";
if ($loggedintally > 0)
{
$loggedintally = '<img src="loggedin.png"> Chat ('.$loggedintally.')';
}
else
{
$loggedintally = '<img src="loggedin.png"> Chat (0)';
}
$readmessagequery = mysql_query("SELECT * FROM conversation WHERE     yourusername='$username' and readmessages='0'");
$numrowsreadmessagequery = mysql_num_rows($readmessagequery);
if ($numrowsreadmessagequery > 0)
{
echo "<img src='mostviewedpicture.png' style='height:16px; width:30px; float:left;       margin-top:1px; margin-left:5px;'/><div style='font-size:.8em; float:left; margin-left:2px;'>".$loggedintally."</div><div id='numberofunreadmessages' style='margin-left:5px; height:14px; margin-top:2px; margin-bottom:2px;'><div style='margin-left:4px; margin-right:4px; min-width:6px; margin-top:-3px;'>".$numrowsreadmessagequery."</div></div>";
}
else
{
echo "<img src='mostviewedpicture.png' style='height:16px; width:30px; float:left;    margin-top:1px; margin-left:5px;'/><div style='font-size:.8em; float:left; margin-left:2px;'>".$loggedintally."</div>";
}
}
?>
\$\endgroup\$
  • 2
    \$\begingroup\$ Warning your code seems to be susceptible to sql injection attacks. \$\endgroup\$ – Daniel A. White Jan 31 '12 at 21:18
  • 4
    \$\begingroup\$ I'd separate the static parts (eg CSS) from your code, and implement caching. An interval of 10 seconds is already generous. You often don't need updates that fast. \$\endgroup\$ – Rob W Jan 31 '12 at 21:19
  • \$\begingroup\$ Where is the flaw in the code that make it susceptible to sql injection? Please point this out as it would be very helpful. \$\endgroup\$ – Eggo Jan 31 '12 at 21:21
  • \$\begingroup\$ @eggo $username maybe isn't validated/escaped. \$\endgroup\$ – Sawny Jan 31 '12 at 21:24
  • \$\begingroup\$ For this bit of code, it needs to be updated as frequently as possible without overloading the server. \$\endgroup\$ – Eggo Jan 31 '12 at 21:24
1
\$\begingroup\$

As some other users have suggested in comments, I recommend separating the CSS from what is returned by the PHP script and using caching to reduce the number of queries you need to make.

You say that the more often this is updated the better - with caching your server will be able to respond to many, many times more requests than querying the database every time. It will also be easier to expand to support more users later too.

The best way to implement caching is to split off the queries into functions and apply logic to check if a cachekey exists (probably using memcached for PHP). If it does then return it, else query the database and set it. You will have to be sure that any time data is updated/inserted into the database, though, that the cache is updated to ensure that they remain in sync.

For example:

function get_user_session($UserID)
{
    $UserSessions = $Cache->get_value('users_sessions_'.$UserID);
    if(!is_array($UserSessions)) {
        $DB->query("SELECT
            SessionID,
            Browser,
            OperatingSystem,
            IP,
            LastUpdate
            FROM users_sessions
            WHERE UserID='$UserID'
            ORDER BY LastUpdate DESC");
        $UserSessions = $DB->to_array('SessionID',MYSQLI_ASSOC);
        $Cache->cache_value('users_sessions_'.$UserID, $UserSessions, 0);
    }
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks, it looks like this would solve my problem, except for the fact that I just spent quite a bit of time trying to fit this to the code that I already have an have no idea how to do it... \$\endgroup\$ – Eggo Jan 31 '12 at 21:58
  • \$\begingroup\$ In my code I'm using two classes, one for MySQL and another for Memcached. You need to get at least the Memcached class to use it like I have and I do recommend you get a class to interface with MySQL too, as mysql_query() is long deprecated! \$\endgroup\$ – deed02392 Feb 1 '12 at 9:40
0
\$\begingroup\$

If you want to protect your server then your server should be the one dictating the interval.

Since any JavaScript can be intercepted and modified you can't rely on setInterval.

First you need some way to measure load on your server. A simple approach would be to count the number of requests per minute.

Then, before you do any work, have your script 'wait' a while before doing anything. (sleep or usleep in PHP).

If the load goes up, increase the sleep time.

Then, on the client side you will need to account for the increase in request time. So rather than using a setInterval you should start a new timer once the request has been completed.

function call_to_server() {
    $('#clicktoenteraconversation').load('getnewonlinefriends.php', function () {
        setTimeout(call_to_server, 1000 /* 1 second */ );
    });
}
call_to_server();

This is the simple example. But if you leave this running for too long JavaScript will complain about nesting depth. You can find solutions for this.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.