Apache Bench Performance Analysis: Interpreting Load Test Results and Optimization Strategies


7 views

Let's break down the essential metrics from your Apache Bench (ab) results:

Concurrency Level:      200
Time taken for tests:   37.030 seconds
Complete requests:      1000
Requests per second:    27.01 [#/sec] (mean)
Time per request:       7406.024 [ms] (mean)

The 27 requests per second (RPS) rate with 200 concurrent connections indicates significant performance bottlenecks. For comparison, a well-optimized web server should handle hundreds or thousands of RPS at this concurrency level.

The connection timing breakdown reveals several interesting patterns:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       27   37  19.5     34     319
Processing:    80 6273 1673.7   6907    8987
Waiting:       47 3436 2085.2   3345    8856
Total:        115 6310 1675.8   6940    9022

Notice how the processing time (6273ms mean) dwarfs the connection time (37ms mean). This suggests the bottleneck isn't network-related but rather server-side processing.

The percentile breakdown shows response time distribution:

Percentage of the requests served within a certain time (ms)
  50%   6940
  90%   7025
  99%   8876
 100%   9022

The tight clustering between 50th and 90th percentiles (6940-7025ms) followed by a jump at 99th percentile (8876ms) indicates most requests complete consistently, with a small percentage experiencing significant delays.

Here are specific optimizations to consider based on these results:

# Example Nginx configuration optimizations
worker_processes auto;
worker_connections 1024;
keepalive_timeout 15;
keepalive_requests 100;
sendfile on;
tcp_nopush on;

For application-level improvements:

# Python Flask example with caching
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'simple'})

@app.route('/4f84b59c557eb79321000dfa')
@cache.cached(timeout=300)
def resource():
    # Your resource generation logic here
    pass

Use these Linux commands to identify specific bottlenecks during tests:

# Monitor CPU usage
mpstat -P ALL 1

# Monitor disk I/O
iostat -x 1

# Monitor memory usage
vmstat 1

# Monitor network connections
ss -s

Run tests with different concurrency levels to identify scaling patterns:

# Test sequence
ab -n 1000 -c 50 http://texteli.com/4f84b59c557eb79321000dfa
ab -n 1000 -c 100 http://texteli.com/4f84b59c557eb79321000dfa
ab -n 1000 -c 200 http://texteli.com/4f84b59c557eb79321000dfa

Plot the RPS vs concurrency to identify where performance begins to degrade.


Let's break down this Apache Bench output to understand server performance characteristics. The key metrics reveal several important aspects:

Concurrency Level:      200
Time taken for tests:   37.030 seconds
Complete requests:      1000
Requests per second:    27.01 [#/sec] (mean)
Time per request:       7406.024 [ms] (mean)

The 27 requests per second (rps) rate suggests significant performance bottlenecks when handling 200 concurrent connections. This is particularly evident when examining the connection times distribution.

The detailed connection timing metrics show how requests progress through different phases:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       27   37  19.5     34     319
Processing:    80 6273 1673.7   6907    8987
Waiting:       47 3436 2085.2   3345    8856
Total:        115 6310 1675.8   6940    9022

The high standard deviation in processing time (1673.7ms) indicates inconsistent performance, likely due to resource constraints or backend bottlenecks.

The percentile distribution reveals important thresholds:

Percentage of the requests served within a certain time (ms)
  50%   6940
  90%   7025
  99%   8876
 100%   9022

The tight cluster between 50th-90th percentiles suggests stable performance for most requests, while the jump at 99% indicates some requests experience significant delays.

When seeing these results, consider these optimization approaches:

  • Check server resource utilization during tests (CPU, memory, I/O)
  • Verify database query performance if applicable
  • Review application code for inefficient loops or algorithms
  • Consider implementing caching for repeated requests

Here's a simple script to visualize the performance data:

import matplotlib.pyplot as plt

percentiles = [50, 66, 75, 80, 90, 95, 98, 99, 100]
times = [6940, 6968, 6988, 7007, 7025, 7078, 8410, 8876, 9022]

plt.plot(percentiles, times, 'bo-')
plt.title('Response Time Percentiles')
plt.xlabel('Percentile')
plt.ylabel('Time (ms)')
plt.grid()
plt.show()

To determine if 27 rps is acceptable, consider:

  • Your application's expected traffic patterns
  • Server hardware specifications
  • Comparison against baseline performance metrics
  • Industry standards for similar applications

For most modern web applications serving dynamic content, 27 rps with 200 concurrent connections would be considered suboptimal, suggesting significant room for improvement.