-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstats.go
134 lines (119 loc) · 2.97 KB
/
stats.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
package main
import (
"fmt"
"math"
"time"
"github.com/miekg/dns"
)
type Stats struct {
RunTime time.Duration
TotalLatency time.Duration
TotalLatencySquare float64
TotalRequestSize int64
TotalResponseSize int64
MinResponseTime time.Duration
MaxResponseTime time.Duration
NumSend int64
NumCompleted int64
NumTimeout int64
NumInterrupted int64
ResponseCodes [16]int64
QPS float64
startTime time.Time
endTime time.Time
}
func (s *Stats) printSummary() {
s.RunTime = s.endTime.Sub(s.startTime)
fmt.Printf("Statistics:\n\n")
// print basic info
fmt.Printf(" Queries sent: %d\n", s.NumSend)
fmt.Printf(" Queries completed: %d (%.2f%%)\n", s.NumCompleted,
SafeDiv(100*s.NumCompleted, s.NumSend))
fmt.Printf(" Queries lost: %d (%.2f%%)\n", s.NumTimeout,
SafeDiv(100*s.NumTimeout, s.NumSend))
if s.NumInterrupted > 0 {
fmt.Printf(" Queries interrupted: %d (%.2f%%)\n", s.NumTimeout,
SafeDiv(100*s.NumInterrupted, s.NumSend))
}
fmt.Printf("\n")
// print rcodes info
s.printRcodes()
// print QPS and misc
fmt.Printf(" Average packet size: request %.f, response %.f\n",
SafeDiv(s.TotalRequestSize, s.NumSend),
SafeDiv(s.TotalResponseSize, s.NumCompleted))
fmt.Printf(" Run time (s): %.6f\n", s.RunTime.Seconds())
fmt.Printf(" Query per second: %.6f\n",
SafeDiv(s.NumCompleted, int64(s.RunTime.Seconds())))
fmt.Printf(" Average Latency (s): %.6f (min %.6f, max %.6f)\n",
SafeDiv(int64(s.TotalLatency.Seconds()), s.NumCompleted),
s.MinResponseTime.Seconds(),
s.MaxResponseTime.Seconds())
if s.NumCompleted > 1 {
latencyStdDev := StdDev(s.TotalLatencySquare, s.TotalLatency.Seconds(), float64(s.NumCompleted))
fmt.Printf(" Latency StdDev (s): %.6f\n", latencyStdDev)
}
fmt.Printf("\n")
}
func (s *Stats) printRcodes() {
fmt.Printf(" Response codes: ")
firstRcode := true
for i := 0; i < 16; i++ {
if s.ResponseCodes[i] == 0 {
continue
}
if firstRcode {
firstRcode = false
} else {
fmt.Print(", ")
}
fmt.Printf("%s %d (%.2f%%)",
dns.RcodeToString[i],
s.ResponseCodes[i],
SafeDiv(s.ResponseCodes[i]*100, s.NumCompleted))
}
fmt.Printf("\n")
}
func SafeDiv(m, n int64) float64 {
if n == 0 {
return 0
}
return float64(m) / float64(n)
}
func StdDev(sumOfSquares, sum, total float64) float64 {
var (
squared float64
variance float64
)
squared = sum * sum
variance = (sumOfSquares - (squared / float64(total))) / (total - 1)
return math.Sqrt(variance)
}
func MaxDuration(d1, d2 time.Duration) time.Duration {
if d1 > d2 {
return d1
} else {
return d2
}
}
func MinDuration(d1, d2 time.Duration) time.Duration {
if d1 < d2 {
return d1
} else {
return d2
}
}
func MaxTime(t1, t2 time.Time) time.Time {
if t1.UnixNano() > t2.UnixNano() {
return t1
} else {
return t2
}
}
func MinTime(t1, t2 time.Time) time.Time {
if t1.UnixNano() < t2.UnixNano() {
return t1
} else {
return t2
}
}