DEV Community

Cover image for Project #1: Loadtest
Abdulaziz Hamzah
Abdulaziz Hamzah

Posted on

Project #1: Loadtest

Overview

A minimal wrk clone written in Go for learning purposes. This is a simple HTTP load testing tool that demonstrates concurrent programming and performance measurement. The tool sends concurrent HTTP requests to a target URL and provides detailed statistics about latency, throughput, and success rates.

Technology Stack

  • Language: Go
  • Key Libraries: net/http, flag, sync, time
  • Tools: Command-line interface

Learning Goals

What I aimed to learn from this project:

  • Go goroutines and channels for concurrent programming
  • Semaphore pattern for controlling concurrency
  • HTTP client configuration and timeout handling
  • Performance measurement and statistics collection
  • Command-line interface design with flag parsing

Key Features

  • HTTP load testing with configurable concurrency
  • Configurable request count and timeout
  • Real-time statistics (latency, throughput, success/failure rates)
  • Simple command-line interface
  • Safe concurrency with semaphore pattern

Technical Challenges & Solutions

Challenge 1: Managing concurrent requests safely

Problem: Needed to control the number of concurrent HTTP requests to avoid overwhelming the system and the target server.

Solution: Implemented a semaphore pattern using buffered channels. Created a worker pool that limits concurrent goroutines by passing "tokens" through a channel. This ensures exactly the specified number of requests run concurrently.

Challenge 2: Accurate timing measurements

Problem: Needed to measure individual request latencies while also calculating overall throughput.

Solution: Used time.Now() before each HTTP request and calculated duration after completion. For overall throughput, measured total time from start to finish and divided by completed requests.

Challenge 3: Proper resource cleanup

Problem: HTTP response bodies needed to be closed to prevent memory leaks, especially with many concurrent requests.

Solution: Used defer resp.Body.Close() immediately after checking for errors to ensure resources are always cleaned up, even if panics occur.

Code Architecture

The project follows a clean separation of concerns:

  1. main.go: Entry point, argument parsing, and result reporting
  2. cli.go: Command-line flag definitions and parsing logic
  3. worker.go: Core concurrent execution logic using semaphore pattern
  4. stats.go: Statistical calculations and result aggregation

Key design patterns:

  • Semaphore Pattern: Buffered channel controls concurrent access
  • Worker Pool: Goroutines execute tasks from a shared channel
  • Sync.WaitGroup: Ensures all goroutines complete before exiting

Installation & Usage

# Clone and build
git clone https://github.com/Azizham66/loadtest.git
cd loadtest
go build -o loadtest .

# Basic usage
./loadtest -url=https://example.com -requests=100

# High concurrency test
./loadtest -url=https://api.example.com -requests=1000 -concurrency=50

# Custom timeout
./loadtest -url=https://slow-server.com -requests=500 -timeout=10
Enter fullscreen mode Exit fullscreen mode

Options

  • -url string: URL to stress test (required)
  • -requests int: Number of requests to send (default: 10)
  • -concurrency int: Number of concurrent requests (default: 10)
  • -timeout int: Timeout in seconds (default: 5)

What I Learned

Technical Skills

  • Go Concurrency: Basic understanding of goroutines, channels, and select statements
  • Semaphore Pattern: How to implement resource limiting using buffered channels
  • HTTP Client Configuration: Custom timeouts and connection management in Go
  • Performance Measurement: Accurate timing and statistical calculations
  • CLI Development: Flag parsing and user-friendly command-line interfaces

Concepts & Patterns

  • Concurrent Programming: Safe coordination between multiple goroutines
  • Resource Management: Proper cleanup in concurrent environments
  • Error Handling: Graceful failure handling in distributed systems
  • Statistics: Latency distribution and throughput calculations

Areas of Improvement

  • Better Code Organization: Implement proper Go package structure with cmd, internal, and pkg directories, plus interface abstractions for testability and configuration management
  • Enhanced Error Handling: Create custom error types for different failure scenarios, implement error aggregation for better categorization, and add retry logic for transient failures

Project Statistics

  • Duration: 1 day
  • Lines of Code: ~200 lines across 4 files
  • Difficulty: Beginner/Intermediate
  • Technology Area: System Programming / Open Source Tooling

Related Resources


This is Project #1 of my 100 Projects Challenge. Read more about the challenge here.

Top comments (0)