From ff305e63b6ae7c20a3b423c5d7ca00816ff4db02 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 4 Oct 2013 10:56:19 -0700 Subject: [PATCH] Add CPUMeter and ScopedTimeInterval --- Builds/VisualStudio2012/beast.vcxproj | 5 +- Builds/VisualStudio2012/beast.vcxproj.filters | 15 +- beast/Chrono.h | 3 +- beast/chrono/CPUMeter.h | 159 ++++++++++++++++++ beast/chrono/Chrono.cpp | 2 +- .../{CPUUsage.h => ScopedTimeInterval.h} | 38 +++-- .../impl/{CPUUsage.cpp => CPUMeter.cpp} | 2 +- 7 files changed, 203 insertions(+), 21 deletions(-) create mode 100644 beast/chrono/CPUMeter.h rename beast/chrono/{CPUUsage.h => ScopedTimeInterval.h} (56%) rename beast/chrono/impl/{CPUUsage.cpp => CPUMeter.cpp} (97%) diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj index e4b8bfebf..657a854f9 100644 --- a/Builds/VisualStudio2012/beast.vcxproj +++ b/Builds/VisualStudio2012/beast.vcxproj @@ -84,8 +84,9 @@ - + + @@ -398,7 +399,7 @@ - + true true true diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters index cfc1e9cca..6d8a46ed8 100644 --- a/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Builds/VisualStudio2012/beast.vcxproj.filters @@ -1224,9 +1224,6 @@ beast_asio\http - - beast\chrono - beast\thread @@ -1236,6 +1233,12 @@ beast\thread + + beast\chrono + + + beast\chrono + @@ -1775,15 +1778,15 @@ beast_asio\http - - beast\chrono\impl - beast\thread\impl beast\thread + + beast\chrono\impl + diff --git a/beast/Chrono.h b/beast/Chrono.h index 728baa1f8..027b1f5f3 100644 --- a/beast/Chrono.h +++ b/beast/Chrono.h @@ -20,7 +20,8 @@ #ifndef BEAST_CHRONO_H_INCLUDED #define BEAST_CHRONO_H_INCLUDED -#include "chrono/CPUUsage.h" +#include "chrono/CPUMeter.h" #include "chrono/RelativeTime.h" +#include "chrono/ScopedTimeInterval.h" #endif diff --git a/beast/chrono/CPUMeter.h b/beast/chrono/CPUMeter.h new file mode 100644 index 000000000..8a02b591c --- /dev/null +++ b/beast/chrono/CPUMeter.h @@ -0,0 +1,159 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CHRONO_CPUMETER_H_INCLUDED +#define BEAST_CHRONO_CPUMETER_H_INCLUDED + +#include "RelativeTime.h" +#include "SCopedTimeInterval.h" +#include "../thread/SharedData.h" +#include "../Atomic.h" + +namespace beast { + +/** Measurements of CPU utilization. */ +class CPUMeter +{ +private: + struct MeasureIdle + { + explicit MeasureIdle (CPUMeter& meter) + : m_meter (&meter) + { } + void operator() (RelativeTime const& interval) const + { m_meter->addIdleTime (interval); } + CPUMeter* m_meter; + }; + + struct MeasureActive + { + explicit MeasureActive (CPUMeter& meter) + : m_meter (&meter) + { } + void operator() (RelativeTime const& interval) const + { m_meter->addActiveTime (interval); } + CPUMeter* m_meter; + }; + +public: + /** The type of container that measures idle time. */ + typedef ScopedTimeInterval ScopedIdleTime; + typedef ScopedTimeInterval ScopedActiveTime; + + /** Returns the fraction of time that the CPU is being used. */ + double getCpuUsage () const + { + SharedState::ConstAccess state (m_state); + double const seconds (state->usage.seconds()); + if (seconds > 0) + return (state->usage.active.inSeconds() / seconds); + return 0; + } + +private: + enum + { + // The amount of time an aggregate must accrue before a swap + secondsPerAggregate = 3 + + // The number of aggregates in the rolling history buffer + ,numberOfAggregates = 20 + }; + + // Aggregated sample data + struct Aggregate + { + RelativeTime idle; + RelativeTime active; + + // Returns the total number of seconds in the aggregate + double seconds () const + { return idle.inSeconds() + active.inSeconds(); } + + // Reset the accumulated times + void clear () + { idle = RelativeTime (0); active = RelativeTime (0); } + + Aggregate& operator+= (Aggregate const& other) + { idle += other.idle; active += other.active; return *this; } + + Aggregate& operator-= (Aggregate const& other) + { idle -= other.idle; active -= other.active; return *this; } + }; + + struct State + { + State () : index (0) + { + } + + // Returns a reference to the current aggregate + Aggregate& front () + { + return history [index]; + } + + // Checks the current aggregate to see if we should advance + void update() + { + if (front().seconds() >= secondsPerAggregate) + advance(); + } + + // Advance the index in the rolling history + void advance () + { + usage += history [index]; + index = (++index) % numberOfAggregates; + usage -= history [index]; + history [index].clear (); + } + + // Index of the current aggregate we are accumulating + int index; + + // Delta summed usage over the entire history buffer + Aggregate usage; + + // The rolling history buffer + Aggregate history [numberOfAggregates]; + }; + + typedef SharedData SharedState; + + SharedState m_state; + + void addIdleTime (RelativeTime const& interval) + { + SharedState::Access state (m_state); + state->front().idle += interval; + state->update(); + } + + void addActiveTime (RelativeTime const& interval) + { + SharedState::Access state (m_state); + state->front().active += interval; + state->update(); + } +}; + +} + +#endif diff --git a/beast/chrono/Chrono.cpp b/beast/chrono/Chrono.cpp index a3030761f..5ce5772e6 100644 --- a/beast/chrono/Chrono.cpp +++ b/beast/chrono/Chrono.cpp @@ -19,5 +19,5 @@ #include "BeastConfig.h" -#include "impl/CPUUsage.cpp" +#include "impl/CPUMeter.cpp" #include "impl/RelativeTime.cpp" diff --git a/beast/chrono/CPUUsage.h b/beast/chrono/ScopedTimeInterval.h similarity index 56% rename from beast/chrono/CPUUsage.h rename to beast/chrono/ScopedTimeInterval.h index 049c779ed..af3672870 100644 --- a/beast/chrono/CPUUsage.h +++ b/beast/chrono/ScopedTimeInterval.h @@ -17,27 +17,45 @@ */ //============================================================================== -#ifndef BEAST_CHRONO_CPUUSAGE_H_INCLUDED -#define BEAST_CHRONO_CPUUSAGE_H_INCLUDED +#ifndef BEAST_CHRONO_SCOPEDTIMEINTERVAL_H_INCLUDED +#define BEAST_CHRONO_SCOPEDTIMEINTERVAL_H_INCLUDED +#include "../Uncopyable.h" #include "RelativeTime.h" namespace beast { -/** Measurements of CPU utilization. */ - -#if 0 -/** Scoped lifetime measurement. */ -class ScopedTimeInterval +/** Time measurement using scoped RAII container. + UnaryFunction will be called with this signature: + void (RelativeTime const& interval); +*/ +template +class ScopedTimeInterval : public Uncopyable { public: - ScopedTimeInterval (); - ~ScopedTimeInterval (); + /** Create the measurement with a default-constructed UnaryFunction. */ + ScopedTimeInterval () + : m_start (RelativeTime::fromStartup()) + { + } + + /** Create the measurement with UnaryFunction constructed from one argument. */ + template + explicit ScopedTimeInterval (Arg arg) + : m_func (arg) + , m_start (RelativeTime::fromStartup ()) + { + } + + ~ScopedTimeInterval () + { + m_func (RelativeTime::fromStartup() - m_start); + } private: + UnaryFunction m_func; RelativeTime m_start; }; -#endif } diff --git a/beast/chrono/impl/CPUUsage.cpp b/beast/chrono/impl/CPUMeter.cpp similarity index 97% rename from beast/chrono/impl/CPUUsage.cpp rename to beast/chrono/impl/CPUMeter.cpp index a27bcd4e0..b5a67f4d1 100644 --- a/beast/chrono/impl/CPUUsage.cpp +++ b/beast/chrono/impl/CPUMeter.cpp @@ -17,5 +17,5 @@ */ //============================================================================== -#include "../CPUUsage.h" +#include "../CPUMeter.h"