Measuring Javascript Performance

Background

I was recently experiencing some Javascript performance issues while working on a physical-to-digital interactive exhibit for one of my clients at Deeplocal. I was looking at a block of code that ran at 60 Hz (paper.js) and noticed a handful of jQuery lookups. Would pure Javascript or caching speed things up? I figured the only way to know would be to try a few approaches and measure the results.

After some quick StackOverflow-ing about the topic “measuring Javascript performance”, I saw a lesser-accepted comment about a performance.now() function that could aid my experiment. Apparently the WebPerf Working Group at Google decided that Chrome’s Javascript engine needed a timer with higher resolution than Date.now(). The performance function returns the floating point milliseconds since that particular page started to load [1]. Time to test it out.

Thoughts

The jQuery selector is the laziest of the three. Based on that fact, I’m guessing it’s also the worst performant. It feels like jQuery is in every project and it’s shorter to type, so I generally go this route unless I have a compelling reason not to (which we may create).

function doStuff() {
// do stuff
var theElement = $('#the-element');
// do more stuff
}

A native Javascript lookup, such as document.getElementById(), would also work for our purpose. The jQuery selector uses this function in its implementation and has additional library overhead, so the pure Javascript version should be faster.

function doStuff() {
// do stuff
var theElement = document.getElementById('the-element');
// do more stuff
}

The third option is a hybrid approach. I still use the jQuery selector, but cache a reference to that object outside of the function doing the work. The lookup isn’t happening on every iteration; the code is just referencing that variable. I suspect this will outperform the other two methods.

var theElement = $('#the-element');
function doStuff() {
// do stuff
var localReference = theElement[0];
// do more stuff
}

Kudos for reading halfway!

 
1 Kudos
Don't
Move

Data

I wrapped for-loops around the code in question, ranged the iteration size from 10 to 1000, and ran the tests. Below is the collected data, with data points in milliseconds.

Num. Iterations Cached jQuery jQuery Lookup Javascript Lookup
10 2.500 6.500 2.500
50 0.500 3.900 1.700
100 0.450 3.150 0.950
500 0.880 1.440 0.440
1000 0.340 2.035 0.470

Results

The jQuery selector clearly has the worst performance by a factor of 10, but the other two methods are rather close. I was surprised to see the cached jQuery perform worse than the Javascript lookup at any number of iterations, but I suspect with more trials this may resolve itself.

There are a few statistical factors that could be affecting my data, including the small sample set and the use of average versus median values. Also, in an ideal environment, I could reproduce Chrome’s exact state for every trial because its background activity likely impacts the performance results on some scale.

So there you have it – for any highly accessed HTML element, be sure to cache references rather than repeatedly query them to improve the performance of your Javascript. If there’s a flaw in my logic or another topic you’d like to see an article about, please let me know! Thanks for reading.

[1]https://developers.google.com/web/updates/2012/08/When-milliseconds-are-not-enough-performance-now

If you liked this article, subscribe to my newest content by leaving your email address below. I’ll only notify you when I post new articles [or have something interesting come up?], and I won’t email you more than once per week. I respect your privacy, I don’t sell your data, and there will always be an ‘Unsubscribe’ button.

The Nest Vending Machine

Deeplocal + Nest, Summer 2016

Nest tasked Deeplocal with creating a cool experience for 500 lucky Chicago residents. Sales and rebates from local energy suppliers were reducing the price of Nest learning thermostats by $240 to a $9 price tag for a short period of time. To get the word out, Nest planned to install two unsuspecting vending machines in Chicago and give away the thermostats for free. They dropped hints on social media during the weeks leading up to the event. In the mean time, the Nest vending machine was being pieced together on the fourth floor of the Deeplocal offices, a revitalized factory building in the city’s Strip District. The machine went live on June 27th, and once the first unit was discovered, a line quickly spawned over 3 city blocks. I contributed to the Android application development for the project. We created an immersive, full screen application the guided users through a clean UX.

 
5 Kudos
Don't
Move

AWS Elastic Beanstalk Tips

Elastic Beanstalk is a service for deploying and scaling web applications in the Amazon Web Services (AWS) cloud. I recently dove in head first with a Node.js app that I needed to deploy. I spent countless minutes spamming the refresh button and scouring Stack Overflow, but in the end, I learned quite a bit. Read on for some tips.

Elastic Beanstalk Overview

