High CPU usage due to Ajax Shoutbox

2019-08-05 23:41发布

问题:

Alright, so I have made a shoutbox, I have been using it for some time, but just recently it has come to my attention that it eats at the cpu usage because of so many calls to the script, and I am wondering how I can go about fixing its performance.

Here is the js script for the shoutbox.

var current_shouts = 0;
            function $shoutid(eleid) {
                return document.getElementById(eleid);
            }
            function urlencode(u) {
                u = u.toString();
                var matches = u.match(/[\x90-\xFF]/g);
                if (matches) {
                    for (var mid = 0; mid < matches.length; mid++) {
                        var char_code = matches[mid].charCodeAt(0);
                        u = u.replace(matches[mid], '%u00' + (char_code & 0xFF).toString(16).toUpperCase());
                    }
                }
                return escape(u).replace(/\+/g, "%2B");
            }
            function shouts() {
                clearTimeout(getshout);
                var xmlHttp = (window.XMLHttpRequest) ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
                xmlHttp.open("GET", "shoutbox/shouts.php?i=" + Math.random());
                xmlHttp.onreadystatechange = function() {
                    if (this.readyState == 4) {
                        if (parseInt(this.responseText) > current_shouts) {
                            getshouts();
                            current_shouts = parseInt(this.responseText);
                        }
                        getshout = setTimeout("shouts()", 1000);
                    }
                }
                xmlHttp.send(null);
            }
            function getshouts() {
                var xmlHttp = (window.XMLHttpRequest) ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
                xmlHttp.open("GET", "shoutbox/getshouts.php?i=" + Math.random());
                xmlHttp.onreadystatechange = function() {
                    if (this.readyState == 4) $shoutid("shoutbox").innerHTML = this.responseText;
$shoutid("shoutbox").scrollTop = $shoutid("shoutbox").scrollHeight;
                }
                xmlHttp.send(null);
            }
            function push_shout() {
                shout();
                return false;
            }
            function shout() {
                var xmlHttp = (window.XMLHttpRequest) ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP");
                xmlHttp.open("POST", "shoutbox/shout.php");
                var data = "user=" + urlencode($shoutid("user").value) + "&" + "shout=" + urlencode($shoutid("shout").value);
                xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                xmlHttp.setRequestHeader("Content-length", data.length);
                xmlHttp.onreadystatechange = function() {
                    if (this.readyState == 4) {
                        if (!this.responseText) $shoutid("shout").value = "";
                        else {
                            alert(this.responseText);
                        }
                        getshouts();
                    }
                }
                xmlHttp.send(data);
                return true;
            }
            var getshout = setTimeout("shouts()", 1000);

I'm not really the brightest crayon when it comes to js so I am not really sure how to go about fixing this. The call to shouts.php is what is really eating up at my cpu.

Here is the script for shouts.php

<?php
$db = new mysqli('localhost', 'username', 'pass', 'database');

if($db->connect_errno > 0){
   die('Unable to connect to database [' . $db->connect_error . ']');
}
    $stmt = $db->query("SELECT COUNT(id) FROM shout");
    while ($shout = $stmt->fetch_assoc()) {
    echo implode($shout);
    }
session_write_close();
?>

I read up on the session locking problem so I added in the session_write_close(); but this doesn't seem to help with my issue at all.

Any tips would be greatly appreciated!

回答1:

This is one of those things where tuning the code isn't necessarily going to help a whole bunch. You're essentially DDoS attacking your own hardware. My suggestion in the immediate future would be to bump up the javascript setTimeout frequency from 1000 to 2000 or higher. In the long run: upgrading hardware, moving to a faster/lighter storage solution (Redis is my personal favorite), both would be wise.



回答2:

Here is some basic code that will cache the output so you're not doing as much processing.

$cachefile = 'mycache.txt';
$timeout = 5;

//if there is no cache, or the cache is older that the specified timeout
if( !file_exists($cachefile) || ( filemtime($cachefile) + $timeout < time() ) ) {
   //your existing code here!
   $shouttext = implode($shout);
   echo $shouttext;
   file_put_contents($cachefile, $shouttext);
} else {
   echo file_get_contents($cachefile);
}