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
|
/*
* This file is part of Go Responsiveness.
*
* Go Responsiveness is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software Foundation,
* either version 2 of the License, or (at your option) any later version.
* Go Responsiveness is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with Go Responsiveness. If not, see <https://www.gnu.org/licenses/>.
*/
package rpm
import (
"fmt"
"github.com/network-quality/goresponsiveness/series"
"github.com/network-quality/goresponsiveness/utilities"
)
type Rpm[Data utilities.Number] struct {
SelfRttsTotal int
ForeignRttsTotal int
SelfRttsTrimmed int
ForeignRttsTrimmed int
SelfProbeRttPN Data
ForeignProbeRttPN Data
SelfProbeRttMean float64
ForeignProbeRttMean float64
PNRpm float64
MeanRpm float64
}
func CalculateRpm[Data utilities.Number, Bucket utilities.Number](
selfRtts series.WindowSeries[Data, Bucket], aggregatedForeignRtts series.WindowSeries[Data, Bucket], trimming uint, percentile uint,
) *Rpm[Data] {
// There may be more than one round trip accumulated together. If that is the case,
// we will blow them apart in to three separate measurements and each one will just
// be 1 / 3.
foreignRtts := series.NewWindowSeries[Data, int](series.Forever, 0)
foreignBuckets := 0
for _, v := range aggregatedForeignRtts.GetValues() {
if utilities.IsSome(v) {
v := utilities.GetSome(v)
foreignRtts.Reserve(foreignBuckets)
foreignRtts.Reserve(foreignBuckets + 1)
foreignRtts.Reserve(foreignBuckets + 2)
foreignRtts.Fill(foreignBuckets, v/3)
foreignRtts.Fill(foreignBuckets+1, v/3)
foreignRtts.Fill(foreignBuckets+2, v/3)
foreignBuckets += 3
}
}
boundedSelfRtts := selfRtts.ExtractBoundedSeries()
// First, let's do a double-sided trim of the top/bottom 10% of our measurements.
selfRttsTotalCount, _ := boundedSelfRtts.Count()
foreignRttsTotalCount, _ := foreignRtts.Count()
_, selfProbeRoundTripTimeMean, selfRttsTrimmed :=
series.TrimmedMean(boundedSelfRtts, int(trimming))
_, foreignProbeRoundTripTimeMean, foreignRttsTrimmed :=
series.TrimmedMean(foreignRtts, int(trimming))
selfRttsTrimmedCount := len(selfRttsTrimmed)
foreignRttsTrimmedCount := len(foreignRttsTrimmed)
// Second, let's do the P90 calculations.
_, selfProbeRoundTripTimePN := series.Percentile(boundedSelfRtts, percentile)
_, foreignProbeRoundTripTimePN := series.Percentile(foreignRtts, percentile)
// Note: The specification indicates that we want to calculate the foreign probes as such:
// 1/3*tcp_foreign + 1/3*tls_foreign + 1/3*http_foreign
// where tcp_foreign, tls_foreign, http_foreign are the P90 RTTs for the connection
// of the tcp, tls and http connections, respectively. However, we cannot break out
// the individual RTTs so we assume that they are roughly equal.
// This is 60 because we measure in seconds not ms
pnRpm := 60.0 / (float64(selfProbeRoundTripTimePN+foreignProbeRoundTripTimePN) / 2.0)
meanRpm := 60.0 / (float64(selfProbeRoundTripTimeMean+foreignProbeRoundTripTimeMean) / 2.0)
return &Rpm[Data]{
SelfRttsTotal: selfRttsTotalCount, ForeignRttsTotal: foreignRttsTotalCount,
SelfRttsTrimmed: selfRttsTrimmedCount, ForeignRttsTrimmed: foreignRttsTrimmedCount,
SelfProbeRttPN: selfProbeRoundTripTimePN, ForeignProbeRttPN: foreignProbeRoundTripTimePN,
SelfProbeRttMean: selfProbeRoundTripTimeMean, ForeignProbeRttMean: foreignProbeRoundTripTimeMean,
PNRpm: pnRpm, MeanRpm: meanRpm,
}
}
func (rpm *Rpm[Data]) ToString() string {
return fmt.Sprintf(
`Total Self Probes: %d
Total Foreign Probes: %d
Trimmed Self Probes Count: %d
Trimmed Foreign Probes Count: %d
P90 Self RTT: %v
P90 Foreign RTT: %v
Trimmed Mean Self RTT: %f
Trimmed Mean Foreign RTT: %f
`,
rpm.SelfRttsTotal,
rpm.ForeignRttsTotal,
rpm.SelfRttsTrimmed,
rpm.ForeignRttsTrimmed,
rpm.SelfProbeRttPN,
rpm.ForeignProbeRttPN,
rpm.SelfProbeRttMean,
rpm.ForeignProbeRttMean,
)
}
|