Performance Testing

Application Performance Testing

1. Test Preparation (On Local Machine)

  1. Install k6
# Windows (using chocolatey)
choco install k6

# MacOS
brew install k6

# Linux
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6
  1. Verify installation
k6 version

2. Create Test Script

  1. Create test-performance.js
import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  stages: [
    { duration: "3m", target: 100 }, // Gradually increase to 100 users in 3 minutes
    { duration: "5m", target: 100 }, // Maintain 100 users for 5 minutes
    { duration: "2m", target: 0 },   // Decrease to 0 in 2 minutes
  ],
  rps: 200,                         // 200 requests/second
  thresholds: {
    http_req_duration: ["p(95)<500"], // 95% requests under 500ms
    http_req_failed: ["rate<0.01"],   // Error rate below 1%
  },
};

export default function () {
  const BASE_URL = "http://<YOUR_ALB_DNS>/"; // Replace with your IP:PORT or ALB DNS

  // Test homepage
  const response = http.get(BASE_URL);

  // Verify response
  check(response, {
    "status is 200": (r) => r.status === 200,
  });

  sleep(1);
}

3. How to Run Test

# Save script to test-performance.js
k6 run test-performance.js

4. Gradual Test Scenarios

  1. Basic Test (Warm Up)
import http from "k6/http";
import { check } from "k6";

export const options = {
  stages: [
    { duration: '1m', target: 100 },    // Gradual increase
    { duration: '2m', target: 100 },    // Maintain stable
    { duration: '1m', target: 0 }       // End
  ],
  rps: 200
};

export default function () {
  http.get("http://<YOUR_ALB_DNS>/");
}

Purpose: System warm-up, basic testing

  1. Heavy Test (High Load)
import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  stages: [
    { duration: '3m', target: 500 },    // Sharp increase
    { duration: '5m', target: 500 },    // Maintain high load
    { duration: '2m', target: 0 }       // End
  ],
  rps: 1000
};

export default function () {
  // Heavy computation
  let result = 0;
  for(let i = 0; i < 100000; i++) {
    result += Math.sqrt(i);
  }

  // Concurrent requests
  const response = http.get(BASE_URL + "/");

  check(responses, {
    "status is 200": (r) => r.status === 200
  });

  sleep(0.1);
}

Test Execution Notes:

  1. Run scripts sequentially
  2. Wait for system stabilization between tests (5-10 minutes)
  3. Monitor and record results at each level

On EC2 Instance

Performance Test Results

Basic Test (Warm Up) target-cpu Heavy Test (High Load) target-cpu

Detailed Performance Test Analysis

  1. Basic Metrics

    MetricTest 1 (100 VUs)AssessmentTest 2 (500 VUs)Assessment
    Duration4 minutes15 minutes
    Total requests3,42226,354
    Requests/second14.25⚠️ Low29.28❌ Very low for 500 VUs
    Success rate100%100%
  2. Response Time

    MetricTest 1 (100 VUs)AssessmentTest 2 (500 VUs)Assessment
    Average5.24s❌ High12.95s❌ Extremely high
    Minimum343.39ms212.27ms
    Median4.84s❌ High15.83s❌ Unacceptable
    Maximum55.84s❌ Large spike18.16s❌ Too high
    p907.75s❌ Poor16.84s❌ Very poor
    p9510.26s❌ Poor16.88s❌ Very poor
  3. Request Phases

    PhaseTest 1 (100 VUs)AssessmentTest 2 (500 VUs)Assessment
    Blocking134.05ms⚠️ High1.37ms
    Connecting58.63ms1.35ms
    Waiting3.99s❌ High12.95s❌ Extremely high
    Receiving1.1s⚠️ High307.01µs
    Sending143.45ms968.27µs
  4. Data Transfer

    MetricTest 1 (100 VUs)AssessmentTest 2 (500 VUs)Assessment
    Data received924 kB/s76 kB/s⚠️ Low
    Data sent1.2 kB/s2.5 kB/s

Main Analysis

  1. Critical Issues:
- Response time too high in both tests
- Waiting time is the main bottleneck
- Throughput doesn't scale with VUs
- p90/p95 show unstable performance

On EC2 Instance After Using ALB and Auto Scaling

Performance Test Results

Basic Test (Warm Up) target-cpu

  1. Overall Comparison

    MetricBefore (EC2)After (ALB+ASG)% ImprovementAssessment
    Throughput (req/s)14.2516.92+18.7%✓ Significant increase
    Avg Response Time5.24s4.46s-14.9%✓ Good reduction
    Max Response Time55.84s10.16s-81.8%✓ Major improvement
    Blocking Time134.05ms1.04ms-99.2%✓ Significant decrease
    Data Transfer924 kB/s1.1 MB/s+19%✓ More efficient
  2. Key Improvements

    AspectBeforeAfterResult
    Load handlingPerformance degraded at high loadStable at high load✓ Achieved
    StabilityMany spikes (55.84s)Few spikes (max 10.16s)✓ Achieved
    ConnectionHigh wait times99% reduction in wait time✓ Achieved
    BandwidthLimited by single instanceDistributed across instances✓ Achieved
  3. Summary of Improvements

Resolved:
- Load processing bottleneck ✓
- Response time spikes ✓
- Connection wait time ✓
- Scalability ✓
  1. Conclusion
- ALB+ASG improved overall performance by 18.7%
- Reduced maximum response time by 81.8%
- System is more stable and reliable
- Ready for scaling
- However, this test was only at basic level, only using ALB and not yet reaching Auto Scaling usage. In the next section, let's examine performance at heavy load to see results after using Auto Scaling.

Heavy Test (High Load) target-cpu

[Continue with the rest of the analysis…]

Testing Notes:

  1. Replace ALB DNS in script
  2. Ensure security group allows traffic
  3. Monitor resources during testing
  4. Verify auto scaling behavior

Complete!