//////////////////////////////////////////////////////////////////////////////// /// @brief utilities for round robin figures /// /// @file /// /// DISCLAIMER /// /// Copyright 2004-2012 triagens GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is triAGENS GmbH, Cologne, Germany /// /// @author Dr. Frank Celler /// @author Copyright 2010-2012, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// #ifndef TRIAGENS_BASICS_ROUND_ROBIN_FIGURES_H #define TRIAGENS_BASICS_ROUND_ROBIN_FIGURES_H 1 #include "Basics/Common.h" #include #include "Basics/Mutex.h" #include "Basics/MutexLocker.h" // ----------------------------------------------------------------------------- // --SECTION-- public macros // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @addtogroup Utilities /// @{ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @brief macro to define a new counter //////////////////////////////////////////////////////////////////////////////// #define RRF_COUNTER(S, n) \ struct n ## Accessor { \ static triagens::basics::RrfCounter& access (S& s) { \ return s.n; \ } \ }; \ \ triagens::basics::RrfCounter n //////////////////////////////////////////////////////////////////////////////// /// @brief macro to define a new continuous //////////////////////////////////////////////////////////////////////////////// #define RRF_CONTINUOUS(S, n) \ struct n ## Accessor { \ static triagens::basics::RrfContinuous& access (S& s) { \ return s.n; \ } \ }; \ \ triagens::basics::RrfContinuous n //////////////////////////////////////////////////////////////////////////////// /// @brief macro to define a new figure /// /// The figures contains the sum of the values and the count. //////////////////////////////////////////////////////////////////////////////// #define RRF_FIGURE(S, n) \ struct n ## Accessor { \ static triagens::basics::RrfFigure& access (S& s) { \ return s.n; \ } \ }; \ \ triagens::basics::RrfFigure n //////////////////////////////////////////////////////////////////////////////// /// @brief macro to define a new set of figures /// /// The figures contains the sum of the values and the count. //////////////////////////////////////////////////////////////////////////////// #define RRF_FIGURES(S, N, n) \ struct n ## Accessor { \ static triagens::basics::RrfFigures& access (S& s) { \ return s.n; \ } \ }; \ \ triagens::basics::RrfFigures n //////////////////////////////////////////////////////////////////////////////// /// @brief macro to define a new distribution /// /// The distributions contains the sum of the values, the sum of the /// squares, the count, and minimum and maximum. //////////////////////////////////////////////////////////////////////////////// #define RRF_DISTRIBUTION(S, n, a) \ struct n ## Cuts_s { \ static vector cuts () { \ triagens::basics::RrfVector g; g << a; return g._value; \ } \ }; \ \ struct n ## Accessor { \ static triagens::basics::RrfDistribution& access (S& s) { \ return s.n; \ } \ }; \ \ triagens::basics::RrfDistribution n //////////////////////////////////////////////////////////////////////////////// /// @brief macro to define a new set of distributions /// /// The distributions contains the sum of the values, the sum of the /// squares, the count, and minimum and maximum. //////////////////////////////////////////////////////////////////////////////// #define RRF_DISTRIBUTIONS(S, N, n, a) \ struct n ## Cuts_s { \ static vector cuts () { \ triagens::basics::RrfVector g; g << a; return g._value; \ } \ }; \ \ struct n ## Accessor { \ static triagens::basics::RrfDistributions& access (S& s) { \ return s.n; \ } \ }; \ \ triagens::basics::RrfDistributions n //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// namespace triagens { namespace basics { // ----------------------------------------------------------------------------- // --SECTION-- public types // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @addtogroup Utilities /// @{ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @brief vector generator //////////////////////////////////////////////////////////////////////////////// struct RrfVector { RrfVector () : _value() { } RrfVector& operator<< (double v) { _value.push_back(v); return *this; } vector _value; }; //////////////////////////////////////////////////////////////////////////////// /// @brief a simple counter //////////////////////////////////////////////////////////////////////////////// struct RrfCounter { RrfCounter() : _count(0) { } RrfCounter& operator= (RrfCounter const&) { _count = 0; return *this; } int32_t _count; }; //////////////////////////////////////////////////////////////////////////////// /// @brief a simple continuous counter //////////////////////////////////////////////////////////////////////////////// struct RrfContinuous { RrfContinuous() : _count(0) { } RrfContinuous& operator= (RrfContinuous const& that) { if (this == &that) { _count = 0; } else { _count = that._count; } return *this; } int32_t _count; }; //////////////////////////////////////////////////////////////////////////////// /// @brief a figure with count //////////////////////////////////////////////////////////////////////////////// struct RrfFigure { RrfFigure() : _count(0), _sum(0.0) { } RrfFigure& operator= (RrfFigure const&) { _count = 0; _sum = 0.0; return *this; } int32_t _count; double _sum; }; //////////////////////////////////////////////////////////////////////////////// /// @brief a figure with count //////////////////////////////////////////////////////////////////////////////// template struct RrfFigures { RrfFigures() { for (size_t i = 0; i < N; ++i) { _count[i] = 0; _sum[i] = 0.0; } } RrfFigures& operator= (RrfFigures const&) { for (size_t i = 0; i < N; ++i) { _count[i] = 0; _sum[i] = 0.0; } return *this; } uint32_t _count[N]; double _sum[N]; }; //////////////////////////////////////////////////////////////////////////////// /// @brief a distribution with count, min, max, mean, and variance //////////////////////////////////////////////////////////////////////////////// template struct RrfDistribution { RrfDistribution() : _count(0), _sum(0.0), _squares(0.0), _minimum(HUGE_VAL), _maximum(-HUGE_VAL), _cuts(C::cuts()), _counts() { _counts.resize(_cuts.size() + 1); } RrfDistribution& operator= (RrfDistribution const&) { _count = 0; _sum = 0.0; _squares = 0.0; _minimum = HUGE_VAL; _maximum = -HUGE_VAL; return *this; } uint32_t _count; double _sum; double _squares; double _minimum; double _maximum; vector _cuts; vector _counts; }; //////////////////////////////////////////////////////////////////////////////// /// @brief many distributions with count, min, max, mean, and variance //////////////////////////////////////////////////////////////////////////////// template struct RrfDistributions { RrfDistributions() : _cuts(C::cuts()) { for (size_t i = 0; i < N; ++i) { _counts[i].resize(_cuts.size() + 1); _sum[i] = 0.0; _squares[i] = 0.0; _minimum[i] = HUGE_VAL; _maximum[i] = -HUGE_VAL; } } RrfDistributions& operator= (RrfDistributions const&) { for (size_t i = 0; i < N; ++i) { _sum[i] = 0.0; _squares[i] = 0.0; _minimum[i] = HUGE_VAL; _maximum[i] = -HUGE_VAL; } return *this; } uint32_t _count[N]; double _sum[N]; double _squares[N]; double _minimum[N]; double _maximum[N]; vector _cuts; vector _counts[N]; }; //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- class RoundRobinFigures // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @addtogroup Utilities /// @{ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @brief utilities for round robin distributions //////////////////////////////////////////////////////////////////////////////// template class RoundRobinFigures { public: //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- constructors and destructors // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @addtogroup Utilities /// @{ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @brief constructor //////////////////////////////////////////////////////////////////////////////// #ifdef TRI_ENABLE_FIGURES RoundRobinFigures () : _current(0), _accessLock() { for (size_t i = 0; i < N; ++i) { _buffer[i] = S(); _start[i] = 0; } time_t now = time(0); _current = (now / P) % N; _start[_current] = (now / P) * P; } #else RoundRobinFigures () { } #endif //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- public methods // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @addtogroup Utilities /// @{ //////////////////////////////////////////////////////////////////////////////// public: //////////////////////////////////////////////////////////////////////////////// /// @brief increments a counter //////////////////////////////////////////////////////////////////////////////// template void incCounter () { #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); S& s = _buffer[_current]; C::access(s)._count += 1; #endif } //////////////////////////////////////////////////////////////////////////////// /// @brief decrements a counter //////////////////////////////////////////////////////////////////////////////// template void decCounter () { #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); S& s = _buffer[_current]; C::access(s)._count -= 1; #endif } //////////////////////////////////////////////////////////////////////////////// /// @brief generate a new figure //////////////////////////////////////////////////////////////////////////////// template void addFigure (double value) { #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); S& s = _buffer[_current]; F::access(s)._count += 1; F::access(s)._sum += value; #endif } //////////////////////////////////////////////////////////////////////////////// /// @brief generate a new figure //////////////////////////////////////////////////////////////////////////////// template void addFigure (size_t pos, double value) { #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); S& s = _buffer[_current]; F::access(s)._count[pos] += 1; F::access(s)._sum[pos] += value; #endif } //////////////////////////////////////////////////////////////////////////////// /// @brief generate a new distribution //////////////////////////////////////////////////////////////////////////////// template void addDistribution (double value) { #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); S& s = _buffer[_current]; F::access(s)._count += 1; F::access(s)._sum += value; F::access(s)._squares += double(value * value); if (F::access(s)._minimum > value) { F::access(s)._minimum = value; } if (F::access(s)._maximum < value) { F::access(s)._maximum = value; } typename vector::const_iterator i = F::access(s)._cuts.begin(); vector::iterator j = F::access(s)._counts.begin(); for(; i != F::access(s)._cuts.end(); ++i, ++j) { if (value < *i) { (*j)++; return; } } (*j)++; #endif } //////////////////////////////////////////////////////////////////////////////// /// @brief generate a new distribution //////////////////////////////////////////////////////////////////////////////// template void addDistribution (size_t pos, double value) { #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); S& s = _buffer[_current]; F::access(s)._count[pos] += 1; F::access(s)._sum[pos] += value; F::access(s)._squares[pos] += double(value * value); if (F::access(s)._minimum[pos] > value) { F::access(s)._minimum[pos] = value; } if (F::access(s)._maximum[pos] < value) { F::access(s)._maximum[pos] = value; } typename vector::const_iterator i = F::access(s)._cuts.begin(); vector::iterator j = F::access(s)._counts[pos].begin(); for(; i != F::access(s)._cuts.end(); ++i, ++j) { if (value < *i) { (*j)++; return; } } (*j)++; #endif } //////////////////////////////////////////////////////////////////////////////// /// @brief returns the list of distributions //////////////////////////////////////////////////////////////////////////////// vector values (size_t n = N) { vector result; #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); if (n >= N) { n = N; } size_t j = (_current + N - n + 1) % N; for (size_t i = 0; i < n; ++i) { result.push_back(_buffer[j]); j = (j + 1) % N; } #endif return result; } //////////////////////////////////////////////////////////////////////////////// /// @brief returns the list of distributions and times //////////////////////////////////////////////////////////////////////////////// vector values (vector& times, size_t n = N) { vector result; #ifdef TRI_ENABLE_FIGURES MUTEX_LOCKER(_accessLock); checkTime(); if (n >= N) { n = N; } times.clear(); size_t j = (_current + N - n + 1) % N; for (size_t i = 0; i < n; ++i) { result.push_back(_buffer[j]); times.push_back(_start[j]); j = (j + 1) % N; } #endif return result; } protected: //////////////////////////////////////////////////////////////////////////////// /// @brief checks if we have to use a new time intervall //////////////////////////////////////////////////////////////////////////////// void checkTime () { #ifdef TRI_ENABLE_FIGURES time_t now = time(0); size_t p1 = now / P; size_t p2 = _start[_current] / P; if (p1 == p2) { return; } S save = _buffer[_current]; for (size_t p = max(p2, p1 - N) + 1; p <= p1; ++p) { _current = p % N; _buffer[_current] = save; _start[_current] = p * P; } #endif } //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @addtogroup Utilities /// @{ //////////////////////////////////////////////////////////////////////////////// private: //////////////////////////////////////////////////////////////////////////////// /// @brief staticstics ring-buffer //////////////////////////////////////////////////////////////////////////////// #ifdef TRI_ENABLE_FIGURES S _buffer[N]; #endif //////////////////////////////////////////////////////////////////////////////// /// @brief time buffer //////////////////////////////////////////////////////////////////////////////// #ifdef TRI_ENABLE_FIGURES time_t _start[N]; #endif //////////////////////////////////////////////////////////////////////////////// /// @brief current position //////////////////////////////////////////////////////////////////////////////// #ifdef TRI_ENABLE_FIGURES size_t _current; #endif //////////////////////////////////////////////////////////////////////////////// /// @brief access lock //////////////////////////////////////////////////////////////////////////////// #ifdef TRI_ENABLE_FIGURES Mutex _accessLock; #endif }; } } //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// #endif // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" // End: