Hi all. In this post I’ll go over the general approach my team uses when planning and executing performance tests in the lab.
Step 1: define the questions we’d like to answer
I view software testing as answering questions. At the beginning of a test effort we document the questions we would like to answer, and then we spend the rest of the milestone answering them.
Questions for performance generally fall into three categories:
- Resource utilization — how much CPU, disk, memory, and network does a system use?
- Throughput — how many operations per second can a system handle?
- Latency — how long does it take one operation to complete?
Here are some examples:
- How many operations per second can a server handle?
- How many concurrent clients can a server handle?
- If a server handles load for 2 weeks straight, does throughput or latency degrade? Do we leak memory?
- If we keep adding new customer accounts to a system, at what point will the system fall over? Which component will fall over first?
- When a user opens a file that is 1 GB in size, how long does it take to open? How much disk activity occurs during this process?
- When a process connects to a remote server, how much network bandwidth is used?
We spend a lot of time thinking about the questions, because these questions guide the rest of the process.
Step 2: define the performance tests
The next step is to define the performance tests that will help us answer our questions. For each performance test we identify two things: 1.) expected load and 2.) key performance indicators (KPIs).
Load is the set of operations that are expected to occur in the system. All of these operations compete for resources and affect the throughput and latency. Usually a system will have multiple types of load all occurring at the same time, and thus we try to simulate all of these types of load in a performance test.
A mistake I’ve made in the past is to not identify all types of important load. Sometimes I’ve focused too closely on one type, and forgot that there were other operations in the system that affected performance. The lesson I’ve learned: don’t test in a vaccuum.
The second part of a performance test is the key performance indicators (KPIs). These are the variables we want to measure, along with the goals for each variable. We always gather data for system resources (CPU, disk, memory, and network). We also gather data for application-specific KPIs in latency and throughput.
Step 3: automate and execute the tests
Now that the plans are complete, we focus on automation and execution. For each performance test we automate the load generation and data (KPI) collection.
Load generators are written in C#. With each load generator we attempt to mimic the expected load in the system. For example, if the load is SMTP email messages, we’ll write a generator that implements the client side of an SMTP session. If the load is SQL transactions, we’ll write functions that simulate these transactions.
Besides load, we also need to automate the collection of KPIs. This usually means collecting Windows performance counters. The .NET Framework has a PerformanceCounter class that makes collection easy.
Once things are automated, the next step is to execute the tests. Sometimes we run the tests manually only once or twice. Other times we schedule the tests to run automatically on a periodic basis. Each approach provides value in different ways and the choice depends on the team’s goals.
Step 4: report results
After tests are executed, we collect, analyze, and report results. We usually create a document that summarizes the major findings of the testing. We publish the document towards the end of the milestone.
Additionally, sometimes results are shared with folks throughout the milestone while testing is taking place. This can happen either manually, or via an automated system. For example, on our current project we are utilizing a web-based performance dashboard that a peer team created. The performance tests publish data to the dashboard automatically at the end of each run.