Cloudflare CDN (Content Delivery Network)

Best practices for web applications often call for the use of a CDN. Those of you that have worked with YSlow! are likely very accustomed to seeing warnings for this reason. I’ve found that CloudFlare is very easy to setup, and for basic services costs absolutely nothing. In addition to the obvious performance advantages of using a CDN to offload much of your network traffic, it also has the advantage of improved security.

CDN’s work by caching a copy of your static content at several locations around the world, making it closer and faster for your users.

Implementation takes only minutes as it requires that you:

  1. create a (free) account,
  2. retrieve your existing DNS values from your current provider,
  3. determine direct vs. CDN “cloud” routing for each subdomain,
  4. change your DNS records to point to the CloudFlare DNS servers

Some additional advantages I’ve seen since implementing:

  • Site remains available in limited capability to users during server outages or upgrades.
  • Simplified network configuration as all requests can be sent outside of the LAN for users local to the servers
  • IPv6 dual-stack support

REFERENCES:

Yahoo! Exceptional Performance (for Web Applications)

I spend a LOT of time trying to optimize web applications to run and appear as fast as possible, one of the most valuable tools I have in my “bag of tricks” is the YSlow! plugin for Firefox.

It integrates in the browser and gives a near real-time scoring of the pages you visit and suggestions on how to improve them. While some of the suggestions are not practical (for example: use of a CDN) the bulk of them can be applied to your application code or server with a little bit of work.

The rules and scoring mechanisms are well documented at the following website:

The YSlow! plugin is available here:
http://developer.yahoo.com/yslow/

Happy… Faster Surfing!

Free Windows Defragmentation Software

Windows, due to it’s MS-DOS heritage has a lot of problems due to disk fragmentation.  To maintain optimal disk read speed, it is advised to “defrag” on a regular basis.   Whether or not LINUX has similar problems remains a subject of debate.

I’ve used many different defrag utilities over the years,  my current choices are Diskkeeper Lite and Defraggler.

Most of these vendors are free or provide free trials of their software, I’ve noted the versions I’m familiar with.

Here’s the run-down:

  • Windows Defrag – installed with Windows.
    •  this is provided with (I believe) all versions since Windows 98.
  • Diskeeper – retail
    • – this is the commercial version that was licenced to Microsoft for use with Windows.
    • Search for the older free “Diskeeper Lite 7.0.418”
  • Pirisoft Defraggler – free
  • O&O Defrag – retail, search for older version 4 which was free.
  • Norton Speed Disk – retail

I have not used the following, but they appear to be worth a look:

WARNING – if you use hard-drive encryption, defragging may cause your drive to become unreadable.  Defrag with caution.

Happy Defragging!

Javascript ‘Response Time’ measurement (latency)

Here’s another ‘fun’ trick. When you build complex web applications, performance metrics start to become an issue. Unfortunately, web tools for this are not typically available within the browser itself and ‘testers’ often rely of such non-technical solutions as stop-watch timing. Not only is this time consuming, but it is nearly impossible to reproduce as the ‘time’ includes the hand-eye coordination of the person using the watch.

In defense of the software itself, there are several Mozilla add-ons to help with this issue, but my solution is in your application code and as such can be enhanced to provide notification or logging with some additional work.

If you’ve ever used a 3270 Emulator (Mainframe “Green Screen”) you’re probably familiar with seeing this data as most 3270 clients expose it somewhere on the screen.

The trouble here is that there is no good API to do this, and no javascript variables are persisted across page loads. (cookies would be overkill). What we’re left with is the browser window-name itself, while it’s normally used when naming ‘popup’ windows and is not visible directly to the user, it provides a ‘safe’ place to store this transient data between pages.
When leaving a page we store the current time, to be sure that we can find the correct data in the window name we use unique prefix and suffix values and add the current name so that it can be restored later.

When the new page is loaded we have to compare the current time with the stored time, then we have to be sure to restore the window ‘name’ as can’t be sure about what other reason it may be named, and we don’t want to interfere.

NOTE: If you also have access to the server code (PHP or Servlet for example) or can wrap calls to external systems like databases, you can make this much more granular by including those times. In that case you could report total time, extract database time, then extract servlet time, then ‘deduce’ network latency itself! This goes a long way when troubleshooting vague user experiences when they indicate that the “site is slow” as you can now pinpoint the problem area(s) to focus on.

WARNING: For Mozilla/Firefox the default security settings prevent JavaScript from modifying the ‘window status’ used in the example code. In a real implementation you might consider using DHTML to insert the output somewhere else. Otherwise changing Mozilla Firefox 2.x’s settings is found at Tools, Options, Content Tab, Advanced JavaScript settings.

<html>
<head>
<script>
var build=’GiantGeek Example’; // you could put build label information here 🙂
var PRE=”MMSpre”;
var SUF=”MMSsuf”;

function xload(){
var tim=grvGetDuration();
build=build + tim;
grvWindowStatus(build);
}
function xclose(){
grvWindowStatus(”);
}
function xlinkObj(obj,url){ // this is for all valid links
grvSetTimeclean();
window.location.replace(uniqueUrl(url)); // ‘replace’ has side-effect of ‘restricting’ back-button, or ‘location’
return false;
}
function grvMillis(){
return new Date().getTime();
}
function grvSetTimeclean(){
var dummy=grvGetTimeclean(); // get any remainder (dupes?)
var x=grvGetName() + grvMms();
grvSetName(x);
}
function grvMms(){
return PRE + grvMillis() + SUF;
}
function grvGetDuration(){
var rc=”;
var old=grvGetTimeclean();
if(old!=”){
rc=” [” + (grvMillis() – old)/1000 + “]”;
}
return rc;
}
function grvGetTimeclean(){
var x=grvGetName();
var pre = x.indexOf(PRE);
var suf = x.indexOf(SUF);
var rc=”;
if((pre >= 0) && (suf > pre)){
rc=x.substring(pre+PRE.length,suf);
// get the garbage in the name (around mms)
var p=x.substring(0,pre);
//var s = x.substr(suf+SUF.length);
//assemble new name (without mms)!
grvSetName(p);
}
if(pre==0){
grvSetName(”);
}
return rc;
}
function grvGetName(){
var rc = window.name;
if(rc==undefined){rc=”};
return rc;
}
function grvSetName(x){
window.name=x;
}
function grvWindowStatus(txt){
window.defaultStatus=txt;
}
function uniqueUrl(x){ // this adds a timestamp to URLs
var mms = grvMillis();
var delim = “?”;
if(x.indexOf(“?”) >=0) { delim = “&”; }
return x + delim + ‘time=’ + mms;
}
</script>
</head>
<body onunload=”xclose();” onload=”xload();”>
</body>
</html>