-
Notifications
You must be signed in to change notification settings - Fork 17
/
stats.cc
159 lines (145 loc) · 4.59 KB
/
stats.cc
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
* SPDX-License-Identifier: BSD-3-Clause-Clear
*
* Copyright (c) 2015 ARM Limited
* All rights reserved
* Created on: Oct 8, 2015
* Author: Matteo Andreozzi
*/
#include "stats.hh"
#include "utilities.hh"
#include <sstream>
#include <algorithm>
namespace TrafficProfiles {
Stats::Stats():
started(false), startTime(numeric_limits<uint64_t>::max()),
timeScale(1), time(0),
sent(0), received(0), dataSent(0),
dataReceived(0), prevLatency(.0), jitter(.0),
latency(.0), underruns(0), overruns(0),
ot(0), otN(0), fifoLevel(0),
fifoLevelN(0) {
}
Stats::~Stats() {
}
void Stats::setTime(const uint64_t t){
// going backwards in time is prevented
if (t >= time) {
time = t;
}
}
void
Stats::send (const uint64_t t, const uint64_t data, const uint64_t o) {
// set start time if required
start(t);
// advance time if necessary
setTime(t);
// record event
sent++;
dataSent +=data;
// update the OT count
ot+=o;
// update OT sample count only when increasing it
otN++;
}
void
Stats::receive (const uint64_t t,const uint64_t data, const double l) {
// set start time if required
start(t);
// advance time if necessary
setTime(t);
// record event
received++;
dataReceived +=data;
/*
* Jitter is computer iteratively based on RFC 1889 January 1996
*
* https://datatracker.ietf.org/doc/rfc1889/?include_text=1
*
* On nth packet reception,
* the latency variation is added to the current jitter
* following the formula:
*
* J=J+(|D(n-1,n)|-J)/16
*
* This algorithm is the optimal first-order estimator
* and the gain parameter 1/16 gives a good noise
* reduction ratio while maintaining a
* reasonable rate of convergence
*/
jitter += ((fabs(l-prevLatency) - jitter)/16);
prevLatency = l;
latency += l;
}
void
Stats::fifoUpdate(const uint64_t l, const bool u, const bool o) {
fifoLevel += l;
fifoLevelN++;
if (u) underruns++;
if (o) overruns++;
}
const string
Stats::dump() const {
stringstream ss;
ss << "start time: " << Utilities::toTimeString((double)startTime/(double)timeScale)
<< " finish time: " << Utilities::toTimeString(getTime())
<< " sent: " << sent
<< " received: " << received
<< " data sent: " << Utilities::toByteString(dataSent)
<< " data received: " << Utilities::toByteString(dataReceived)
<< " avg response latency: " << Utilities::toTimeString(avgLatency())
<< " avg response jitter: " << Utilities::toTimeString(avgJitter())
<< " send rate:" << Utilities::toByteString(sendRate()) << "ps"
<< " receive rate: " << Utilities::toByteString(receiveRate()) << "ps"
<< " average OT: " << avgOt()
<< " average FIFO level: " << avgFifoLevel()
<< " FIFO underruns: " << underruns
<< " FIFO overruns: " << overruns;
return ss.str();
}
const StatObject*
Stats::xport() const {
StatObject* ret = new StatObject();
ret->set_start(getStartTime());
ret->set_time(getTime());
ret->set_sent(sent);
ret->set_received(received);
ret->set_datasent(dataSent);
ret->set_datareceived(dataReceived);
ret->set_latency(avgLatency());
ret->set_jitter(avgJitter());
ret->set_receiverate(receiveRate());
ret->set_sendrate(sendRate());
ret->set_underruns(underruns);
ret->set_overruns(overruns);
ret->set_ot(avgOt());
ret->set_fifolevel(avgFifoLevel());
return ret;
}
Stats Stats::operator+(const Stats& s) {
Stats ret;
// all stats objects should have the same time scale factor
assert(this->timeScale == s.timeScale);
ret.started = (s.started | this->started);
ret.startTime = min(this->startTime, s.startTime);
ret.timeScale = this->timeScale;
ret.time = max(this->time, s.time);
ret.sent = this->sent + s.sent;
ret.received = this->received + s.received;
ret.dataSent = this->dataSent + s.dataSent;
ret.dataReceived = this->dataReceived + s.dataReceived;
ret.latency = this->latency + s.latency;
ret.jitter = this->jitter + s.jitter;
ret.underruns = this->underruns + s.underruns;
ret.overruns = this->overruns + s.overruns;
ret.ot = this->ot + s.ot;
ret.otN = this->otN + s.otN;
ret.fifoLevel = this->fifoLevel + s.fifoLevel;
ret.fifoLevelN = this->fifoLevelN + s.fifoLevelN;
return ret;
}
Stats& Stats::operator+=(const Stats& s) {
*this = *this + s;
return *this;
}
} /* namespace TrafficProfiles */