1 #include "artdaq-core/Core/MonitoredQuantity.hh"
6 using namespace artdaq;
8 MonitoredQuantity::MonitoredQuantity
10 DURATION_T expectedCalculationInterval,
11 DURATION_T timeWindowForRecentResults
14 _expectedCalculationInterval(expectedCalculationInterval)
16 setNewTimeWindowForRecentResults(timeWindowForRecentResults);
19 void MonitoredQuantity::addSample(
const double value)
21 if (! _enabled) {
return;}
22 boost::mutex::scoped_lock sl(_accumulationMutex);
23 if (_lastCalculationTime <= 0.0) {
24 _lastCalculationTime = getCurrentTime();
26 ++_workingSampleCount;
27 _workingValueSum += value;
28 _workingValueSumOfSquares += (value * value);
29 if (value < _workingValueMin) { _workingValueMin = value; }
30 if (value > _workingValueMax) { _workingValueMax = value; }
31 _workingLastSampleValue = value;
34 void MonitoredQuantity::addSample(
const int value)
36 addSample(static_cast<double>(value));
39 void MonitoredQuantity::addSample(
const uint32_t value)
41 addSample(static_cast<double>(value));
44 void MonitoredQuantity::addSample(
const uint64_t value)
46 addSample(static_cast<double>(value));
49 bool MonitoredQuantity::calculateStatistics(TIME_POINT_T currentTime)
51 if (! _enabled) {
return false;}
52 if (_lastCalculationTime <= 0.0) {
return false;}
53 if (currentTime - _lastCalculationTime < _expectedCalculationInterval) {
59 long long latestSampleCount;
60 double latestValueSum;
61 double latestValueSumOfSquares;
62 double latestValueMin;
63 double latestValueMax;
64 DURATION_T latestDuration;
65 double latestLastLatchedSampleValue;
67 boost::mutex::scoped_lock sl(_accumulationMutex);
68 latestSampleCount = _workingSampleCount;
69 latestValueSum = _workingValueSum;
70 latestValueSumOfSquares = _workingValueSumOfSquares;
71 latestValueMin = _workingValueMin;
72 latestValueMax = _workingValueMax;
73 latestDuration = currentTime - _lastCalculationTime;
74 latestLastLatchedSampleValue = _workingLastSampleValue;
75 _lastCalculationTime = currentTime;
76 _workingSampleCount = 0;
77 _workingValueSum = 0.0;
78 _workingValueSumOfSquares = 0.0;
79 _workingValueMin = INFINITY;
80 _workingValueMax = -INFINITY;
84 boost::mutex::scoped_lock sl(_resultsMutex);
85 _lastLatchedSampleValue = latestLastLatchedSampleValue;
86 _lastLatchedCalculationTime = _lastCalculationTime;
88 _fullSampleCount += latestSampleCount;
89 _fullValueSum += latestValueSum;
90 _fullValueSumOfSquares += latestValueSumOfSquares;
91 if (latestValueMin < _fullValueMin) {_fullValueMin = latestValueMin;}
92 if (latestValueMax > _fullValueMax) {_fullValueMax = latestValueMax;}
93 _fullDuration += latestDuration;
96 _binSampleCount[_workingBinId] = latestSampleCount;
97 _binValueSum[_workingBinId] = latestValueSum;
98 _binValueSumOfSquares[_workingBinId] = latestValueSumOfSquares;
99 _binValueMin[_workingBinId] = latestValueMin;
100 _binValueMax[_workingBinId] = latestValueMax;
101 _binDuration[_workingBinId] = latestDuration;
102 _binEndTime[_workingBinId] = _lastCalculationTime;
103 if (latestDuration > 0.0) {
104 _lastLatchedValueRate = latestValueSum / latestDuration;
107 _lastLatchedValueRate = 0.0;
109 _recentSampleCount = 0;
110 _recentValueSum = 0.0;
111 _recentValueSumOfSquares = 0.0;
112 _recentValueMin = INFINITY;
113 _recentValueMax = -INFINITY;
114 _recentDuration = 0.0;
115 for (
unsigned int idx = 0; idx < _binCount; ++idx) {
116 _recentSampleCount += _binSampleCount[idx];
117 _recentValueSum += _binValueSum[idx];
118 _recentValueSumOfSquares += _binValueSumOfSquares[idx];
119 if (_binValueMin[idx] < _recentValueMin) {
120 _recentValueMin = _binValueMin[idx];
122 if (_binValueMax[idx] > _recentValueMax) {
123 _recentValueMax = _binValueMax[idx];
125 _recentDuration += _binDuration[idx];
130 if (_workingBinId >= _binCount) {_workingBinId = 0;}
132 if (_fullDuration > 0.0) {
133 _fullSampleRate =
static_cast<double>(_fullSampleCount) / _fullDuration;
134 _fullValueRate =
static_cast<double>(_fullValueSum) / _fullDuration;
137 _fullSampleRate = 0.0;
138 _fullValueRate = 0.0;
140 if (_fullSampleCount > 0) {
141 _fullValueAverage = _fullValueSum /
static_cast<double>(_fullSampleCount);
142 double squareAvg = _fullValueSumOfSquares /
static_cast<double>(_fullSampleCount);
143 double avg = _fullValueSum /
static_cast<double>(_fullSampleCount);
144 double sigSquared = squareAvg - avg * avg;
145 if (sigSquared > 0.0) {
146 _fullValueRMS = sqrt(sigSquared);
153 _fullValueAverage = 0.0;
157 if (_recentDuration > 0.0) {
158 _recentSampleRate =
static_cast<double>(_recentSampleCount) / _recentDuration;
159 _recentValueRate =
static_cast<double>(_recentValueSum) / _recentDuration;
162 _recentSampleRate = 0.0;
163 _recentValueRate = 0.0;
165 if (_recentSampleCount > 0) {
166 _recentValueAverage = _recentValueSum /
static_cast<double>(_recentSampleCount);
167 double squareAvg = _recentValueSumOfSquares /
168 static_cast<double>(_recentSampleCount);
169 double avg = _recentValueSum /
static_cast<double>(_recentSampleCount);
170 double sigSquared = squareAvg - avg * avg;
171 if (sigSquared > 0.0) {
172 _recentValueRMS = sqrt(sigSquared);
175 _recentValueRMS = 0.0;
179 _recentValueAverage = 0.0;
180 _recentValueRMS = 0.0;
186 void MonitoredQuantity::_reset_accumulators()
188 _lastCalculationTime = 0;
189 _workingSampleCount = 0;
190 _workingValueSum = 0.0;
191 _workingValueSumOfSquares = 0.0;
192 _workingValueMin = INFINITY;
193 _workingValueMax = -INFINITY;
194 _workingLastSampleValue = 0;
197 void MonitoredQuantity::_reset_results()
200 for (
unsigned int idx = 0; idx < _binCount; ++idx) {
201 _binSampleCount[idx] = 0;
202 _binValueSum[idx] = 0.0;
203 _binValueSumOfSquares[idx] = 0.0;
204 _binValueMin[idx] = INFINITY;
205 _binValueMax[idx] = -INFINITY;
206 _binDuration[idx] = 0.0;
207 _binEndTime[idx] = 0.0;
209 _fullSampleCount = 0;
210 _fullSampleRate = 0.0;
212 _fullValueSumOfSquares = 0.0;
213 _fullValueAverage = 0.0;
215 _fullValueMin = INFINITY;
216 _fullValueMax = -INFINITY;
217 _fullValueRate = 0.0;
219 _recentSampleCount = 0;
220 _recentSampleRate = 0.0;
221 _recentValueSum = 0.0;
222 _recentValueSumOfSquares = 0.0;
223 _recentValueAverage = 0.0;
224 _recentValueRMS = 0.0;
225 _recentValueMin = INFINITY;
226 _recentValueMax = -INFINITY;
227 _recentValueRate = 0.0;
228 _recentDuration = 0.0;
229 _lastLatchedSampleValue = 0.0;
230 _lastLatchedValueRate = 0.0;
233 void MonitoredQuantity::reset()
236 boost::mutex::scoped_lock sl(_accumulationMutex);
237 _reset_accumulators();
240 boost::mutex::scoped_lock sl(_resultsMutex);
245 void MonitoredQuantity::enable()
253 void MonitoredQuantity::disable()
260 void MonitoredQuantity::setNewTimeWindowForRecentResults(DURATION_T interval)
265 boost::mutex::scoped_lock sl(_resultsMutex);
266 _intervalForRecentStats = interval;
272 _binCount = std::max(1U,
273 static_cast<unsigned int>(
274 (_intervalForRecentStats / _expectedCalculationInterval) + 0.5
278 _binSampleCount.reserve(_binCount);
279 _binValueSum.reserve(_binCount);
280 _binValueSumOfSquares.reserve(_binCount);
281 _binValueMin.reserve(_binCount);
282 _binValueMax.reserve(_binCount);
283 _binDuration.reserve(_binCount);
284 _binEndTime.reserve(_binCount);
288 boost::mutex::scoped_lock sl(_accumulationMutex);
289 _reset_accumulators();
296 bool MonitoredQuantity::
297 waitUntilAccumulatorsHaveBeenFlushed(DURATION_T timeout)
const
300 boost::mutex::scoped_lock sl(_accumulationMutex);
301 if (_workingSampleCount == 0) {
return true;}
303 long sleepTime =
static_cast<long>(timeout * 100000.0);
304 for (
int idx = 0; idx < 10; ++idx) {
307 boost::mutex::scoped_lock sl(_accumulationMutex);
308 if (_workingSampleCount == 0) {
return true;}
315 MonitoredQuantity::getStats(
Stats & s)
const
317 boost::mutex::scoped_lock results(_resultsMutex);
318 s.fullSampleCount = _fullSampleCount;
319 s.fullSampleRate = _fullSampleRate;
320 s.fullValueSum = _fullValueSum;
321 s.fullValueSumOfSquares = _fullValueSumOfSquares;
322 s.fullValueAverage = _fullValueAverage;
323 s.fullValueRMS = _fullValueRMS;
324 s.fullValueMin = _fullValueMin;
325 s.fullValueMax = _fullValueMax;
326 s.fullValueRate = _fullValueRate;
327 s.fullDuration = _fullDuration;
328 s.recentSampleCount = _recentSampleCount;
329 s.recentSampleRate = _recentSampleRate;
330 s.recentValueSum = _recentValueSum;
331 s.recentValueSumOfSquares = _recentValueSumOfSquares;
332 s.recentValueAverage = _recentValueAverage;
333 s.recentValueRMS = _recentValueRMS;
334 s.recentValueMin = _recentValueMin;
335 s.recentValueMax = _recentValueMax;
336 s.recentValueRate = _recentValueRate;
337 s.recentDuration = _recentDuration;
338 s.recentBinnedSampleCounts.resize(_binCount);
339 s.recentBinnedValueSums.resize(_binCount);
340 s.recentBinnedDurations.resize(_binCount);
341 s.recentBinnedEndTimes.resize(_binCount);
342 unsigned int sourceBinId = _workingBinId;
343 for (
unsigned int idx = 0; idx < _binCount; ++idx) {
344 if (sourceBinId >= _binCount) {sourceBinId = 0;}
345 s.recentBinnedSampleCounts[idx] = _binSampleCount[sourceBinId];
346 s.recentBinnedValueSums[idx] = _binValueSum[sourceBinId];
347 s.recentBinnedDurations[idx] = _binDuration[sourceBinId];
348 s.recentBinnedEndTimes[idx] = _binEndTime[sourceBinId];
351 s.lastSampleValue = _lastLatchedSampleValue;
352 s.lastValueRate = _lastLatchedValueRate;
353 s.lastCalculationTime = _lastLatchedCalculationTime;
354 s.enabled = _enabled;
357 MonitoredQuantity::TIME_POINT_T MonitoredQuantity::getCurrentTime()
359 TIME_POINT_T result = -1.0;
361 if (gettimeofday(&now, 0) == 0) {
362 result =
static_cast<TIME_POINT_T
>(now.tv_sec);
363 result +=
static_cast<TIME_POINT_T
>(now.tv_usec) / (1000 * 1000);
368 MonitoredQuantity::TIME_POINT_T MonitoredQuantity::lastCalculationTime()
const
370 boost::mutex::scoped_lock results(_resultsMutex);
371 return _lastLatchedCalculationTime;
374 MonitoredQuantity::DURATION_T MonitoredQuantity::fullDuration()
const
376 boost::mutex::scoped_lock results(_resultsMutex);
377 return _fullDuration;
380 double MonitoredQuantity::recentValueSum()
const
382 boost::mutex::scoped_lock results(_resultsMutex);
383 return _recentValueSum;
386 double MonitoredQuantity::recentValueAverage()
const
388 boost::mutex::scoped_lock results(_resultsMutex);
389 return _recentValueAverage;
392 long long MonitoredQuantity::fullSampleCount()
const
394 boost::mutex::scoped_lock results(_resultsMutex);
395 return _fullSampleCount;