diff --git a/Framework/Analytics/ClassTimer.h b/Framework/Analytics/ClassTimer.h index 638a46dbac2173c2df79b8ff12d1d9e9de404cc3..5d99b37070393fc8cd8dfcaee42136e40ecba0f6 100644 --- a/Framework/Analytics/ClassTimer.h +++ b/Framework/Analytics/ClassTimer.h @@ -1,5 +1,5 @@ /* - * (c) Copyright 2019 CORSIKA Project, corsika-project@lists.kit.edu + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu * * This software is distributed under the terms of the GNU General Public * Licence version 3 (GPL Version 3). See file LICENSE for a full version of @@ -8,6 +8,9 @@ // Another possibility: // https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Execute-Around_Pointer +// for a more global approach +// +// In this case here only a single function is measured via member function pointer. #pragma once @@ -16,26 +19,47 @@ namespace corsika::analytics { - template <typename TType, TType> + /// Measure the runtime of a single class function + /** + * @tparam TClassFunc Type of the member function pointer that should be wrapped + * @tparam TFunc Actual function of the type defined in TClass + */ + template <typename TClassFunc, TClassFunc TFunc> class ClassTimer; - // Specialisation for normal member functions - template <typename TType, typename TRet, typename... TArgs, - TRet (TType::*TFuncPtr)(TArgs...)> - class ClassTimer<TRet (TType::*)(TArgs...), TFuncPtr> { + + /// Measure the runtime of a single class function + /** Specialisation to capture exact information about the composition of the member function pointer used. + * + * This class wrapes a single function and allowes the measureing of its runtime if it called via the "call(...)" function + * + * @tparam TClass Class of the function that should be wrapped + * @tparam TRet Return value of the wrapped function + * @tparam TArgs Arguments passed to the wrapped function + * @tparam TFuncPtr Actual function of the type defined by TRet TClass::TFuncPtr(TArgs...) + */ + template <typename TClass, typename TRet, typename... TArgs, + TRet (TClass::*TFuncPtr)(TArgs...)> + class ClassTimer<TRet (TClass::*)(TArgs...), TFuncPtr> { private: using TClock = std::chrono::high_resolution_clock; using TDuration = std::chrono::microseconds; - TType& vObj; + TClass& vObj; typename TClock::time_point vStart; TDuration vDiff; public: - ClassTimer(TType& obj) + ClassTimer(TClass& obj) : vObj(obj) {} + /// Executes the wrapped function + /** This function executes and measure the runtime of the wrapped function with the highest precision available (high_resolution_clock). + * + * @param args Arguments are perfect forwarded to the wrapped function. + * @return Returns the return value of the wrapped function. This value get copied during the process and therefore must be copie constructible! + */ TRet call(TArgs... args) { vStart = TClock::now(); auto tmp = (vObj.*TFuncPtr)(std::forward<TArgs>(args)...); @@ -43,23 +67,24 @@ namespace corsika::analytics { return tmp; } + /// returns the last runtime of the wraped function accessed via call inline TDuration getTime() const { return vDiff; } }; - // Specialisation for member functions without return value - template <typename TType, typename... TArgs, void (TType::*TFuncPtr)(TArgs...)> - class ClassTimer<void (TType::*)(TArgs...), TFuncPtr> { + /// Specialisation for member functions without return value + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...)> + class ClassTimer<void (TClass::*)(TArgs...), TFuncPtr> { private: using TClock = std::chrono::high_resolution_clock; using TDuration = std::chrono::microseconds; - TType& vObj; + TClass& vObj; typename TClock::time_point vStart; TDuration vDiff; public: - ClassTimer(TType& obj) + ClassTimer(TClass& obj) : vObj(obj) {} void call(TArgs... args) { @@ -72,22 +97,22 @@ namespace corsika::analytics { inline TDuration getTime() const { return vDiff; } }; - // Specialisation for const member functions - template <typename TType, typename TRet, typename... TArgs, - TRet (TType::*TFuncPtr)(TArgs...) const> - class ClassTimer<TRet (TType::*)(TArgs...) const, TFuncPtr> { + /// Specialisation for const member functions + template <typename TClass, typename TRet, typename... TArgs, + TRet (TClass::*TFuncPtr)(TArgs...) const> + class ClassTimer<TRet (TClass::*)(TArgs...) const, TFuncPtr> { private: using TClock = std::chrono::high_resolution_clock; using TDuration = std::chrono::microseconds; - const TType& vObj; + const TClass& vObj; typename TClock::time_point vStart; TDuration vDiff; public: - ClassTimer(TType& obj) + ClassTimer(TClass& obj) : vObj(obj) {} TRet call(TArgs... args) { @@ -100,21 +125,21 @@ namespace corsika::analytics { inline TDuration getTime() const { return vDiff; } }; - // Specialisation for const member functions without return value - template <typename TType, typename... TArgs, void (TType::*TFuncPtr)(TArgs...) const> - class ClassTimer<void (TType::*)(TArgs...) const, TFuncPtr> { + /// Specialisation for const member functions without return value + template <typename TClass, typename... TArgs, void (TClass::*TFuncPtr)(TArgs...) const> + class ClassTimer<void (TClass::*)(TArgs...) const, TFuncPtr> { private: using TClock = std::chrono::high_resolution_clock; using TDuration = std::chrono::microseconds; - const TType& obj_; + const TClass& obj_; typename TClock::time_point start_; TDuration timeDiff_; public: - ClassTimer(TType& obj) + ClassTimer(TClass& obj) : obj_(obj) {} void call(TArgs... args) { diff --git a/Framework/Analytics/FunctionTimer.h b/Framework/Analytics/FunctionTimer.h index 8488dd2de1e45173022cdeebc2cf847610c4daef..ce4585ff40bc644e35ff256bdc497e5925cc55af 100644 --- a/Framework/Analytics/FunctionTimer.h +++ b/Framework/Analytics/FunctionTimer.h @@ -1,14 +1,10 @@ /* - * (c) Copyright 2019 CORSIKA Project, corsika-project@lists.kit.edu + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu * * This software is distributed under the terms of the GNU General Public * Licence version 3 (GPL Version 3). See file LICENSE for a full version of * the license. */ - -// Another possibility: -// https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Execute-Around_Pointer - #pragma once #include <chrono> @@ -16,6 +12,13 @@ namespace corsika::analytics { + /// Wraps and measures the runtime of a single function type object + /** + * + * @tparam TFunc funtion pointer that should be wrapped + * @tparam TClock type of the clock that should be used for measurements + * @tparam TDuration type of std::duration to measure the elapsed time + */ template <typename TFunc, typename TClock = std::chrono::high_resolution_clock, typename TDuration = std::chrono::microseconds> class FunctionTimer { @@ -26,6 +29,8 @@ namespace corsika::analytics { TFunc function_; public: + + /// Constructs the wrapper with the given functionpointer FunctionTimer(TFunc f) : function_(f) {} diff --git a/Framework/ProcessSequence/BaseProcess.h b/Framework/ProcessSequence/BaseProcess.h index 193b6db287e74c41784dbfc0ea61545d38bd5120..d839305939729bb2ef822b6ebbdbf1046d7cfce7 100644 --- a/Framework/ProcessSequence/BaseProcess.h +++ b/Framework/ProcessSequence/BaseProcess.h @@ -37,6 +37,7 @@ namespace corsika::process { const TDerived& GetRef() const { return static_cast<const TDerived&>(*this); } public: + // Base processor type for use in other template classes using TProcessType = TDerived; }; diff --git a/Processes/AnalyticProcessors/ExecTime.h b/Processes/AnalyticProcessors/ExecTime.h index d8faaddfebc40a70b8c1d7ac7beb1b9e56e985c6..b03252918551cbb2790fee461d84e3b7de2e61bd 100644 --- a/Processes/AnalyticProcessors/ExecTime.h +++ b/Processes/AnalyticProcessors/ExecTime.h @@ -29,6 +29,15 @@ namespace corsika::process { namespace analytic_processors { + /// Time measurement of individual processes + /** This class allowes to log the runtime spend in all default calls to the process. + * No distinction is made between individual function calls of the process, the runtime is accumulated + * and or avaraged without differentiation. + * + * The class is currently only implemented for BoundaryProcess, ContinuousProcess, DecayProcess, InteractionProcess and SecondariesProcess and captures only the according functions of the base class given as template parameter. Trying to access BoundaryProcess functions with a DecayProcess as template parameter will currently give long errormessages. + * + * Inherits all functionality of the class that should be measured, this includes functions like getters and setters + */ template <typename T> class ExecTime : public Boundary<T, std::is_base_of<corsika::process::BoundaryCrossingProcess< diff --git a/Processes/AnalyticProcessors/ExecTimeImpl.h b/Processes/AnalyticProcessors/ExecTimeImpl.h index 11a11ebd901c8a1c22b2606a71cc69ba0dec8254..31596b08d89fb8fc7806826218fd56daad6bd5e9 100644 --- a/Processes/AnalyticProcessors/ExecTimeImpl.h +++ b/Processes/AnalyticProcessors/ExecTimeImpl.h @@ -31,8 +31,14 @@ namespace corsika::process { namespace detail { + /// Process type independent functionality of the Process runtime measurement class ExecTime + /** Inherits all functionality of the class that should be sampled, this includes special functions for getters and setters + * + * + * + */ template <typename T> - class ExecTimeImpl : protected T { + class ExecTimeImpl : public T { private: std::chrono::high_resolution_clock::time_point startTime_; std::chrono::duration<double, std::micro> cumulatedTime_; @@ -55,7 +61,10 @@ namespace corsika::process { n_ = 0; } + /// Starts the internal inline void start() { startTime_ = std::chrono::high_resolution_clock::now(); } + + /// Stops the internal timer and updates measurements inline void stop() { auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<double, std::micro> timeDiv = @@ -65,6 +74,7 @@ namespace corsika::process { this->update(timeDiv); } + /// Updates the floating mean and variance as well as the global min and max of the sampled runtimes void update(std::chrono::duration<double, std::micro> timeDif) { cumulatedTime_ += timeDif; diff --git a/Processes/AnalyticProcessors/ImplBoundary.h b/Processes/AnalyticProcessors/ImplBoundary.h index accdf0d44f91d23709f8f3574bcca8445a6d3e89..1c825e340994c3f7f293d2a785a9b825f93e2ea9 100644 --- a/Processes/AnalyticProcessors/ImplBoundary.h +++ b/Processes/AnalyticProcessors/ImplBoundary.h @@ -19,12 +19,15 @@ namespace corsika::process { class ExecTimeImpl; } + /// Base for Boundary Implementation template <class T, bool TCheck> class Boundary; + /// Specialisation if class is not BoundaryProcess template <class T> class Boundary<T, false> {}; + /// Specialisation if class is a BoundaryProcess template <class T> class Boundary<T, true> : public detail::ExecTimeImpl<T> { private: @@ -32,6 +35,8 @@ namespace corsika::process { template <typename Particle, typename VTNType> EProcessReturn DoBoundaryCrossing(Particle& p, VTNType const& from, VTNType const& to) { + + // Use of the ClassTimer function -> see ClassTimer for documentation auto tc = corsika::analytics::ClassTimer< EProcessReturn (detail::ExecTimeImpl<T>::_T::*)(Particle&, VTNType const&, VTNType const&), diff --git a/Processes/AnalyticProcessors/ImplContinuous.h b/Processes/AnalyticProcessors/ImplContinuous.h index 9ff63149189fe9c4ce1e3316a622f14158ce345f..06a0b9b8dbf8dd8375c46f807f2f7681b81dac2c 100644 --- a/Processes/AnalyticProcessors/ImplContinuous.h +++ b/Processes/AnalyticProcessors/ImplContinuous.h @@ -18,12 +18,15 @@ namespace corsika::process { class ExecTimeImpl; } + /// Base for Continuous Implementation template <class T, bool TCheck> class Continuous; + /// Specialisation if class is not ContinuousProcess template <class T> class Continuous<T, false> {}; + /// Specialisation if class is a ContinuousProcess template <class T> class Continuous<T, true> : public detail::ExecTimeImpl<T> { private: diff --git a/Processes/AnalyticProcessors/ImplDecay.h b/Processes/AnalyticProcessors/ImplDecay.h index 786b1a951ae251b0a53f431d0bf67d1e6f661c3e..b514c835474250b0f529ad5c0c0c9c86e121a7f2 100644 --- a/Processes/AnalyticProcessors/ImplDecay.h +++ b/Processes/AnalyticProcessors/ImplDecay.h @@ -18,12 +18,15 @@ namespace corsika::process { class ExecTimeImpl; } + /// Base for Decay Implementation template <class T, bool TCheck> class Decay; + /// Specialisation if class is not DecayProcess template <class T> class Decay<T, false> {}; + /// Specialisation if class is a DecayProcess template <class T> class Decay<T, true> : public detail::ExecTimeImpl<T> { private: