PPT

CACHING TO
IMPROVE PERFORMANCE
http://www.flickr.com/photos/jamescridland/613445810
Overview of caching
• After you get a result, save it so you don't
have to get it again
• Examples
– Finding the maximum of many different numbers
• Or any other expensive mathematical computation
– Generating a really nicely-formatted image
• Or any other expensive formatting computation
Key steps in caching
1. Define a variable for storing the result
2. If the variable does not yet have a value
a) Do whatever is needed to compute the result
b) Assign the result to your variable
3. Use the value of the variable
Pros and cons of caching
• Pros:
– Caching eliminates the need to recompute
• Cons:
– Caching requires some storage to store values
(such as RAM, or some hard drive space)
– Caching gives no benefit unless the value is reused
When and when not to cache
• Do cache when
– A value is very expensive to compute or get, AND
– And that value will be needed many times
• Do not cache when
– The result is not expensive to get, OR
– The result will only be needed once, OR
– There isn't enough storage available to cache
Caching works at every level!!!
Web page
UI
Your AJAX
code
Web server
Database or
files
Cache in JS variable
Cache in browser
Cache in session
Cache in DB/files
Examples of expensive JS computations
• Retrieving a piece of data from the server
– Such as retrieving a JSON object or XML file
– Network round-trips are probably the slowest
computation you can do!
• Prompting the user for some input
– E.g., if you have a site for browsing different
schools' courses, ask the user once what school he
or she wants to look at
– From the user's standpoint, giving input is an
"expensive" operation.
Detailed example of JS caching
<script src="jquery-1.8.2.min.js"></script>
<script>
var teamCache = {};
function getPlayers() {
var team = $("#team").val();
if (teamCache[team])
fillin(teamCache[team]);
else $.ajax({
url:"team"+$("#team").val()+".json",
dataType:"json",
error:function() {alert("Cannot retrieve.");},
success:function(result) {
if (result && result.players) {
teamCache[team] = result.players;
fillin(result.players);
} else {
alert("No data provided.");
}
}
});
}
function fillin(playerlist) {
$("#players").text(playerlist+"");
}
</script>
<select id="team" onchange="getPlayers()"><option value="">--Choose--</option>
<option value="1">Team Alpha</option><option value="2">Team Beta</option></select>
<div id="players"></div>
You need a JS variable.
If you might be storing
multiple values, then use an
associative array.
Index your array with a key.
Check if your value is already
saved. If so, just use it.
Otherwise, just do your
expensive computation
Remember to save your result
for reuse later on!
Caching in the browser
• Your AJAX code doesn't need to hit the server
every single time.
• $.ajax({}) accepts a cache option
– Tells AJAX to automatically cache every GET
request in the browser's cache
– By default
• cache == true for most versions of Internet Explorer
• cache == false for most other versions of browsers
Example of AJAX request to cache
<script src="jquery-1.8.2.min.js"></script>
<script>
function getPlayers() {
$.ajax({
url:“team"+$("#team").val()+”.json”,
dataType:"json",
cache:true,
error:function() {alert("Cannot retrieve.");},
success:function(result) {
if (result && result.players) {
fillin(result.players);
} else {
alert("No data provided.");
}
}
});
}
function fillin(playerlist) {
$("#players").text(playerlist+"");
}
</script>
<select id="team" onchange="getPlayers()"><option value="">--Choose--</option>
<option value="1">Team Alpha</option><option value="2">Team Beta</option></select>
<div id="players"></div>
Wow, just one line of code.
More control over browser caching
• Your server exerts some control over caching
• Server can specify that a certain page
– Should NOT be cached at all
– Should INDEED be cached if possible
– Should INDEED be cached if possible, but only for a
certain amount of time
– Should cache in even more complex ways (that you
probably don't need to know, for now)
• All of these OVERRIDE your AJAX cache param
• All these apply also to the web page
All these apply also to the web page
• When your PHP generates some HTML, the
PHP can send a cache control header
– So that the browser caches the page (or not)
• ALSO works very nicely for JS and CSS
– Put your JS and CSS in another PHP file
– At the top of your PHP file, send headers
– Link with your main page with <script> and <link>
Server telling browser NOT to cache
JSON (server-side)
<?php
header("Expires: Tue, 1 May 2012 10:00:00 GMT"); // in the past
header("Cache-Control: no-cache");
echo '{"players":["Chet","Emelia","Rob","Tami"]}';
?>
HTML (server-side)
<?php
header("Expires: Tue, 1 May 2012 10:00:00 GMT"); // in the past
header("Cache-Control: no-cache");
?>
<html><body><?php echo time()."" ?>
<a href="mydata.php">test</a></body></html>
Server telling browser INDEED to cache
JSON (server-side)
<?php
$nsecs = 7*24*60*60; // 7 days in the future
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()+ $nsecs),true);
header("Cache-Control: public, max-age=$nsecs",true);
?><?php
echo '{"players":["Chet","Emelia","Rob","Tami"]}';
?>
HTML (server-side)
<?php
$nsecs = 7*24*60*60; // 7 days in the future
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()+ $nsecs),true);
header("Cache-Control: public, max-age=$nsecs",true);
?>
<html><body><?php echo time()."" ?>
<a href="mydata.php">test</a></body></html>
Caching in proxy servers
• Remember that there might also be proxy servers
between the browser and the server
– The http headers shown in the preceding slides will
also control caching by proxies
• This will affect all users behind those proxies
– There are also http headers you can use to control just
browsers or just proxies
• Under some circumstances, http cache headers
are ignored
– E.g., if user clears the cache, or runs out of space, or if
the request is an http POST
Summary so far
• You can store results in JS variables
– Takes some code, but you have lots of control
• http-based caching
– Can be specified with 1 line of JS in AJAX code
– Can be specified with 2 lines of PHP on server
– Can be used to control browser or proxy caching
– Might be disregarded
Moving to the server…
Examples of expensive computations
• Retrieving data from the database
– Such as retrieving a list of records
– Especially if you need to join multiple tables or do
an aggregate query
• Formatting data as HTML
– E.g., if you have a site for browsing different
schools' courses, generate the HTML once and
cache it
Where should results be cached?
• If the results are only needed by one user
– If the results are only needed in the client
• Then cache in JS or browser (http headers)
– Else
• Cache in the PHP session
• Else
– Cache in the database or a file on the server
Example of caching in the session
<?php
session_start();
$teamdflt = (isset($_SESSION['team'])) ? $_SESSION['team'] : "";
?>
<script src="jquery-1.8.2.min.js"></script>
<script>
function getPlayers() {
$.ajax({
url:"mydata.php?team="+$("#team").val(),
dataType:"json",
cache:true,
error:function() {alert("Cannot retrieve.");},
success:function(result) {
if (result && result.players) {
fillin(result.players);
} else {
alert("No data provided.");
}
}
});
}
function fillin(playerlist) {
$("#players").text(playerlist+"");
}
$(document).ready(getPlayers);
<?php
mydata.php
session_start();
$_SESSION["team"] = $_REQUEST['team'];
echo '{"players":["Team' .
$_SESSION["team"] .
'","Chet","Emelia","Rob","Tami"]}';
/* what is wrong with the code above? hint: security */
?>
Example of caching in files
<?php
ini_set('display_errors', 'On');
$mysql_handle = mysql_connect('oniddb.cws.oregonstate.edu', 'scaffidc-db', 'tzBs5Bf8uDAAvqiK') or die("Error connecting to database server");
mysql_select_db('scaffidc-db', $mysql_handle) or die("Error selecting database: $dbname");
mysql_query("drop table player"); mysql_query("create table player(pid integer, tid integer, pname varchar(20), primary key(pid))");
mysql_query("insert into player(pid, tid, pname) values(1,1,'Jim')"); mysql_query("insert into player(pid, tid, pname) values(2,1,'Carrie')");
mysql_query("insert into player(pid, tid, pname) values(3,1,'Karen')"); mysql_query("insert into player(pid, tid, pname) values(4,1,'Chris')");
mysql_query("insert into player(pid, tid, pname) values(5,2,'Kecia')"); mysql_query("insert into player(pid, tid, pname) values(6,2,'Pablo')");
mysql_query("insert into player(pid, tid, pname) values(7,2,'Monty')"); mysql_query("insert into player(pid, tid, pname) values(8,2,'Becca')");
$team = isset($_REQUEST["team"]) ? $_REQUEST["team"] : "";
if (!preg_match('/^[0-9]+$/', $team))
echo '{"players":["none '.$team.'"]}';
else {
$filename = "team".$team.".txt"; // note, this should be a .txt; do NOT use .php; we will discuss in the security lecture
if (file_exists($filename)) {
echo file_get_contents($filename);
} else {
$rs = mysql_query("select * from player where tid = " . $team);
$nrows=mysql_numrows($rs);
$rv = '{"players":[';
for ($i = 0; $i < $nrows; $i++) {
if ($i > 0) $rv .= ',';
$rv .= '"'. htmlspecialchars(mysql_result($rs,$i,"pname")) . '"';
}
$rv .= ']}';
Check if file exists;
Read & return if so.
echo $rv;
// FYI, see also file_put_contents
$file = fopen($filename,"w");
fwrite($file, $rv);
fclose($file);
}
}
mysql_close();
?>
Otherwise, perform
the expensive
computation.
Then put the
result in the cache.
Caching in the database
• You could also define a blob and store the
JSON string in the database
• This is left as an exercise for you, if you like.