Multisend latency tester

mail@pastecode.io avatar
unknown
golang
3 years ago
2.4 kB
2
Indexable
Never
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"sync"
	"time"
)

func arrayToString(A []time.Duration, delim string) string {

	var buffer bytes.Buffer
	for i := 0; i < len(A); i++ {
		buffer.WriteString(strconv.FormatInt(A[i].Milliseconds(), 10))
		if i != len(A)-1 {
			buffer.WriteString(delim)
		}
	}

	return buffer.String()
}

type Request struct {
	url    string
	method string
}

type Client struct {
	httpClient *http.Client
	request    Request
}

type Result struct {
	id        int64
	durations []time.Duration
	mu        sync.Mutex
}

func (r *Result) addResult(duration time.Duration) {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.durations = append(r.durations, duration)
}

func (r *Result) reset(id int64) {
	r.id = id
	r.durations = []time.Duration{}
}

func (r *Result) print() {
	fmt.Printf("%d,%s\r\n", r.id, arrayToString(r.durations, ","))
}

func NewClient(request Request) *Client {
	return &Client{
		httpClient: &http.Client{
			Timeout: time.Second * 5,
		},
		request: request,
	}
}

func (c *Client) Send() (time.Duration, error) {
	start := time.Now()
	req, err := http.NewRequest(c.request.method, c.request.url, nil)

	if err != nil {
		return 0, err
	}

	res, err := c.httpClient.Do(req)
	if err != nil {
		return 0, err
	}

	_, err = ioutil.ReadAll(res.Body)

	return time.Since(start), nil
}

func main() {
	var batchSize int
	var count int
	var endpoint string
	var interval int
	flag.StringVar(&endpoint, "url", "", "url to multi send too")
	flag.IntVar(&batchSize, "batchSize", 0, "number of orders to send in a batch")
	flag.IntVar(&count, "count", 0, "number of attempts")
	flag.IntVar(&interval, "interval", 0, "attempt interval in ms")
	flag.Parse()

	req := Request{
		url:    endpoint,
		method: http.MethodGet,
	}

	client := NewClient(req)
	result := Result{
		id:        0,
		durations: make([]time.Duration, 0),
	}

	var wg sync.WaitGroup

	for i := int64(0); i < int64(count); i++ {
		result.reset(i + 1)

		for j := 0; j < batchSize; j++ {
			wg.Add(1)
			go func(result *Result) {
				defer wg.Done()
				if duration, err := client.Send(); err == nil {
					result.addResult(duration)
				}
			}(&result)
		}

		wg.Wait()
		result.print()
		time.Sleep(time.Millisecond * time.Duration(interval))
	}

}