-
Notifications
You must be signed in to change notification settings - Fork 3
/
statistics.go
143 lines (124 loc) · 2.94 KB
/
statistics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"bytes"
"encoding/gob"
"fmt"
"log"
"os"
"sort"
"sync"
"time"
)
type Statistics struct {
MaxRequest int
StartTime time.Time
Delta time.Duration
Config *Config
}
type NodeStats struct {
Success uint32
Fail uint32
Concurrency int
Time time.Duration
PathCount map[string]uint32
PathTime map[string]time.Duration
}
type AvarageTimeByPath struct {
Path string
Time float64
}
type AvarageTimeStats []AvarageTimeByPath
func (s AvarageTimeStats) Len() int {
return len(s)
}
func (s AvarageTimeStats) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s AvarageTimeStats) Less(i, j int) bool {
return s[i].Time < s[j].Time
}
func (s *Statistics) PrintAfterDuration(duration int) {
time.Sleep(time.Duration(duration) * time.Second)
s.Print()
os.Exit(0)
}
func (s *Statistics) printGob() {
delta := s.Delta
var buf bytes.Buffer
var n NodeStats = NodeStats{
Success: SUCCESS,
Fail: FAIL,
Concurrency: s.MaxRequest,
Time: delta,
PathCount: PathCount,
PathTime: PathTime,
}
enc := gob.NewEncoder(&buf)
err := enc.Encode(n)
if err != nil {
log.Fatal("encode:", err)
}
fmt.Print(buf.String())
}
func (s *Statistics) printHumanReadable() {
delta := s.Delta
nreq := SUCCESS + FAIL
rps := float64(nreq) / float64(delta.Seconds())
fmt.Printf("\nrequest count:%d, concurrency:%d, time:%.5f[s], %f[req/s]\n",
nreq, s.MaxRequest, delta.Seconds(), rps)
fmt.Printf("SUCCESS %d\n", SUCCESS)
fmt.Printf("FAILED %d\n", FAIL)
var avgTimeByPath map[string]float64 = map[string]float64{}
var totalCount uint32
var totalTime time.Duration
for path, cnt := range PathCount {
totalTime += PathTime[path]
totalCount += cnt
avgTimeByPath[path] += PathTime[path].Seconds() / float64(cnt)
}
fmt.Printf("Average response time[ms]: %v\n",
1000.*totalTime.Seconds()/float64(totalCount))
if s.Config.ShowReport {
var stats AvarageTimeStats = []AvarageTimeByPath{}
fmt.Printf("Average response time for each path (order by longest) [ms]:\n")
for path, time := range avgTimeByPath {
stats = append(stats, AvarageTimeByPath{Path: path, Time: time})
}
sort.Sort(sort.Reverse(stats))
for i := 0; i < len(stats); i++ {
fmt.Printf("%.3f : %s\n", stats[i].Time*1000., stats[i].Path)
}
}
}
func (s *Statistics) Print() {
if MODE_NORMAL != ExecMode {
s.printGob()
} else {
s.printHumanReadable()
}
}
func parseResultGob(s string) (result NodeStats, err error) {
b := bytes.NewBufferString(s)
dec := gob.NewDecoder(b)
err = dec.Decode(&result)
if err != nil {
log.Fatal("decode:", err)
}
return
}
func (s *Statistics) Collector(c chan string, wg *sync.WaitGroup) {
s.Delta = time.Duration(0)
for {
ret := <-c
n, _ := parseResultGob(ret)
SUCCESS += n.Success
FAIL += n.Fail
s.MaxRequest += n.Concurrency
s.Delta += n.Time
for path, cnt := range n.PathCount {
PathTime[path] += n.PathTime[path]
PathCount[path] += cnt
}
wg.Done()
}
}