Are you working on a new web app that will win the hearts of its users? Are you a resourceful client of a software house, a dedicated product owner, or an ingenious developer?
Then, you want the user experience to be as good as possible – regardless of whether your app is a personal project or the next Facebook-killer. Graphic design and user interface are exciting, but their less obvious cousin, performance, is no less important. If you would like to take care of performance testing yourself or introduce your QA team to this task, keep reading – this blogpost will be about JMeter, an easy-to-use, yet powerful (and free!) tool to perform load tests with.
Web apps are under constant onslaught. Under the effortless facade of sleek user interfaces, CPUs get red-hot as they respond to users’ requests and plow through databases. Whenever the CPU load gets excessively high, the site runs slow and users may say it’s buggy, even if the visual design and logic in the code are flawless. Hardly anything ruins user experience as much as the dreaded 504 Gateway Timeout Error. That’s why it pays to test the performance of your apps beforehand! With a well-designed load test, it is possible to spot the problem before it’s too late and your users flee in terror.
Some tools give you something to look at sooner than JMeter does, but often this is the case of “easy to learn, not much to master”. Scenario recording tools will allow you to simulate a thousand users that do the exact same thing over and over again. In contrast, JMeter requires a little more practice to get the hang of, but the possibilities it offers are endless! Simulating a crowd of users behaving in a natural way? Updating your tests after new releases with minimal maintenance required? You name it. JMeter can do it all.
Try empathising with your users, hundreds of users, all at once. What are they going try to do on your website? Some of them will view your landing page, then browse through whatever you have to offer. Others will view photos or just hit the search button to find what they want. Try to think of a few main paths your typical user takes. When load testing, you want to simulate a full user journey, from start to finish.
At the same time, you may want to think about your website. What eats up the most RAM? When is the CPU running at full speed? Depending on what your webapp does, it may blow up at different moments. Maybe you have a web store where users search through a database of thousands of products? Or maybe it is a social network site with data from multiple sources displayed at once? Every app is different, but the planning tends to usually go as follows: mind your users, know the backend, predict where the bottlenecks are and strike at them with all your might! Er, that is, with all your all carefully crafted tests. No sledgehammers necessary.
We won’t be covering installation as it’s really simple and we’re sure you got where you are by being at least a little bit tech savvy ;) First, we’ll spoonfeed you with the setup, and then we’ll explain what each part does. Start JMeter in full screen (some options may be hidden for smaller windows). Begin by loading a template from File > Templates… > Building a Web Test Plan. Expand JMeter Users. In it, you should see HTTP Request Defaults, Home page, Changes, Graph Results and Login. Click on JMeter Users. Set the Number of Threads to 20, Ramp-Up Period to 60 and Loop Count to 10.
Next up, go to the ‘HTTP Request Defaults’ element. In Web server > Server name or IP type in your full domain name. To the bottom, there are 2 checkboxes, Retrieve All Embedded Resources and Use concurrent pool. Check both of them. Change the Size from 4 to 6.
Now, move to the Changes element. In HTTP request > Path type the slug of the page you want your virtual user to visit (like /imghp from google.com/imghp).
That’s it! Congratulations, your first scenario is ready! You can now select the graph results, press Run > Start and marvel at the colorful dots appearing on your screen.
A thing of beauty!
You might want to know what exactly you were doing for the past few minutes. JMeter Users is a thread group, an element that controls the number of active virtual users and how many times they’re doing their job. Number of threads is basically the number of users (and note that for JMeter run with GUI, the limit is 300 separate threads, if you exceed this limit JMeter will crash). Ramp-up means how long it’ll take to load all the users – this setup means one user will be loaded every 3 seconds. Every user will perform the scenario 10 times, because you set it to 10 in loop count.
Next element: HTTP Request Defaults. Think of it as a form of global settings for HTTP Request ('home page' and 'changes' for example). The domain you set will be requested each time, so if you want to change it, you have to change it only in one spot. How convenient! Retrieve All Embedded Resources means that the user will download all the resources – fonts, images, stylesheets, just as a typical user would. There are two schools on whether you should use it or not, I prefer staying as close to the real user experience as possible. Using concurrent pool with an appropriate size is just as important, as it simulates how a browser would download those resources – in batches of 6, not one by one.
HTTP Requests are, simply put, steps your virtual users make. Changes element uses the domain address (google.com) with an extension specified as the Path (/imghp) – so that the virtual users visit google.com/imghp that is, Google Image Search page. If you need to simulate the users visiting more than one URL, insert more steps. To do so, just right click on the Changes element and select duplicate it. Rename it and change its path as you see fit.
After you start the test, you’ll see results pouring in in Graph Results. Take notice of the average throughput. That’s how many requests were sent per minute. See how it rises? That’s the ramp-up period. After the number of users stabilizes you can see how the remaining parameters behave – if you notice that over time the average response time (Average in the Graph Results) increases, it will mean that your server isn’t handling the load efficiently.
While Graph Results are very pretty, you will probably need more detailed data to record how the performance of the app changes. Luckily, JMeter has plenty of tools (called Listeners) for that! Feel free to experiment with all of them, though I’d recommend starting with View Results Tree. It provides all info you need to get to know what is wrong and debug the app.
- Know what your goal is – a scenario for a brutal spike on one page is an entirely different test than a steady, long-term heavy load.
- Always start small. The golden value is 250 threads per server's CPU core (for simple scenarios), but you should never start with it. Be gentle, never go over 50 in the first few runs, so that you don’t kill the server. Downtimes directly translate into lost money.
- Monitor the server from as many angles as you can during a load test, you never know where something might pop up. It’s good to have at hand a developer looking at the server console.
- Run the script a few times and compare the results, especially if you're running those on a working production server.
- Include as many types of user interaction as you can: from visiting paths to sending private messages, or checkout (if possible).
- Don’t stress test random servers you don’t own. It’s called Denial of Service (DoS) attack, and it’s illegal.
Now you are ready to test the performance of your app. Have fun!