Friday, December 23, 2011

Installing weighttp on AWS/EC2: ev library not found

when installing weighttp on AWS EC2 using the Amazon Linux AMI you might get errors such as:
  • "ev library not found." when running ./waf configure or
  • libev.so.4 not being found
This series of steps fixed it for me:

Saturday, November 19, 2011

Sutton with analytics

Sutton: a website to test performance & seo has not reach #1 yet :-)

The next stage is to get more information about visits, before adding google analytics the page performed something like this:


Document CompleteFully Loaded
Load TimeFirst ByteStart RenderDOM ElementsTimeRequestsBytes InTimeRequestsBytes In
First View0.355s0.321s0.383s310.355s13 KB0.597s38 KB
Repeat View0.279s0.240s0.259s310.279s13 KB0.290s23 KB



After adding it looked performed like this:

Document CompleteFully Loaded
Load TimeFirst ByteStart RenderDOM ElementsTimeRequestsBytes InTimeRequestsBytes In
First View0.364s0.331s0.393s360.364s216 KB0.687s522 KB
Repeat View0.338s0.225s0.369s360.338s24 KB0.498s34 KB


Overall its looks ok (a few extra KB - hopefully that users have already loaded from visiting other sites), however the repeat view time has crept up by nearly 0.200s, something that is not too surprising with the need to force the client to fetch a non-cacheable tracking image (GET /__utm.gif?...).



Thursday, September 1, 2011

Comparing S3 with EC2 micro instance with go

Created the same page on both S3 and on an EC2 micro instance running linux & go.

Using Google's web master tools as a bench-marker: the S3 instance is for Croydon:

And on EC2 micro instance for New Malden:
Time spent downloading a page (in milliseconds)

Looks pretty good - this is the instance that bench-marked well.

All assets etc are the same, so should be a fair comparison, I'll give it a few days to get a good average.

Tuesday, August 30, 2011

Perfomance of Go as a web server on Amazon AWS

Continuing the series on performance and exploring the Go language I wanted to see how many requests/second I could get out of an Amazon micro instance.

I used Siege for the testing of the "Sutton" server, and using the same code that gives us this sort of response:



Document CompleteFully Loaded
Load TimeFirst ByteStart RenderDOM ElementsTimeRequestsBytes InTimeRequestsBytes In
First View0.355s0.321s0.383s310.355s13 KB0.597s38 KB
Repeat View0.279s0.240s0.259s310.279s13 KB0.290s23 KB

I also added some caching on the server side, to stop it regenerating the content every time.

Using Siege from a large instance (a small instance could not generate enough requests) I got the following results:


$ siege -c 40 -t 20s -d0 http://wimbledon.chart.is


Lifting the server siege...      done.
Transactions:       28178 hits
Availability:      100.00 %
Elapsed time:       19.78 secs
Data transferred:       68.07 MB
Response time:        0.03 secs
Transaction rate:     1424.57 trans/sec
Throughput:        3.44 MB/sec
Concurrency:       37.69
Successful transactions:       28178
Failed transactions:           0
Longest transaction:        1.51
Shortest transaction:        0.00



So over 1,000 requests/second on the smallest AWS instance! the server is running at 100% CPU so some simple performance analysis could yield some significant improvements. Also some more effort around making the benchmark more trustworthy, especially with higher numbers of concurrent requests.

Wednesday, August 17, 2011

Hosting favicon.ico on a different server (Amazon S3)

To increase the performance of our very simple Where is Croydon test site static assets are hosted on S3.

One of the assets that is requested for a site is favicon.ico the icon is used against the site name in browsers (normally to make spotting it among many tabs easier). By default this is requested from the root of the site, however this can be changed by adding:
<link rel="shortcut icon" href="http://static.chart.is/favicon.ico" />
to each page (head element) on the site.

To host it on S3 requires a bucket matching the domain name, and mapping a CNAME to point to the amazon end-point. In this case using a "static" sub-domain to host these kinds of static assets. Note: if you get "Access Denied" from these its probably because of permissions for "Everyone" to open/download are not set (per asset).