Amazon provides a curated collection of their services under the name Elastic Beanstalk for deploying scalable, production-ready web applications. A few of its competitors include Heroku, Google App Engine, and Microsoft Azure. Elastic Beanstalk is free to use but you pay for the underlying resources, including:

  • Amazon EC2 – The server instances that will run your application code. These are normal EC2 instances; they show up on the AWS console’s Compute > EC2 page and you can SSH into them to do tasks as you normally would.
  • Amazon S3 -A scalable storage service to back up your server logs and previous application versions.
  • Amazon RDS / DynamoDB / SimpleDB – Chances are you’ll need some type of database for your application and another Amazon service will integrate seamlessly.
  • For other third-party services, you’ll continue to use them and pay as you normally would.

There are several application platforms supported, such as Node.js, Python, Ruby, Docker, Java, and more. The application I deployed was powered by Express and Node.js, with nginx acting as the proxy server and Elastic Beanstalk handling the server load balancing.

Deploying the application is as easy as zipping the files, uploading them to the Elastic Beanstalk web interface, and waiting for the rollout to complete. AWS automatically saves old application versions to an Amazon S3 bucket for easy rollbacks (which I used multiple times). Of course, anything you can do from the GUI, you can also do via the command line.

There’s a nice enough dashboard for monitoring your environment’s general status…

Elastic Beanstalk Overview Dashboard

…and some graphs for the data nerds in all of us.

Elastic Beanstalk Monitoring Graphs

Deployment Strategy

An Elastic Beanstalk application is the top-level entity under which your resources sit. Within an application, you can have multiple environments. Each environment contains a load balancer, auto-scaling group, and EC2 instances. Each environment has a unique URL pointing to its load balancer. Environments can be created and destroyed at any time, and you can save an environment configuration to re-create it later.

I housed our web app in two Elastic Beanstalk environments under a single application. The first environment contained the production application, which took advantage of load-balancing and auto-scaling to maintain a balance between performance and cost. The second environment contained a single server as a low-cost testbed for application and settings updates.

Cost Analysis

The campaign incurred just under $500 in AWS costs over the 3-week period. The m1.large EC2 instance accounted for the lion’s share at 2,325 hours x $0.175/hour for a total of $406.88. Other paid Amazon services (S3, DynamoDB, and CloudWatch alarms) cost an order of magnitude less coming in under $40.

To calculate these numbers, I had to dig through tables, match instance types, and make other estimations based on all of the projects we host on AWS. In the future, I’ll surely use Cost Allocation Tags to avoid this. Cost Allocation Tags are labels that you can attach to any AWS resource to organize projects and track costs in a more detailed manner. Some tags are automatically generated when you initialize a resource, but they can also be manually created and assigned. After assigning and activating tags, AWS will automatically generate cost allocation reports by tag in the Billing and Cost Management console. Read more about Cost Allocation Tags here.

Tips

Not all EC2 instance types are available in the Elastic Beanstalk environment configuration. I would recommend setting up your project when you begin development so you’re aware of what type of server is backing your system.

Use a minimum of two servers in the load balancing configuration so your production environment can take advantage of rolling updates. This allows each server to de-register from the load balancer, update to a new version, and re-activate for no-downtime updates.

You can SSH into your server instances and perform actions manually from the command line. While this is useful for testing and debugging, you will need to write an .ebextension script that performs the action and upload that script with your application bundle to take advantage of Elastic Beanstalk’s auto-scaling functionality.

Speaking of .ebextension files, OS X does not compress hidden files by default. I spent a few hours trying to debug .ebextension files that were not running because they were not in the zipped application bundle. You can confirm those files by checking the eb-activity.log where the result of the unzip command is shown. To include hidden files when compressing from Finder:

  1. Show hidden files in Finder by running this terminal command: $ defaults write com.apple.finder AppleShowAllFiles YES
  2. Select the files you want to compress
  3. Right click and select “Compress X Items”

Time zones are no fun – make sure you double and triple check your work.

Summary

Amazon’s Elastic Beanstalk service is a cost-effective, scalable environment in which to run your web applications. It’s not without its quirks and isn’t the right fit for every project, but the platform condenses a magnitude of development into an easy-to-use service that allows just about anyone to deploy and manage a cloud-based service.

Other Resources

Check out the insanely great AWS Elastic Beanstalk Survival Guide by Colin Toh.

For de-mystifying the names of AWS offerings, see AWS in Plain English.

AWS Elastic Beanstalk (Official)

*Disclaimer: I am not responsible for any losses or damages from actions you take on your servers. This is simply me documenting my experience. Do your homework.

If you found this article useful, please tell me!

 
9 Kudos
Don't
Move