fix: 压测客户端改为 MQTT 5 并完成 hello 与收发统计
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package load
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Percentiles 是毫秒延迟分位。
|
||||
type Percentiles struct {
|
||||
P50 float64
|
||||
P95 float64
|
||||
P99 float64
|
||||
N int
|
||||
}
|
||||
|
||||
func calcPercentiles(ms []float64) Percentiles {
|
||||
out := Percentiles{N: len(ms)}
|
||||
if len(ms) == 0 {
|
||||
return out
|
||||
}
|
||||
cp := append([]float64(nil), ms...)
|
||||
sort.Float64s(cp)
|
||||
out.P50 = percentileAt(cp, 0.50)
|
||||
out.P95 = percentileAt(cp, 0.95)
|
||||
out.P99 = percentileAt(cp, 0.99)
|
||||
return out
|
||||
}
|
||||
|
||||
func percentileAt(sorted []float64, p float64) float64 {
|
||||
n := len(sorted)
|
||||
if n == 1 {
|
||||
return sorted[0]
|
||||
}
|
||||
idx := int(math.Ceil(p*float64(n))) - 1
|
||||
if idx < 0 {
|
||||
idx = 0
|
||||
}
|
||||
if idx >= n {
|
||||
idx = n - 1
|
||||
}
|
||||
return sorted[idx]
|
||||
}
|
||||
|
||||
// Report 是一次压测输出:提交/送达分位、错误码分布、掉线数。
|
||||
type Report struct {
|
||||
Connections int
|
||||
Alive int
|
||||
Disconnects int
|
||||
Sends int
|
||||
ActualRate float64
|
||||
SubmitMs Percentiles
|
||||
DeliverMs Percentiles
|
||||
Errors map[string]int
|
||||
GroupMembers int
|
||||
GroupQueueMs float64
|
||||
}
|
||||
|
||||
func (r Report) Format() string {
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "connections: %d alive: %d disconnects: %d\n", r.Connections, r.Alive, r.Disconnects)
|
||||
fmt.Fprintf(&b, "sends: %d", r.Sends)
|
||||
if r.ActualRate > 0 {
|
||||
fmt.Fprintf(&b, " actual_rate: %.2f/s", r.ActualRate)
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
fmt.Fprintf(&b, "submit_ms: n=%d p50=%.1f p95=%.1f p99=%.1f\n", r.SubmitMs.N, r.SubmitMs.P50, r.SubmitMs.P95, r.SubmitMs.P99)
|
||||
fmt.Fprintf(&b, "deliver_ms: n=%d p50=%.1f p95=%.1f p99=%.1f\n", r.DeliverMs.N, r.DeliverMs.P50, r.DeliverMs.P95, r.DeliverMs.P99)
|
||||
if r.GroupMembers > 0 {
|
||||
fmt.Fprintf(&b, "group: members=%d queue_ms=%.1f\n", r.GroupMembers, r.GroupQueueMs)
|
||||
}
|
||||
if len(r.Errors) == 0 {
|
||||
b.WriteString("errors: (none)\n")
|
||||
} else {
|
||||
b.WriteString("errors:")
|
||||
keys := make([]string, 0, len(r.Errors))
|
||||
for k := range r.Errors {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
fmt.Fprintf(&b, " %s=%d", k, r.Errors[k])
|
||||
}
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func addError(m map[string]int, code string) {
|
||||
if code == "" {
|
||||
code = "error"
|
||||
}
|
||||
m[code]++
|
||||
}
|
||||
Reference in New Issue
Block a user