Doing this means the browser can use a separate connection to retrieve the icon, and therefore process the download in parallel with other content. Its worth considering multiple sub-domains if you have many static assets. This also has the benefit of reducing requests to your site's servers, and improving server-side cache hits as well.

During testing of this a little "feature" of chrome was discovered, it requests "/favicon.ico" from you site if you do a "view page source" - even if you specify a different location.

Friday, August 12, 2011

Google Ads Async (asynchronous)

Making Google Ads asynchronous seems to be critical to achieving better performance, in this post in the continuing series on optimization of sites (Performance: the effect of google ads and Go Faster Stripes for site performance and google ads), a simple idea has some interesting implications.

The current ad code for Where is Croydon looks like this:

&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7600935420912685";
google_ad_slot = "7690333966";
google_ad_width = 336;
google_ad_height = 280;
//--&gt;
&lt;/script&gt; 
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt; 
&lt;/script&gt; 


And performs like this:
Document CompleteFully Loaded
Load TimeFirst ByteStart RenderDOM ElementsTimeRequestsBytes InTimeRequestsBytes In
First View1.939s0.289s0.426s1871.939s1252 KB2.438s1453 KB
Repeat View1.054s0.228s0.574s1821.054s26 KB1.054s26 KB

Document complete in about 2 seconds is not good enough, (given our page has nothing on it), and the advert script is going to slow down any other asset downloads (by putting the browser into serial mode).

So how can we fix this? a bit of re-plumbing should fix this, our ad script becomes:


&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-7600935420912685";
google_ad_slot = "7690333966";
google_ad_width = 336;
google_ad_height = 280;
//--&gt;
&lt;/script&gt; 
&lt;script type="text/javascript"&gt;&lt;!--
// dynamically Load Ads out-of-band
setTimeout((function ()
{
// placeholder for ads
        var eleAds = document.createElement("ads");  
        // dynamic script element
        var eleScript = document.createElement("script");  
        // remember the implementation of document.write function
        w = document.write;
        // override and replace with our version
        document.write = (function(params)
        {
// replace our placeholder with real ads
eleAds.innerHTML = params;
// put the old implementation back in place
document.write=w;
        });
        // setup the ads script element
        eleScript.setAttribute("type", "text/javascript");
        eleScript.setAttribute("src", "http://pagead2.googlesyndication.com/pagead/show_ads.js");
        // add the two elements, causing the ads script to run
        document.body.appendChild(eleAds);              
        document.body.appendChild(eleScript);           
}), 1);
                //--&gt;
        &lt;/script&gt; 


How does this work? Google's Ad script is quite "nasty" as it uses document.write, generally not a good idea  as it can only be used during page creation. So this script does two things:
  1. it dynamically inserts the Google ad script, allowing this to be separate from the main page render, hence the rest of the page can load without waiting for the adverts
  2. it re-plumbs the document.write function to instead add the ads to a placeholder element. If this is not done then the Google code will try to call document.write and it won't output anything as the document is already complete. For completeness the code re-plumbs document.write after the first call, but really there should be no other code calling it.
Now this code is far from bullet proof, or tested (WOMM), but it shows the basic principle - it works only because its specific to the Google code, a more generic solution might need to follow this approach.

What does all this effort yield us:
Document CompleteFully Loaded
Load TimeFirst ByteStart RenderDOM ElementsTimeRequestsBytes InTimeRequestsBytes In
First View0.484s0.332s0.584s1910.484s13 KB2.353s1355 KB
Repeat View0.347s0.211s0.611s1860.347s10 KB1.185s26 KB

Fully loaded has not changed (as expected, we are still loading the same amount), but document complete is massively improved - from 2 seconds to less than half a second. Whilst this might seem to be moving numbers around, it means that the browser can render the rest of the page before adverts, and since adverts can be very very slow, this can make the site appear much faster.

And for those of you who do want to cheat performance numbers, then changing the  "}), 1);" line to "}), 4000);" gives you this. A page that is "fully loaded" in 0.39 seconds - this is of course cheating, the adverts appear 4 seconds later, but https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/quick-start-quide#TOC-Fully-Loaded: looks for 2 seconds of no activity to judged fully loaded time.