Skip to content

Instantly share code, notes, and snippets.

@aimof
Created April 9, 2018 23:20
Show Gist options
  • Save aimof/46274e1bc6c1bbac1c0a43c665a8e144 to your computer and use it in GitHub Desktop.
Save aimof/46274e1bc6c1bbac1c0a43c665a8e144 to your computer and use it in GitHub Desktop.
simple load test.
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"os"
"runtime"
"sync"
"time"
)
var (
maxGoroutine int = 10000
tps int64 = 10000
interval time.Duration = time.Second / time.Duration(tps)
duration time.Duration = 10 * time.Second
cpus int = 3
fileName string = "tmp.txt"
client http.Client = http.Client{
Timeout: 100 * interval,
}
manageCh chan bool = make(chan bool, maxGoroutine)
resultCh chan Result = make(chan Result, 100*tps)
finishConnectCh chan struct{} = make(chan struct{})
finishResultCh chan struct{} = make(chan struct{})
wgConnect sync.WaitGroup = sync.WaitGroup{}
wgResult sync.WaitGroup = sync.WaitGroup{}
)
type Result struct {
Status string `json:"status_code"`
Body string `json:"body"`
standByTime time.Time
FormattedStandByTime string `json:"stand_by_time"`
startTime time.Time
FormattedStartTime string `json:"start_time"`
endTime time.Time
FormattedEndTime string `json:"end_time"`
Err error `json:"error"`
}
// initialize Result
func newResult() Result {
return Result{
Status: "",
Body: "",
standByTime: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
FormattedStandByTime: "",
startTime: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
FormattedStartTime: "",
endTime: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
FormattedEndTime: "",
Err: nil,
}
}
func (result Result) record(file *os.File) {
b, err := json.Marshal(result)
if err != nil {
b = []byte(`{"error": "json marshal error"}`)
}
_, err = file.Write(b)
file.Write([]byte("\n"))
if err != nil {
log.Fatalln(err)
}
}
func main() {
req, err := http.NewRequest("GET", "http://localhost:8080/", nil)
if err != nil {
log.Fatalln(err)
}
runtime.GOMAXPROCS(cpus)
for i := 0; i < maxGoroutine; i++ {
manageCh <- true
}
ticker := time.NewTicker(interval)
file, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatalln(err)
}
// record result
wgResult.Add(1)
go func(file *os.File) {
firstLoop:
for {
select {
case result := <-resultCh:
result.record(file)
case <-finishResultCh:
break firstLoop
}
}
for len(resultCh) != 0 {
result := <-resultCh
result.record(file)
}
wgResult.Done()
}(file)
go func(duration time.Duration) {
time.Sleep(duration)
close(finishConnectCh)
}(duration)
connectLoop:
for {
select {
case <-ticker.C:
wgConnect.Add(1)
go doRequest(req)
case <-finishConnectCh:
break connectLoop
}
}
wgConnect.Wait()
wgResult.Wait()
}
func doRequest(req *http.Request) {
defer wgConnect.Done()
result := newResult()
result.standByTime = time.Now()
_ = <-manageCh
result.startTime = time.Now()
resp, err := client.Do(req)
result.endTime = time.Now()
if err != nil {
result.Err = err
resultCh <- result
manageCh <- true
return
}
defer resp.Body.Close()
result.Status = resp.Status
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
b = make([]byte, 0)
result.Err = err
}
result.Body = string(b)
resultCh <- result
manageCh <- true
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment