summaryrefslogtreecommitdiff
path: root/rpm/calculations.go
diff options
context:
space:
mode:
Diffstat (limited to 'rpm/calculations.go')
-rw-r--r--rpm/calculations.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/rpm/calculations.go b/rpm/calculations.go
new file mode 100644
index 0000000..5387aa7
--- /dev/null
+++ b/rpm/calculations.go
@@ -0,0 +1,94 @@
+/*
+ * 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/ms"
+)
+
+type Rpm struct {
+ SelfRttsTotal int
+ ForeignRttsTotal int
+ SelfRttsTrimmed int
+ ForeignRttsTrimmed int
+ SelfProbeRttPN float64
+ ForeignProbeRttPN float64
+ SelfProbeRttMean float64
+ ForeignProbeRttMean float64
+ PNRpm float64
+ MeanRpm float64
+}
+
+func CalculateRpm(selfRtts ms.MathematicalSeries[float64], foreignRtts ms.MathematicalSeries[float64], trimming uint, percentile int) Rpm {
+ // First, let's do a double-sided trim of the top/bottom 10% of our measurements.
+ selfRttsTotalCount := selfRtts.Len()
+ foreignRttsTotalCount := foreignRtts.Len()
+
+ selfRttsTrimmed := selfRtts.DoubleSidedTrim(trimming)
+ foreignRttsTrimmed := foreignRtts.DoubleSidedTrim(trimming)
+
+ selfRttsTrimmedCount := selfRttsTrimmed.Len()
+ foreignRttsTrimmedCount := foreignRttsTrimmed.Len()
+
+ // Then, let's take the mean of those ...
+ selfProbeRoundTripTimeMean := selfRttsTrimmed.CalculateAverage()
+ foreignProbeRoundTripTimeMean := foreignRttsTrimmed.CalculateAverage()
+
+ // Second, let's do the P90 calculations.
+ selfProbeRoundTripTimePN := selfRtts.Percentile(percentile)
+ foreignProbeRoundTripTimePN := foreignRtts.Percentile(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{
+ SelfRttsTotal: selfRttsTotalCount, ForeignRttsTotal: foreignRttsTotalCount,
+ SelfRttsTrimmed: selfRttsTrimmedCount, ForeignRttsTrimmed: foreignRttsTrimmedCount,
+ SelfProbeRttPN: selfProbeRoundTripTimePN, ForeignProbeRttPN: foreignProbeRoundTripTimePN,
+ SelfProbeRttMean: selfProbeRoundTripTimeMean, ForeignProbeRttMean: foreignProbeRoundTripTimeMean,
+ PNRpm: pnRpm, MeanRpm: meanRpm,
+ }
+}
+
+func (rpm *Rpm) 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: %f
+P90 Foreign RTT: %f
+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,
+ )
+}