diff --git a/examples/simple/main.go b/examples/simple/main.go index 2fcbf86..3082f42 100644 --- a/examples/simple/main.go +++ b/examples/simple/main.go @@ -11,7 +11,7 @@ func main() { l1.WithTarget("https://remoteukjobs.com"), l1.WithRunFunc(l1.DefaultHTTPTester), l1.WithMaxParrellConns(10), - l1.WithMaxConns(6000), + l1.WithMaxConns(30), ) if err != nil { log.Fatal(err) diff --git a/http.go b/http.go index 604c594..3817464 100644 --- a/http.go +++ b/http.go @@ -17,12 +17,15 @@ func DefaultHTTPTester(target string) *Result { return result } + req.Header.Add("accept-encoding", "gzip, deflate, br") + req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0") + startTime := time.Now() rsp, err := client.Do(req) if err != nil { result.Error = err } - result.CompletedIn = time.Since(startTime).Seconds() + result.CompletedIn = float64(time.Since(startTime).Milliseconds()) result.StatusCode = rsp.StatusCode return result diff --git a/l1.go b/l1.go index fbc9602..8a823dd 100644 --- a/l1.go +++ b/l1.go @@ -15,6 +15,7 @@ type Runner struct { RunTime time.Duration RunFunc F Target string + RampUp int results []*Result } @@ -24,6 +25,7 @@ func NewRunner(opts ...Opt) (*Runner, error) { Timeout: 30 * time.Second, MaxParrellConnections: 10, MaxConnections: 10, + RampUp: 0, } for _, o := range opts { @@ -46,10 +48,18 @@ func (r *Runner) Execute() { for i := 0; i < r.MaxConnections; i++ { tasks = append(tasks, &Task{Target: r.Target, F: r.RunFunc}) } + + waitDuration := 0 + if r.RampUp > 0 { + waitDuration = r.RampUp / len(tasks) + } + // create the pool and process the tasks. - pool := newPool(tasks, r.MaxParrellConnections) + pool := newPool(tasks, r.MaxParrellConnections, waitDuration) + // the tasks are updated in memory so we don't expect a return here. pool.run() + for _, t := range tasks { r.results = append(r.results, t.Result) } diff --git a/opts.go b/opts.go index 18d9750..d085225 100644 --- a/opts.go +++ b/opts.go @@ -40,3 +40,9 @@ func WithRunFunc(f F) Opt { r.RunFunc = f } } + +func WithRampUp(seconds int) Opt { + return func(r *Runner) { + r.RampUp = seconds + } +} diff --git a/pool.go b/pool.go index 7366031..4793da2 100644 --- a/pool.go +++ b/pool.go @@ -2,6 +2,7 @@ package l1 import ( "sync" + "time" ) type Task struct { @@ -11,18 +12,20 @@ type Task struct { } type pool struct { - tasks []*Task - concurrency int + tasks []*Task + concurrency int + rampUpDuration int tasksChan chan *Task wg sync.WaitGroup } -func newPool(tasks []*Task, concurrency int) *pool { +func newPool(tasks []*Task, concurrency, rampUpDuration int) *pool { return &pool{ - tasks: tasks, - concurrency: concurrency, - tasksChan: make(chan *Task), + tasks: tasks, + concurrency: concurrency, + tasksChan: make(chan *Task), + rampUpDuration: rampUpDuration, } } @@ -32,9 +35,11 @@ func (p *pool) run() { go p.work() } - p.wg.Add(len(p.tasks)) for _, t := range p.tasks { p.tasksChan <- t + p.wg.Add(1) + + time.Sleep(time.Duration((1000 * p.rampUpDuration) * int(time.Millisecond))) } close(p.tasksChan) diff --git a/results.go b/results.go index fe25d9e..e7dd80f 100644 --- a/results.go +++ b/results.go @@ -20,14 +20,7 @@ type Result struct { } func (r *results) RequestPerSecond() float64 { - totalCompletedIn := float64(0) - for _, res := range r.Results { - if res.Error != nil { - continue - } - totalCompletedIn += res.CompletedIn - } - + totalCompletedIn := r.CompletedTime() / 1000 return float64(len(r.Results)) / totalCompletedIn } @@ -62,14 +55,7 @@ func (r *results) SuccessfulCount() int { } func (r *results) AvgResponseTime() float64 { - totalCompletedIn := float64(0) - - for _, res := range r.Results { - if res.Error != nil { - continue - } - totalCompletedIn += res.CompletedIn - } + totalCompletedIn := r.CompletedTime() return totalCompletedIn / float64(len(r.Results)) } @@ -97,7 +83,7 @@ func (r *results) Print() { fmt.Printf("Load testing %s\n", r.Target) fmt.Println("") fmt.Printf("Request per second: %.2f\n", r.RequestPerSecond()) - fmt.Printf("Average response time: %.2f seconds\n", r.AvgResponseTime()) + fmt.Printf("Average response time: %.0f ms\n", r.AvgResponseTime()) fmt.Printf("Success count: %d\n", r.SuccessfulCount()) fmt.Printf("Error count: %d\n", r.ErrorCount()) fmt.Println("")