hatch-surf/cmd/loadtest/main.go
Jordan Patel fb004e0fbb fix: resolve CI failures for ELF-231 merge
- Format cmd/loadtest/main.go with gofmt
- Downgrade go.mod to go 1.24 for golangci-lint compatibility
- Update CI workflow Go version to 1.24
- Fix deprecated govet check-shadowing → shadow

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-06-24 07:56:12 +02:00

100 lines
2.4 KiB
Go

package main
import (
"flag"
"fmt"
"io"
"net/http"
"sync"
"sync/atomic"
"time"
)
func main() {
url := flag.String("url", "http://localhost:8080/healthz", "URL to test")
concurrency := flag.Int("c", 10, "concurrent workers")
total := flag.Int("n", 1000, "total requests")
flag.Parse()
var (
successCount int64
failCount int64
totalLatency int64 // microseconds
minLatency int64 = 1<<63 - 1
maxLatency int64
)
client := &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: *concurrency,
MaxIdleConnsPerHost: *concurrency,
IdleConnTimeout: 90 * time.Second,
},
}
var wg sync.WaitGroup
requests := make(chan int, *total)
for i := 0; i < *total; i++ {
requests <- i
}
close(requests)
start := time.Now()
for i := 0; i < *concurrency; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range requests {
reqStart := time.Now()
resp, err := client.Get(*url)
latency := time.Since(reqStart).Microseconds()
if err != nil {
atomic.AddInt64(&failCount, 1)
continue
}
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
if resp.StatusCode == http.StatusOK {
atomic.AddInt64(&successCount, 1)
} else {
atomic.AddInt64(&failCount, 1)
}
atomic.AddInt64(&totalLatency, latency)
// Update min/max using atomic operations for simplicity
for {
old := atomic.LoadInt64(&minLatency)
if latency >= old || atomic.CompareAndSwapInt64(&minLatency, old, latency) {
break
}
}
for {
old := atomic.LoadInt64(&maxLatency)
if latency <= old || atomic.CompareAndSwapInt64(&maxLatency, old, latency) {
break
}
}
}
}()
}
wg.Wait()
duration := time.Since(start)
fmt.Printf("Load test completed\n")
fmt.Printf("URL: %s\n", *url)
fmt.Printf("Total requests: %d\n", *total)
fmt.Printf("Concurrency: %d\n", *concurrency)
fmt.Printf("Duration: %v\n", duration)
fmt.Printf("Success: %d\n", atomic.LoadInt64(&successCount))
fmt.Printf("Failed: %d\n", atomic.LoadInt64(&failCount))
if *total > 0 {
avgLatency := float64(atomic.LoadInt64(&totalLatency)) / float64(*total)
fmt.Printf("Average latency: %.2f ms\n", avgLatency/1000)
fmt.Printf("Min latency: %.2f ms\n", float64(atomic.LoadInt64(&minLatency))/1000)
fmt.Printf("Max latency: %.2f ms\n", float64(atomic.LoadInt64(&maxLatency))/1000)
fmt.Printf("Requests/sec: %.2f\n", float64(*total)/duration.Seconds())
}
}