Every millisecond counts!

Recently, I was working on a pet project (pluckdp), which helps ruby coders test / improve their design pattern skills.

After deploying to production, the home page was taking a whooping 3.5 seconds to load.

Knowing how small the application is, this dint make any sense. So, I digged into the reasons and fixed on the time consuming parts. This article outlines the important actions that I took during the analysis.

Initial Infrastructure

AWS (Free Tier)

  • t2.micro ec2 instance
  • RDS
  • Cloudwatch (alarms on the CPU consumption)

Servers

  • nginx
  • unicorn (1 worker)

Others

  • pluckdp.theox.in CNAME mapped to ec2-public-dns

Final Infrastructure

AWS (Free Tier)

  • t2.micro
  • RDS
  • Cloudwatch
  • Cloudfront (gzip compression for js, css)
  • Elastic-IP

Servers

  • nginx
  • unicorn (2 workers)

Others

  • pluckdp.theox.in is A mapped to elastic-ip
  • Assets served through cdn with content encoding gzip.

Brief notes on different time consuming components

Application

DNS Lookup

  • Quick search revealed that CNAME mapping does increase in latency. Setting up an A record instead of CNAME reduced the lookup time by ~250ms.
  • From what I understand, it can be further decreased if I use a domain instead of sub-domain, but I dint want to pay for a separate domain.

Connecting Time

  • The connecting time to the main request is still ~250ms. There is something seriously wrong here, but I will figure it and blog as part-2.
  • Just fyi, the connecting time for Google page load is under 15ms.

Blocking Time

  • There was not much I could do here, as am already using pre-compiled assets.

Waiting Time

  • I noticed that the average waiting time reported was around ~250ms. Am guessing it is because of the resource limitations. But, this waiting time was consistent for every request I made!
  • Introducing CDN reduced this waiting time to ~8ms. That’s a saving of ~240ms! That’s huge!!
  • Do note that introducing CDN does introduce extra DNS lookup and Connecting times. But, I noticed that both of them combined is less than 10ms.

Receiving Time

  • Enabling gzip compression in CloudFront reduced the receiving-time by ~550ms

Overall, I saved 2 seconds using the above mentioned techniques.

Unknowns

Still, there are few unknowns that I will dig into, in the coming days

  • Why does it take ~250ms connecting-time to ec2 ?
  • Why does it take ~250ms waiting-time when am sure no one else is accessing the server?
  • I noticed that the css file (~64KB uncompressed) takes around ~500ms to trigger onload. This is similar with js file.

Follow me here or on twitter for updates.