In part 1 of this post, we covered writing web app load tests using multi–mechanize. This post picks up where the other left off and will discuss how to gather interesting and actionable performance data from the load tests, using (of course) Tracelytics as an example.
The big problem we had after writing load tests was that timing data gathered by multi-mechanize is inherently external to the application. This means it can tell us the response times of requests when the app is under load but doesn’t identify bottlenecks or configuration problems. So we need to be gathering a bit more data about how the internals of our web application respond to the workload.
For this blog post, I’ll be using Tracelytics’ instrumentation, which is installable from OS-native packages and, in the case of Reddit, takes care of instrumenting nginx, pylons, SQL queries, memcache calls, and Cassandra calls automatically.
Test 1: ramp-up read threads
[global] run_time: 1800 rampup: 1800 results_ts_interval: 20 progress_bar: on console_logging: off xml_report: on [user_group-1] threads: 10 script: view_base.py [user_group-2] threads: 10 script: view_all.py [user_group-3] threads: 10 script: view_all_new.py [user_group-4] threads: 10 script: view_all_top.py
So, this test is going to run for 30 minutes and generate steadily increasing read-oriented loads on various pages. Like in a cooking show, I’ve taken all the waiting out, so let’s skip straight to the results!
What we’re looking at here is the performance of the deafult open-source Reddit install under a steadily increasing read load, broken down by layer of the stack:
At first, it performs like a champ. But as the number of concurrent users rises over time, we see that requests slow down. In fact, it looks like we are spending a lot of time per-request in nginx.
We also have access to machine metrics here (blue bar at bottom), so I’ve pulled up the load on the box. Our machine is bored–the max load the machine reaches is only 1.06–but it’s serving slowly! This is a sign that we might not have enough worker threads in our application layer.
In fact, the default Reddit install only sets up a single uwsgi worker. So, let’s fix that, and move on. Here’s what it looks like with 10 uwsgi processes, same workload:
It seems that we’ve traded our uwsgi queuing problems for an overloaded machine, but at least it’s fully utilizing the hardware now–and our throughput is much greater!
Test 2: ramp-up write threads
[global] run_time: 1800 rampup: 1800 results_ts_interval: 10 progress_bar: on console_logging: off xml_report: off [user_group-1] threads: 10 script: vote_comment.py [user_group-2] threads: 10 script: submit_comment.py
This test will vote and submit comments on a particular thread with inceasing numbers of logged in users. Ok, go!
One really interesting thing is that we can see there are two distinct trends in the data–one band grows slower faster than the other. Selecting them for comparison, we can see that the slower band is for rendering the comments, while the faster one is the POST requests for commenting/voting:
We might have expected to see contention for the database (in this case, postgres). However, by pushing the limits with our load tests, we figured out that the actual limiting factor will be cores on our app servers (or, in this case, server) before we have to worry about the database. Here’s what the breakdown by layer of stack looked like–note that we’re spending almost no time in our database calls (measured through sqlalchemy and the Cassandra client):
Where to go from here:
- Performance testing is not only valuable to ensure that a new Web app meets projected demand; it can also be part of your CI system to detect performance regressions during everyday development. Here’s a screencast about getting performance tests running in Jenkins.
- If your website is particularly AJAX-heavy, you may also want to do load testing that simulates a browser better and execute JavaScript in order to create the exact load patterns that users will. This makes testing significantly more resource intensive as it requires spinning up headless browsers, but can be accomplished using selenium or a hosted selenium service.
- Tracelytics performance monitoring and analysis isn’t only for load tests; most of our customers run our lightweight instrumentation in production as well as development environments. Sign up for a free trial—no credit card required.





Pingback: Solving Two Of The Most Common Web Performance Mistakes | Tracelytics Blog